東京―新大阪間の新幹線加速度をLinkingを使って計測する

こんにちは、やましんです。
以前[タンジブルユーザーインターフェースをLinkingで挑戦](http://qiita.com/yamashin/items/3bf689dc0b650424b820)で紹介した、ブルートゥース搭載の加速度センサーを使用して、新幹線の東京―新大阪間の加速度を計測してみました。
　今回は計測期間は2時間半程度と比較的短く、途中トンネルなどあるのでローカルでログを収集しましたが、
データをサーバーで受け取りたい方のために、PHPとmysqlで受け取る方法も後半に紹介します！


#新幹線　東京―新大阪間の加速度の変化のグラフ
収集した加速度（X軸、Y軸、Z軸）をグラフにしたものがこちら。
![加速度グラフ.png](https://qiita-image-store.s3.amazonaws.com/0/175188/ae2e2d6a-829b-d831-3df8-6b18cf7d0de7.png)
上の青いグラフはX軸、中央オレンジのグラフはY軸、下の緑のグラフはZ軸です。
X軸、Y軸は0を中心に振幅している。
Z軸は1を中心に振幅していることから、このセンサーの加速度の単位はG（重力加速度）を返却しているようだ。つまり、１は9.80665 m/s^2ということ。
21:10頃、Sizukux6が振動で回転していることに気付いたため、向きを手動で補正しました。
また、途中（時間軸22:28～22:42の間）に空白の領域がありますが、寝落ちしてました。すみません。


#準備したもの
ローカルでログ収集する場合に必要な環境はこちら。
- [Linking Android SDK](https://linkingiot.com/developer/api.html)
- [Linking アプリ（Google Playからダウンロード）](https://play.google.com/store/apps/details?id=com.nttdocomo.android.smartdeviceagent&hl=ja)
- [Sizuku6x](http://www.braveridge.com/PressRelease/Sizuku.pdf)
- スマホ（SC-01H/Androidバージョン5.1.1）
- パソコン（ログ収集用）
- 新幹線チケット

さらに、サーバーに加速度データをアップする場合に必要なサーバー環境はこちら。

- CentOS7
- PHP v2.5.0
- mysql  Ver 14.14 Distrib 5.5.54

#のぞみ425号が6分遅れで発車
慌てて、のぞみ425号に乗り込み、急いで機材を準備していると「緊急停止ボタンが押されたので点検中。しばらくお待ちください」の車内アナウンス。これでゆっくり準備ができる。ふーっ、なんとか間に合った。
![のぞみ425.jpg](https://qiita-image-store.s3.amazonaws.com/0/175188/58045803-f5b8-95df-29b0-5e05369da369.jpeg)


![20170414_203511.jpg](https://qiita-image-store.s3.amazonaws.com/0/175188/052afdc2-fedb-db2b-4e7f-dad698c66d87.jpeg)
Sizuku6xの設置の様子。

#Android側プログラミング
Linkingを使用してSizuku6xから加速度データを取得します。
デバイスの初期化やセンサー情報のリクエストについては[タンジブルユーザーインターフェースをLinkingで挑戦](http://qiita.com/yamashin/items/3bf689dc0b650424b820)を参照してください。
今回はControlSensorDataクラスのsetInterval()メソッドの引数に1000msを指定して、1秒単位の加速度を受け取った。

##加速度を取得するためのレシーバー定義
　Linkingを使うとBluetoothを意識しなくてよいので簡単。加速度センサーの値を受け取るメソッドonSensorData()で、X、Y、Z軸方向の加速度を取得して、ログに出力する。このタイミングでPOST通信を実施すれば、サーバーに加速度をアップできますね。

```Android:LightDemoActivity.java
    class SensorReceiver implements ControlSensorData.SensorDataInterface {

        String bd;
        int type;
        float x;
        float y;
        float z;
        byte[] originalData;

        @Override
        public void onStopSensor(final String bd, int type, int reason) {
            Toast.makeText(LightDemoActivity.this, "センサ情報の取得を停止しました", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onSensorData(String bd, int type, float x, float y, float z,
                                 byte[] originalData, long time) {

            this.bd = bd;
            this.type = type;
            this.x = x;
            this.y = y;
            this.z = z;
            this.originalData = originalData;

            //ローカルでデータを収集する場合はログ出力のみでOK
            Log.d(TAG, "[" + bd + "] のデータ[type:" + type + "]を受信 " + "timeStamp:" +  getNowDate() + ", x:" + x + ", y : " + y +", z : " + z);

            //★★サーバーにデータをアップロードする場合はここでPOST通信を記述してください。★★
            // http://YOUR_SERVER_ADDRESS/postAcceleration.php?x=0.1&y=0.3&z=1.0            
        }


    }
```



#サーバー側プログラミング
下記の形式でリクエストされた加速度を保存します。

postAcceleration.php?x=0.1&y=0.3&z=1.0

PHPを使用してX,Y,Z軸の加速度を受け取り、mysqlに保存する場合の処理は下記の通りです。

```php:postAcceleration.php
<?php

$server = 'YOUR SERVER NAME';
$username = 'YOUR USER NAME';
$password = 'YOUR PASSWPRD';
$database = 'YOUT DATABASE NAME';


function quote_smart($value)
{
    if (!is_numeric($value)) {
        $value = "'" . mysql_real_escape_string($value) . "'";
    }
    return $value;
}

function param_check_acceleration($value){
    return preg_match('/^[+-]?(\d*\.\d+|\d+\.?\d*)/',$value);
}


function set_sql_parameters($html_parameter_list,&$sql_parameter_list){
    foreach( $html_parameter_list as $table => $html_p )
    {
        $sql_p = array();
        foreach( $html_p as $key => $array )
        {
            if($array[0] === 'required'){
                if(isset($_GET[$key]) and !is_array($_GET[$key]) and $_GET[$key] != '' and !empty($_GET[$key]) and $array[1]($_GET[$key]) === 1){
                    $sql_p += array($key=>quote_smart($_GET[$key]));
                }else{
                    unset($sql_p);
                    break;
                }
            }else{
                if( isset($_GET[$key]) and !is_array($_GET[$key]) and $_GET[$key] != '' and $array[1]($_GET[$key]) === 1){
                    $sql_p += array($key=>quote_smart($_GET[$key]));
                }
            }
        }
        if(isset($sql_p) and count($_GET) == count($sql_p) and count($_GET) != 0){
            $sql_parameter_list = $sql_p;
            return $table;
        }
    }
    exit();
}

function insert($con,$table,$fields)
{
    $sql = 'INSERT INTO '.$table;
    $sql .= '(';
    $sql .= implode( ',', array_keys($fields) );
    $sql .= ')';
    $sql .= 'VALUES(';
    $sql .= implode( ',', $fields );
    $sql .= ')';
    $result_flag = mysqli_query($con,$sql);
    if (!$result_flag) {
        exit();
    }
}


$acceleration_html_params = array(
    'x' => array('required','param_check_acceleration'),
    'y' => array('required','param_check_acceleration'),
    'z' => array('required','param_check_acceleration'),
    );

$html_params_list = array(
    'acceleration' => $acceleration_html_params,
    );


$sql_parameter = array();

$con = mysqli_connect($server, $username, $password);
if (!$con) {
    exit();
}

$table = set_sql_parameters($html_params_list,$sql_parameter);

if($table === ''){
    exit();
}

$db_selected = mysqli_select_db($con, $database);
if (!$db_selected){
    exit();
}

insert($con,$table,$sql_parameter);

mysqli_close($con);
?>

```


set_sql_parameters()は取得したパラメータをチェックする関数。
\$acceleration_html_paramsは受け取り可能なHTMLパラメータと、それぞれのパラメータをバリデーションチェックするための関数を定義する。
x,y,zのパラメータ値のバリデーションチェックは同じでparam_check_acceleration()で実施します。
$html_params_listはHTMLパラメータリストとmysqlテーブル名との関連を定義している。
insert()では、取得したパラメータ値とテーブル名を入力して、INSERT用のSQL文を作成し実行している。

#今後の展開
加速度以外にも[Linkingを使用したデバイス](https://linkingiot.com/devices.html)が世の中には結構あるようなので、
ボタン系とか、温度・湿度センサーとか試してみます。