Check! Bluemix で IBM IoT Foundation のデータを可視化しよう！（リアルタイムと履歴表示）

こんにちは、[cloudpack][] の @dz_ こと[大平かづみ][]です。

Prologue - はじめに
====
Bluemix のドキュメント「[IoT サンプル - データの可視化](https://www.ng.bluemix.net/docs/services/IoT/index-gentopic1.html#iot200 "IoT サンプル - データの可視化 | Bluemix")」に、[IBM Internet of Things Foundation](https://internetofthings.ibmcloud.com/ "IBM Internet of Things Foundation") (以下、IoT Foundation または IoTF ) のデータを可視化する方法が紹介されていたので試しました。

IoT Foundation のデータをどう扱うのかの見本にもなり、ちょうどよかったです。

以下は、ざっくりですが使用した際のメモです。参考になればさいわいです。

サンプルアプリ IoT Visualization
====
このドキュメントでは、 [IoT Visualization](https://github.com/ibm-messaging/iot-visualization/ "ibm-messaging/iot-visualization") という Node.jsアプリケーションを使って、 IoTF のデータを表示します。

- リアルタイムのグラフ表示
- 過去ログのグラフ表示

IoTF のデータはAPI や MQTT で提供されており、**Bluemix のダッシュボードからバインドすることでアクセストークンを紐付けてくれます。** (便利！) また、別途アクセストークンを発行してそれを利用することもできます。

取得したデータは、javascriptでグラフ描画します。

| データの種類 | 取得方法 |
|-------------|---------|
| リアルタイム | MQTT    |
| 過去ログ     | HTTPS   |

IoT Foundation からのデータ取得の方法
====
IoT Foundation からデータを取得するには、https ベースの API や、MQTT が使えます。

Internet of Things Foundation API を利用する
----
[Internet of Things Foundation API](https://docs.internetofthings.ibmcloud.com/ja/api/api_intro.html "Internet of Things Foundation API の概要 — IBM IoT Foundation 1.0 ドキュメント") は、IoTF に登録されたデバイスの管理やデータ・診断情報の管理、IoTFの組織に関する情報の取得などができます。

現在は **[バージョン 2](https://docs.internetofthings.ibmcloud.com/swagger/v0002.html "IoT Foundation API バージョン 2")** がサポートされています。

バージョン 1 も引き続きサポートすると書かれていますが、正常に動作しない場合があるのでご注意ください。実際に、[ドキュメント](https://www.ng.bluemix.net/docs/services/IoT/index-gentopic1.html#iot200 "IoT サンプル - データの可視化 | Bluemix")に従ってダウンロードしたサンプルアプリではAPIがバージョン1で動かず、リポジトリからバージョン2に対応したソースコードを取得して対応しました。

MQTT で接続する
----

MQTT については、「[メッセージング](https://docs.internetofthings.ibmcloud.com/ja/index.html#/messaging#messaging "メッセージング - 概要 — IBM IOT Foundation 1.0 ドキュメント")」に記載されています。

アプリケーションから MQTT に接続してパブリッシュ、サブスクライブする詳細については「[MQTT アプリケーション接続](https://docs.internetofthings.ibmcloud.com/ja/messaging/applications.html "MQTT アプリケーション接続 — IBM IOT Foundation 1.0 ドキュメント")」を参照ください。

導入方法
====

大まかな流れ
----
1. [IoT Visualization](https://github.com/ibm-messaging/iot-visualization/ "ibm-messaging/iot-visualization") の IoTF API v2 に対応したソースコードを入手する
2. Bluemix で Node.js のアプリを作成する
3. 2.で作成したアプリに IoTFサービスをバインドする
4. ソースコードを展開する
5. 動作確認

実際の手順
====

今回は手っ取り早く進めるために、[DevOps サービス](https://hub.jazz.net/ "Bluemix DevOps Services") を利用します。

なお、Bluemix のだいたいの操作感や、Node.js と Express で構成されたアプリケーションが理解できる知識がある前提で手順を書きます。ご了承くださいませ。

1. IoT Visualization のソースコードを入手する
----
[Release IBM IOT Foundation Cloud Registered Devices Visualization Sample v0.2.0](https://github.com/ibm-messaging/iot-visualization/releases/tag/v0.2.0 "Releases · ibm-messaging/iot-visualization") から、IoTF API v2 に対応したソースコードを取得します。 

のちほど DevOps サービスにアップロードするときに便利なので、**zip 形式**の方を取得してください。(例: `iot-visualization-0.2.0.zip`)

2. Bluemix で Node.js アプリを作成する
----
Bluemix ダッシュボードから 「Cloud Foundry アプリ」作成に進み、「WEB」を選択してください。
![2015127_bluemix_001.png](https://qiita-image-store.s3.amazonaws.com/0/3812/d7c6cab9-ea5a-eb72-baf9-ae6c9389b60a.png)

Node.js アプリを選び、任意のアプリ名を入力して作成します。
![2015127_bluemix_002.png](https://qiita-image-store.s3.amazonaws.com/0/3812/5b0137e0-73a7-85dc-f8c1-e0d7b6394e32.png)

3. IoTFサービスをバインドする
----
アプリケーションが起動したら、アプリのダッシュボードから IoTFサービスをバインドします。
![2015127_bluemix_004.png](https://qiita-image-store.s3.amazonaws.com/0/3812/d6643e3f-0b1f-acda-5cc1-3ac779eced43.png)

4. ソースコードを展開する
----
アプリのダッシュボードの画面右上にある「GITの追加」から、DevOpsサービスを作成します。
![2015127_bluemix_005.png](https://qiita-image-store.s3.amazonaws.com/0/3812/29019d7b-69dd-2afc-eff2-21de08679141.png)

完了したら、同じく画面右上の「コードの編集」をクリックして、DevOpsサービスのコード編集画面へ移動します。

「ファイル」>「インポート」>「ファイルまたは.zipアーカイブ」を選択して、`iot-visualization-0.2.0.zip` をアップロードし、指示に従い unzip します。
![2015127_bluemix_006.png](https://qiita-image-store.s3.amazonaws.com/0/3812/b4289bc1-be7a-51b7-e44e-26dca96146ee.png)

unzip 直後はこのようなファイル構成になります。
![2015127_bluemix_007.png](https://qiita-image-store.s3.amazonaws.com/0/3812/9b4cb768-e6e6-235f-2d50-e08427a233ac.png)

そして、アプリケーションが動くように調整します。ここでは `iot-visualization-0.2.0` 配下をアプリケーションとして実行するように調整します。（本来は、適宜マージしてください～）最小限の調整で稼働させるにはこれ↓だけでよさそうです。
![2015127_bluemix_008.png](https://qiita-image-store.s3.amazonaws.com/0/3812/2decf03a-13f7-e741-d0e9-1bf0153e7873.png)

```diff:package.json(参考)
{
  "name": "NodejsStarterApp",
  "version": "0.0.1",
  "description": "A sample nodejs app for Bluemix",
  "scripts": {
-   "start": "node app.js"
+   "start": "node iot-visualization-0.2.0/app.js"
  },
	"dependencies": {
-   "express": "4.12.x",
-   "cfenv": "1.0.x"
+   "express": "~4.2.0",
+   "serve-favicon": "~2.1.0",
+   "morgan": "~1.0.0",
+   "cookie-parser": "~1.0.1",
+   "body-parser": "~1.0.0",
+   "debug": "~0.7.4",
+   "jade": "~1.3.0",
+   "stylus": "0.42.3",
+   "express-session": "^1.8.1"
  },
  "repository": {},
  "engines": {
    "node": "0.12.x"
  }
}
```

調整が終わったら、画面上部のデプロイアイコンから、アプリケーションをデプロイしてください。

5. 動作確認
----
デプロイが終わったらアプリケーションみてみましょう！
![2015127_bluemix_009.png](https://qiita-image-store.s3.amazonaws.com/0/3812/61b888f1-eca2-bfef-2693-17b8de047a00.png)

しかし、アプリケーションを開くと、いくつかエラーが出ているかと思います…(;´･ω･) `https://` ではなく `http://` でアプリを開くことでエラーは抑えられます。(https で使えるほうがよいので確認中です。）

私の場合、作業時にIoTのモノを動作させてなかったので、過去データを見てみることにします。

デバイスを選択します。
<img width="1031" alt="20151225_bluemix-iotf_002.png" src="https://qiita-image-store.s3.amazonaws.com/0/3812/229c3622-5e80-0c40-5a00-58b8a8bbf537.png">

過去データを選択し、表示条件を設定するとグラフが表示さます！(/・ω・)/
<img width="1123" alt="20151225_bluemix-iotf_003.png" src="https://qiita-image-store.s3.amazonaws.com/0/3812/dada81ac-46e0-20d2-70ac-e1b13987514d.png">

ただし、おそらくここでグラフは表示されない方は… データ構造の不一致による不具合であればデバッグして修正したので、トラブルシューティングをご参照ください〜


トラブルシューティング
====
Historic Data のグラフが表示されない（データの数字(文字列)を認識しない）
----

IoTデータのパース処理で、値が数値でない場合は扱わないようになっていました。

私のデータ構造では、センサデータの値も "数字" (文字列) で送ってしまっていたので、数字も数値として認識するよう修正しました。私のデータに合わせてるので参考程度にご覧ください。

```diff:public/js/historian/historianGraph.js
this.displayHistChart = function(device,histData){

	var seriesData = [];
	var counter = 0;
	var data = histData.events;
	
	for(var i = data.length-1 ; i>=0 ;i-- ){	
   		var key = 0;	
		for (var j in data[i].evt){
+　			// 数値である場合（"数字"も含める）
-　			if (typeof data[i].evt[j] !== 'string') {
+			if (typeof data[i].evt[j] !== 'string' || isNaN(parseFloat(data[i].evt[j])) === false) {
				if(i===data.length-1){
					seriesData[key]={};
					seriesData[key].name=j;
					seriesData[key].color = this.palette.color();
					seriesData[key].data=[];	
				}
				
				seriesData[key].data[counter]={};
+　				// 数値に変換
-				seriesData[key].data[counter].x = data[i].timestamp.$date/1000;// timestamp;
-				seriesData[key].data[counter].y = data[i].evt[j];
+				seriesData[key].data[counter].x = parseFloat(data[i].timestamp.$date/1000);// timestamp;
+				seriesData[key].data[counter].y = parseFloat(data[i].evt[j]);
			
				key++;
			}
		}
		
		counter++;
	}	
	this.drawGraph(seriesData);
	
};
```
<img width="936" alt="20151225_bluemix-iotf_001.png" src="https://qiita-image-store.s3.amazonaws.com/0/3812/64737b45-c71f-33a2-50ec-bcb5575f155b.png">
(※実験でカウントアップするだけのデータを送っているので、ただただ右肩上がりのグラフです。)

Live Data のグラフが表示されない（データの数字(文字列)を認識しない）
----

Live Data も試したところ、上記と同じ状況でデータが表示されなかったので、数字も数値にパースするように調整しました。

```diff:public/js/realtime/realtimeGraph.js
this.graphData = function(data)
{
  
  var key = 0;
  var seriesData = [];
  var timestamp = Date.now()/1000;
  var maxPoints = 25; 
  for (var j in data.d)
  {
-   if (typeof data.d[j] !== 'string') {
+   if (typeof data.d[j] !== 'string' || isNaN(parseFloat(data.d[j])) === false) {
-   this.graph.series[key].data.push({x:timestamp,y:data.d[j]});
+   this.graph.series[key].data.push({x:timestamp,y:parseFloat(data.d[j])});
    if (this.graph.series[key].data.length > maxPoints)
    {
      this.graph.series[key].data.splice(0,1);//only display up to maxPoints
    }
    key++;
  }
  }
  this.graph.render();	
}

this.displayChart = function(device,data){

  var key = 0;
  var seriesData = [];
  var timestamp = Date.now()/1000;
  for (var j in data.d)
  {
-   if (typeof data.d[j] !== 'string') {
+   if (typeof data.d[j] !== 'string' || isNaN(parseFloat(data.d[j])) === false) {
      seriesData[key]={};
      seriesData[key].name=j;
      seriesData[key].color = palette.color();
      seriesData[key].data=[];
  
      seriesData[key].data[0]={};
      seriesData[key].data[0].x = timestamp;
-     seriesData[key].data[0].y = data.d[j];
+     seriesData[key].data[0].y = parseFloat(data.d[j]);
      key++;
    }
  }

  this.drawGraph(seriesData);
}
```

これで、リアルタイムのグラフも表示されます。
![2015127_001.png](https://qiita-image-store.s3.amazonaws.com/0/3812/fba8b233-70c1-5492-9502-03493e2abc86.png)

ボタン押したのがリアルタイムにグラフに表示されるので、ちょっと感動です！

Epilogue - 終わりに
====
APIのバージョンと、データ構造に気をつければ、いとも簡単に IoT のデータを可視化することができました！

実感が湧いていいですね～！(/・ω・)/

[cloudpack]:https://cloudpack.jp/ "cloudpack（クラウドパック） 400社を超える導入実績! EC2などAWSクラウドの導入設計、構築、運用保守サービス"
[cloudpack-blog]:http://blog.cloudpack.jp/ "cloudpack技術情報サイト"
[大平かづみ]:http://blog.cloudpack.jp/author/oohira/ "大平かづみの記事一覧"