Raspberry PiからMindSphereへ (5)Raspberry Piからアップロードする


# オムロン環境センサからデータを取得する
オムロン環境センサの使い方を簡単に紹介します。
今回は温度情報(とついでにその他情報)だけを取得しましょう。

まずお持ちの環境センサのBDアドレス(≒MACアドレス)を調べてください。デバイスの購入時に箱の中にシールに記載されて入っていると思います。
もしそれがなければ、まず環境センサをUSBポートに接続して、Androidスマホはお持ちなら[BLEスキャナー](https://play.google.com/store/apps/details?id=com.macdom.ble.blescanner&hl=ja)のようなスキャナツールを利用して、「Rbt」という名前のついたペリフェラルを探してください。それが環境センサです(ただしEnvの場合もあるようです)。
名前の下に出るE4:12:A5:39:13:67のような16進数がBDアドレスです。

Raspberry Piのターミナル(LXTerminal)を開いて以下のようにgatttoolを実行してください。

```bash
gatttool -t random -b {BDアドレス} --char-read --handle=0x0059
```
するとキャラクタリスティクスの値が取得できるでしょう。

```bash
Characteristic value/descriptor: 23 ed 09 95 0e ae 00 c8 98 0f 00 2e 1d 03 00 a6 01
```

後半の「23 ed 09 95 0e ae 00 c8 98 0f 00 2e 1d 03 00 a6 01」というのが、気温やら湿度やらのデータとなっています。16進数ですがリトルエンディアンで10進数に変換します。
リトルエンディアン変換は例えば以下のサイトなどで調べてみてください。
[16進法とリトルエンディアンの変換](http://web.save-editor.com/tool/wse_hex.html)

上記のデータを元に十進数に直すと以下のようになります。

| 取得値   | 内容           | 解析値  | 単位      |
|----------|----------------|---------|-----------|
| 23       | シーケンス番号 | 35      | -         |
| ed09     | 温度           | 2541    | 0.01 degC |
| 950e     | 湿度           | 3733    | 0.01 %RH  |
| ae00     | 照度           | 174     | 1 lx      |
| c8980f00 | 気圧           | 1022152 | 0.001 hPa |
| 2e1d     | 騒音           | 7470    | 0.01 dB   |
| 0300     | eVTOC          | 3       | 1 ppb     |
| a601     | eCO2           | 422     | 1 ppm     |



これでキャラクタリスティクスの値から気温その他の情報が取得できました！

# PHPでAPIコールする
ここからはほぼ前回と同じAPIコールをPHP CLI経由で実行します。
Raspberry PiにPHPがインストールされていなければインストールしておいてください。
今回はPHPで書きましたが、自分の得意な言語でもAPIコールはできますので、前回と同じものですが、根本的なポイントだけ以下に抜粋しておきます。

| 項目        | 内容                                                                                   |
|-------------|----------------------------------------------------------------------------------------|
| Req Header1 | Content-Type: application/json                                                         |
| Req Header2 | Authorization:Bearer {認可トークン}                                             |
| メソッド        | PUT                                                                                    |
| URL         | https://gateway.eu1.mindsphere.io/api/iottimeseries/v3/timeseries/{Asset ID}/rasPiData |

リクエストボディは以下のようにします。

```json
[
		{
		  "_time": "2019-02-27T02:33:35.000Z",
		  "temperature":23.4
		}
]
```

以下はその実装例です。
まずAPIテスターかPostmanで認可トークンを取得しておいてください。
定数TOKENにその認可トークンを設定し、Asset IDも書き換えてください。
それをapi.phpなどと名前をつけてローカルのどこかに保存し、
ターミナルから`php api.php`と実行すればOKです。
成功すれば約10秒ごとにsuccessと表記されます。


```php
<?php

/**
 * MindSphere・オムロン環境センサ用サンプルコード
 */

// 認可トークン
define("TOKEN","eyJhbGciOi");

//アセットID
define("ASSET_ID","6a85dfe94ccd4415");

// アスペクト名
define("ASPECT","rasPiData");


    // メインの繰り返し処理
    while(true){
        $param = makeUploadData();

        $res = setData($param);
        if ($res == true)
            print "success\n";
        else 
            print "fail! \n";

        sleep(10);
    }


    /**
     * setData
     * 
     * @param String $param     Assetに登録したいJSONデータ
     */
    function setData($param){
		// 時系列APIのURL
		$aspect_url = "https://gateway.eu1.mindsphere.io/api/iottimeseries/v3/timeseries" . "/" . ASSET_ID . "/" . ASPECT;


        // 必要な要素をまとめる
        $header = [];
        $header[] = "Content-Type:application/json";
        $header[] = "Authorization:Bearer ".TOKEN;
        $method = "PUT";
    
        list($arr,$info) = exeCurl($aspect_url,$header,$method,$param);
        if ($info["http_code"] == 204) {
            return true;
        } else {
            print "Error code : " . $info["http_code"] . "\n";
            return false;
        }
    
    
    }


    /**
     * cURL実行
     */
    function exeCurl($url,$header,$method,$param){
    
    
        // cURLセッションを初期化
        $ch = curl_init();
    
        curl_setopt($ch, CURLOPT_URL, $url); // 取得するURLを指定
    
        // cURLのその他設定
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果を文字列で返す
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // サーバー証明書の検証を行わない
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // リクエストにヘッダーを含める
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); // methodの指定
    
    
        //リダイレクト関係
        //Locationをたどる
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true);
        //最大何回リダイレクトをたどるか
        curl_setopt($ch,CURLOPT_MAXREDIRS,30);
        //リダイレクトの際にヘッダのRefererを自動的に追加させる
        curl_setopt($ch,CURLOPT_AUTOREFERER,true);
    
		// リクエストボディ
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
    
    
        // URLの情報を取得
        $response =  curl_exec($ch);
        $arr = json_decode($response,true);
    
        $information = curl_getinfo($ch);
    
    
        // セッションを終了
        curl_close($ch);
    
        return [$arr,$information];
    
    }


	/**
	 * アップロード用データ作成
	 */
	function makeUploadData(){
		// 環境データを取得
		list($tempe,$hum,$illum,$atm,$dB,$eTVOC,$eCO2) = getEnvData();

		// 現在時刻の所得
		$dt = new DateTime();
		$dt->setTimeZone(new DateTimeZone('UTC'));
		$date =  $dt->format('Y-m-d\TH:i:s.\0\0\0\Z');

		$param = <<<PARAM
[
		{
			"_time": "$date",
			"temperature":$tempe
		}
]
PARAM;
		return $param;
	}
	/**
	 * getEnvData
	 * @param none
	 * @return Array 環境データ7種
	 */
	function getEnvData(){

		$str="";
		$count=0;
		while(true) {
			$str = exec("gatttool -t random -b F8:ED:D7:44:AC:E9 --char-read --handle=0x0059");
			if (strpos($str,"descriptor") !== false)
				break;

			if ($count > 10) {
				print "データ取得に失敗しました";
				$str = "Characteristic value/descriptor: b3 9e 0a e0 09 83 01 70 5b 0f 00 bd 19 02 00 9f 01 ";
				break;
			}
			$count++;
		}
		
		$hex = explode(" ",trim(explode(":",$str)[1]));

		$tempe = hexdec($hex[2] . $hex[1]) * 1/100;//温度(temperature) degC
		$hum = hexdec($hex[4] . $hex[3]) * 1/100;//湿度(humidity)%RH
		$illum = hexdec($hex[6] . $hex[5]) ;//照度(illumination)1 lx
		$atm = hexdec($hex[10] . $hex[9] . $hex[8] . $hex[7]) * 1/1000;//気圧(atmospheric pressure)1 hPa
		$dB = hexdec($hex[12] . $hex[11]) * 1/100;//騒音(dB)
		$eTVOC = hexdec($hex[14] . $hex[13]) ;//eTVOC(VOCにカテゴライズされるガス種の濃度、ホルムアルデヒドやアルコール、タバコの煙)ppb
		$eCO2 = hexdec($hex[16] . $hex[15]) ;//eCO2（equivalent CO2）値は、TVOC値から算出される二酸化炭素濃度相当値であり、二酸化炭素濃度を直接検出ではない(1ppm)

		return [$tempe,$hum,$illum,$atm,$dB,$eTVOC,$eCO2];
	}



```


# 終わりに
長かったRaspberry PiからMindSphereへのデータアップロードが出来ました！
APIを使うのは実装にやや手間がかかりますが、ある程度自由度があるという利点があります。

また認可トークンの取得は自動化できますので、サービス・クレデンシャルさえあれば期限をきにしなくてもいいでしょう。
それに対してデバイスをオンボードする方法は、データポイントの設定などがやや手間です。イニシャル・アクセス・トークンの取得などはAPIで可能ですが、個人的には今回紹介したやり方のほうがスッキリしていると思います。

以上、MindSphereの利用の参考になれば幸いです。




# 参考
 [Howto : 「オムロン 環境センサ」からBLE GATTを用いてデータ収集](https://armadillo.atmark-techno.com/howto/armadillo_2JCIE-BU01_GATT)