Node-RED ダッシュボードでサーマルカメラの温度をグラフ描画

# Node-REDのダッシュボード

Node-REDはIoT向きと言われておきながら、意外とモニタリング用のリアルタイム グラフ表示の話がそっちのけになっている気がしておりました。そんな中、3ヶ月くらい前にNode-REDのmailing listでdashboardがリリースされたことを知り、早速使って見ようと思い早速作ってみました。ここで書いている内容はその時に作った内容ですが、あんまりdashboardも取り上げられていなかったので思い起こしながら書いてみました。

dashboardのgithubは[ここ](https://github.com/node-red/node-red-dashboard)にありますので、詳しい使い方はこちらを御覧ください。
また本内容はBluemix版のNode-REDに準拠しているので、予めご了承ください。

<img width="300" alt="687474703a2f2f6e6f64657265642e6f72672f696d616765732f64617368626f617264642e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/106468/6a037da3-81f4-4c92-448d-68a3e325adb0.png">

# Node-REDのダッシュボードを使うには

Node-REDのダッシュボードはNode-RED(ここではBluemix版を指していますが)最初から有効になっていません。以下のような感じで、package.jsonファイルにdashbordのモジュールを追記し、再デプロイを行います。
そんな人はあまりないと思いますが、**dashboardはNode-REDのversion 1.4以降対応**ですので、もしpackage.jsonで古いバージョンを指定している人はこの際「latest」で指定してしまうか、Productionな人は「1.5x」や固定バージョンで指定しましょう。
そして更にそんな人はいないかもしれませんが、**「node-red-contrib-ui」のモジュールとコンフリクト**しますので、上記githubの内容を参考にしてマイグレーションするようにしてください（アンインストールが必要です）。

```package.json
{
    "name"         : "node-red-bluemix",
    "version"      : "0.4.25",
    "dependencies": {
        "when": "~3.x",
        "mongodb": "~1.4.x",
        "nano": "~5.11.0",
        "cfenv":"~1.0.0",
        "feedparser":"~0.19.2",
        "redis":"~0.10.1",
        "node-red": "latest",    <-ここのバージョンにも注意
        "node-red-bluemix-nodes":"latest",
        "node-red-node-watson":"latest",
        "node-red-node-openwhisk":"latest",
        "node-red-node-cf-cloudant":"latest",
        "node-red-contrib-scx-ibmiotapp":"0.x",
        "node-red-contrib-ibmpush":"0.x",
        "node-red-contrib-bluemix-hdfs":"0.x",
        "node-red-nodes-cf-sqldb-dashdb":"0.x",
        "node-red-dashboard":"latest"  <-これ。「,」に注意。
    },
    "engines": {
        "node": "0.12.x"
    }
}
```

再デプロイを行って起動が完了すると、Node-REDのパレットに次のようなアイコンが追加されているはずです。

![dashboard_icon.png](https://qiita-image-store.s3.amazonaws.com/0/106468/a2229c22-6e88-9a19-f539-ea4eb612e090.png)

# リアルタイムに描画するグラフの元ネタを構成する

今回リアルタイムにグラフを描く際に対象となる元ネタは**「FLIR AX8」という、ちょっとマイナーなサーマルカメラ**です。カメラ機能を利用した「機器監視ソリューション」という表現が正しいカメラですが、普通に「監視カメラ」としても、絶対温度を計測する「サーマルカメラ」としても利用できます。
そしてまだオープンにはなっていないようですが、**ちょっとゴニョゴニョ**するだけでAX8から温度データを取得することが可能になりました。詳しくはFLIR社のご担当者の方にご確認ください。

**[FLIR AX8](http://www.flir.jp/automation/display/?id=65816)**
![AX8.png](http://www.flir.com/uploadedImages/CS_EMEA/Products/AX8/AX8.png)
![AX8_MSX.png](https://qiita-image-store.s3.amazonaws.com/0/106468/3ffa16c7-4505-979d-5e72-ad962b597d7a.png)

## FLIR AX8から温度データをどのように吸い上げるか

上述のとおり、通常の方法では温度データはMODBUS TCPやEthernet/IPのような産業用で使用されるフィールド プロトコルでのみ取得が可能で、一般的なftpやsshのようなプロトコルで取得する方法がありません。
しかし最近の仕様？変更で一般的な方法＋プロトコルで取得できるようになりました。まだまだPushで温度情報を出力できるまでには至っておりませんが、一段間に処理を行うサーバー等を置く事でオンプレのサーバーにも、例えばBluemixなどのクラウド環境にもデータを転送できるようになります。

今回はNode-RED + Bluemixで温度情報を取得するということもあり、折角ですのでIoTらしくMQTTでデータをPutすることにしました。
中間処理のサーバーはpaho + Pythonを使ってMQTT Publisherになってもらい、Node-REDのInternet of Things PlatformのNodeでSubscriberになってもらいました。
以下のコードは温度をPutするコードの一部です。実際にAX8から取得する部分は諸般の事情で省いておりますが、MQTTの部分はまさにこの部分になります。
今回はこのコードを使用して、5秒に一度温度計測データをMQTT経由でNode-REDまでアップロードしています。

```put_temp.pyの一部
class BluemixMQTTClient(object):
    CLIENT_NAME_BASE = "d:%s:%s:%s"
    URL_BASE = "%s.messaging.internetofthings.ibmcloud.com"
    TOPIC = "iot-2/evt/temperature/fmt/json"
    PORT = 1883
    USER = "use-token-auth"

    def __init__(self, org, type, id, token):
        client_name = self.CLIENT_NAME_BASE % (org, type, id)
        url = self.URL_BASE % org

        self.mqttc = paho.Client(client_name)
        self.mqttc.username_pw_set(self.USER, token)
        self.mqttc.connect(url, self.PORT, 60)

    def publish(self, msg):
        self.mqttc.publish(self.TOPIC, self.__make_payload(msg))

    def __make_payload(self, msg):
        return "{\"d\":{\"val\":" + str(msg) + "}}"
```

# IoT Platformを構成する

IoT Platformへのデバイスの登録については他に詳しい記事があると思いますので、ここでは登録後のスナップだけ紹介します。特に特別なことはしておらず、デバイスの登録を行って、トークンのメモなどを行うことになります。

- IoT Platformのデバイス管理画面
![IoT_Dashboard.png](https://qiita-image-store.s3.amazonaws.com/0/106468/612cfdb4-280c-b8a2-c07a-5ea5ee80e629.png)

- IoT Platformのデバイスの設定画面
![IoT_Device.png](https://qiita-image-store.s3.amazonaws.com/0/106468/3d3353d2-d60c-0460-3a02-e2a984f563f7.png)

デバイスの「センサー情報」に上記スクリプトで記載した ``return "{\"d\":{\"val\":" + str(msg) + "}}"`` が、「データ・ポイント」に「d.val」、「値」に現在のAX8で測定している温度が表示されていれば問題ありません。

# Node-REDでフローを作成する

いよいよ本題です。
以下のjsonをインポートすると、下図のフローが表示されるはずです。もし右端の水色のダッシュボード ノードが点線で表示されている場合にはdashboardのモジュールが正常に読み込まれていない可能性がありますので、ログを確認しましょう。

```
[{"id":"247a57b9.6fcb18","type":"ibmiot in","z":"589802f2.d8ea8c","authentication":"boundService","apiKey":"","inputType":"evt","deviceId":"","applicationId":"","deviceType":"+","eventType":"+","commandType":"","format":"json","name":"IBM IoT","service":"registered","allDevices":true,"allApplications":"","allDeviceTypes":true,"allEvents":true,"allCommands":"","allFormats":"","qos":0,"x":90,"y":240,"wires":[["10dac31d.3c3ced"]]},{"id":"10dac31d.3c3ced","type":"function","z":"589802f2.d8ea8c","name":"val2pay","func":"msg.payload = msg.payload.d.val;\n\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":240,"wires":[["cc938aad.ec43c8","16160c73.0cc384","aed4f344.77d4b"]]},{"id":"cc938aad.ec43c8","type":"ui_chart","z":"589802f2.d8ea8c","name":"Thermal Spot #2","group":"a54dd648.313c38","order":3,"width":"6","height":"2","label":"1Day Temp History","chartType":"line","xformat":"%H:%M:%S","interpolate":"linear","nodata":"","ymin":"0","ymax":"40","removeOlder":1,"removeOlderUnit":"86400","x":530,"y":280,"wires":[[],[]]},{"id":"16160c73.0cc384","type":"ui_gauge","z":"589802f2.d8ea8c","name":"","group":"a54dd648.313c38","order":1,"width":0,"height":0,"gtype":"gage","title":"AX8 Spot #1 Temp","label":"C","format":"{{value}}","min":0,"max":"50","colors":["#00b500","#e6e600","#ca3838"],"x":490,"y":320,"wires":[]},{"id":"aed4f344.77d4b","type":"ui_chart","z":"589802f2.d8ea8c","name":"Thermal Spot #1","group":"a54dd648.313c38","order":2,"width":0,"height":0,"label":"1Min Temp History","chartType":"line","xformat":"%H:%M:%S","interpolate":"step-after","nodata":"","ymin":"0","ymax":"40","removeOlder":1,"removeOlderUnit":"60","x":530,"y":240,"wires":[[],[]]},{"id":"a54dd648.313c38","type":"ui_group","z":"589802f2.d8ea8c","name":"Thermal","tab":"49373f0a.fec8e","order":1,"disp":true,"width":"6"},{"id":"49373f0a.fec8e","type":"ui_tab","z":"","name":"Thermal","icon":"dashboard","order":1}]
```

![Node-Thrm.png](https://qiita-image-store.s3.amazonaws.com/0/106468/d69db8f5-4aff-d591-d55a-306d12f94ecb.png)

imbiotノードを編集して、自分の環境に合わせましょう。
ちなみに私はこんな感じの設定になっています。

![Node-RED_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/106468/4f9edadf-f136-afc4-de33-aa1b3157e109.png)

続けてダッシュボードの設定を確認します。インポートしたままでも使えると思いますが、念のためダッシュボードの設定を確認しましょう。

![Node-RED_dashpain.png](https://qiita-image-store.s3.amazonaws.com/0/106468/bc6d7b15-cce7-6c2f-79cd-31f08f6c134c.png)

図を見て頂くと分かるとおり、普段一番右側のペインには「info」と「debug」の2タブしかありませんが、dashboardを有効化することで**「dashboard」**のタブが現れます。ここでダッシュボードやページ、ウィジェットの表示位置を変更することができます。

これでDeployする準備ができました。「Deploy」ボタンをクリックしてダッシュボードを見てみましょう。

***
# ダッシュボードの表示

ダッシュボードを表示するには、先程のダッシュボードのペインからボタンをクリックして「ダッシュボード画面」を起動します。

![Node-RED_dashbutton.png](https://qiita-image-store.s3.amazonaws.com/0/106468/9dc6cbac-ea53-ef4a-69c8-c5f24dfbc6fc.png)

そんな感じでクリックすると、以下のような画面が開きます。やっとダッシュボードが表示されることになりました。
今回は現在の値を表示する**「ゲージ」**と、時系列のデータを表す**「チャート」**の2種類のウィジェットを使用しています。ご覧の通り、中段のチャートは1分間の温度変化、下段のチャートは1日の温度変化を表しています。
今回の計測範囲は弊社のCAMSSセンターという検証施設の室内となっているため、計測対象は通常、棚に取り付けられているロールスクリーンになります。スナップでは12.5度となっているので、結構寒いですね。このスクリーンの前に人が通り過ぎるとその人物の温度になりますので、大体20度から30度台に上がります。
1日のチャートを見ると、空調のサーモスタットで逐次温度変化が起きていることがわかります。

![dashboard.png](https://qiita-image-store.s3.amazonaws.com/0/106468/451343ef-67cd-8125-b1a7-b68fef89ad00.png)

テーマも選べますので、ダークなテーマを選ぶとこんな感じになります。
![dashboard_dark.png](https://qiita-image-store.s3.amazonaws.com/0/106468/1bcefeb5-0448-d39f-0abd-bedbdff8b92f.png)
※1分グラフもステップからカーディナルに変更済み

結構簡単に出力ができました！（かな？）

#まとめ
Node-REDは結構中間的な役割で使われることが多く、直接プレゼンテーションする機能はあまり使われる人もいないかもしれません。
しかし、IoTのように数多くのデバイスを一つの画面で視覚化も含めて集中監視・管理する仕組みが提供されていることには大きい意義があると思います。

あと、何よりもグラフ作成を含め、テキストの出力に至るまで本当に「プログラムレス」で表現できること自体は大変素晴らしく、他の仕組みとは代えがたいものがあります。
みなさんも是非いろいろなデバイスから出力されるいろいろなデータを可視化して遊んでみてください。