こんにちは、cloudpack の @dz_ こと大平かづみです。
Prologue - はじめに
Bluemix のドキュメント「IoT サンプル - データの可視化」に、IBM Internet of Things Foundation (以下、IoT Foundation または IoTF ) のデータを可視化する方法が紹介されていたので試しました。
IoT Foundation のデータをどう扱うのかの見本にもなり、ちょうどよかったです。
以下は、ざっくりですが使用した際のメモです。参考になればさいわいです。
サンプルアプリ IoT Visualization
このドキュメントでは、 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 は、IoTF に登録されたデバイスの管理やデータ・診断情報の管理、IoTFの組織に関する情報の取得などができます。
現在は バージョン 2 がサポートされています。
バージョン 1 も引き続きサポートすると書かれていますが、正常に動作しない場合があるのでご注意ください。実際に、ドキュメントに従ってダウンロードしたサンプルアプリではAPIがバージョン1で動かず、リポジトリからバージョン2に対応したソースコードを取得して対応しました。
MQTT で接続する
MQTT については、「メッセージング」に記載されています。
アプリケーションから MQTT に接続してパブリッシュ、サブスクライブする詳細については「MQTT アプリケーション接続」を参照ください。
導入方法
大まかな流れ
- IoT Visualization の IoTF API v2 に対応したソースコードを入手する
- Bluemix で Node.js のアプリを作成する
- 2.で作成したアプリに IoTFサービスをバインドする
- ソースコードを展開する
- 動作確認
実際の手順
今回は手っ取り早く進めるために、DevOps サービス を利用します。
なお、Bluemix のだいたいの操作感や、Node.js と Express で構成されたアプリケーションが理解できる知識がある前提で手順を書きます。ご了承くださいませ。
- IoT Visualization のソースコードを入手する
Release IBM IOT Foundation Cloud Registered Devices Visualization Sample v0.2.0 から、IoTF API v2 に対応したソースコードを取得します。
のちほど DevOps サービスにアップロードするときに便利なので、zip 形式の方を取得してください。(例: iot-visualization-0.2.0.zip
)
- Bluemix で Node.js アプリを作成する
Bluemix ダッシュボードから 「Cloud Foundry アプリ」作成に進み、「WEB」を選択してください。
Node.js アプリを選び、任意のアプリ名を入力して作成します。
- IoTFサービスをバインドする
アプリケーションが起動したら、アプリのダッシュボードから IoTFサービスをバインドします。
- ソースコードを展開する
アプリのダッシュボードの画面右上にある「GITの追加」から、DevOpsサービスを作成します。
完了したら、同じく画面右上の「コードの編集」をクリックして、DevOpsサービスのコード編集画面へ移動します。
「ファイル」>「インポート」>「ファイルまたは.zipアーカイブ」を選択して、iot-visualization-0.2.0.zip
をアップロードし、指示に従い unzip します。
そして、アプリケーションが動くように調整します。ここでは iot-visualization-0.2.0
配下をアプリケーションとして実行するように調整します。(本来は、適宜マージしてください~)最小限の調整で稼働させるにはこれ↓だけでよさそうです。
{
"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"
}
}
調整が終わったら、画面上部のデプロイアイコンから、アプリケーションをデプロイしてください。
- 動作確認
しかし、アプリケーションを開くと、いくつかエラーが出ているかと思います…(;´・ω・) https://
ではなく http://
でアプリを開くことでエラーは抑えられます。(https で使えるほうがよいので確認中です。)
私の場合、作業時にIoTのモノを動作させてなかったので、過去データを見てみることにします。
過去データを選択し、表示条件を設定するとグラフが表示さます!(/・ω・)/
ただし、おそらくここでグラフは表示されない方は… データ構造の不一致による不具合であればデバッグして修正したので、トラブルシューティングをご参照ください〜
トラブルシューティング
Historic Data のグラフが表示されない(データの数字(文字列)を認識しない)
IoTデータのパース処理で、値が数値でない場合は扱わないようになっていました。
私のデータ構造では、センサデータの値も "数字" (文字列) で送ってしまっていたので、数字も数値として認識するよう修正しました。私のデータに合わせてるので参考程度にご覧ください。
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);
};
Live Data のグラフが表示されない(データの数字(文字列)を認識しない)
Live Data も試したところ、上記と同じ状況でデータが表示されなかったので、数字も数値にパースするように調整しました。
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);
}
ボタン押したのがリアルタイムにグラフに表示されるので、ちょっと感動です!
Epilogue - 終わりに
APIのバージョンと、データ構造に気をつければ、いとも簡単に IoT のデータを可視化することができました!
実感が湧いていいですね~!(/・ω・)/