SenseWay LoRaWAN のための Node-RED 2019/09/01, 05, 15

・2019/09/15 送信データの間違いを修正
・2019/09/05 送達確認の間違いを修正


Node-RED は、「ハードウェアデバイス、API、オンラインサービスをつなげるためのプログラミングツール」です。

SenseWay Mission Connct (LoRaWAN を用いた IoT 通信プラットフォームサービス)では、
外部連携機能で Microsoft Azure、AWS (Amazon Web Service) へ接続できます。
それ以外は、MQTT プロコトルを使って接続するようです。
Node-RED を使うと、下↓のイメージのように、ノードを置き、ワイヤでつなぐだけで、MQTT 接続、データベース、視覚化、メール送信までできてしまいます。
 
MQTT のデータは、iPhone、Android アプリでも取得可能です。Delphi でも読み込み、書き込みできます。

Node-RED は 24 時間稼働させたいため、ローカルの PC にインストールせずに、enebular サーバ上の Node-RED を使っています。
ローカルの PC を使った場合は、Node-RED を起動しておく必要があり、電源を切ると Node-RED は停止し、一連のフローは動かなくなります。
当たり前といえば当たり前のことが、やってみるまで分かりませんでした。初めての Node-RED なので、その程度のレベルです。

SenseWay提供のチュートリアルで作ったフロー(赤枠の中) に、
デバイスデータをデータベースに格納、可視化サービスを使った可視化、データ異常をメールで送信するまでを追加してみました。
以下はその説明(自分なりの解釈)の羅列です。

■赤枠の外(下)が追加したフローで、データベース接続、データ可視化、メール送信のフローを追加しています。


■赤枠の中の上側のフロー


 センスウェイサーバからの情報を [ mqtt in (SenseWa MQTT) ] ノードで受け取ります。
 この時点で、JSON (改行なし) 形式のテキストデータになります。

  ※JSON (ジェイソン) とは JavaScript Object Notation の略で、XML などと同様のテキストベースのデータフォーマットです。
    XML より簡潔で整形(改行)すると、見た目にも分かりやすくなります。


 デバイスから送られた実際のデータ (16 進表記の文字列)を、[ kgpcomposer (SenseWay)] ノードでポートごとのバイナリデータに変換。
 [ kgpparser ([Port12)]、[ kgpparser ([Port13)] でデータを読む順番と型(int16, unit16, uint32 ...)を指定し、ポートごとのデータを取得します。
 結果、[123, 456, 789 ... ] のような配列として取得されます。

 [ kgpparser ([Port12])] のプロパティーです。Format は、int16_t, uint16_t, uint32_t になっています。
  
 これは、データが "09c813880000320"のとき、"09c8", "1388", "00000320" の順で読むことになります。
 バイト数で言うと、、2バイト(int16_t), 2バイト(uint_16_t), 4バイト(uint32_t)の順、文字数で言うと、4文字, 4文字, 8文字の順になり、
 結果 [0x09c8, 0x1388, 0x00000320] の配列になります。
 10進表記だと、0x09c8 = 2500, 0x1388 = 5000, 0x00000320 = 800 になり、[ 2500, 5000, 800 ] も同じです。
  ※[ kgpcompose ] が受けるデータは16進表記の文字列(限定)ですが、送る側の送り方(エンコード方法)と受ける側の読み方
   (デコード方法)が合っていれば、どういう表記でも問題ありません。
  [ kgpcomposer ] を使う場合は、16進表記にする必要があるようです。

 
[ kgpparser ] ノードをインストールするには、 enebular 上の Node-RED の場合、
 サイドバーの[ admin ] タブの入力ボックスに"kgp"と入力し、一覧の中から "node-red-contrib-kgpparser"を選択、
 [ Install ] ボタンをクリックすると、ノードパレットに追加されます。[ kgpcomposer ] ノードも同様にインストールできます。

 

 
ノードのインストールはサイドナー右上の[ ] マーク(ハンバーガーメニュー)をクリックし、「パレットの管理」からも行なえます。(こちらが一般的なようです)
 
  
「ノードを追加」を選択し、検索文字列を入力します。一覧から選んで,[ ノードを追加 ] をクリックします。
 
  
 ポートごとにデータを分ける意味がよく分からなかったのですが、そうすることでデータの読み方を変える、
 以後の処理が分岐できるということのようです。
 例えば、Port11 は温湿度、Port12 は電流、電圧、Port13 は生産数、サイクルタイム ... のように分け、それぞれのデータの保存先を変える、
 メール、SMS で上下限値を超えた場合のメッセージを変えるとか、処理を分岐する場合に使うのかなと思います。

 
※デバッグ用 [ debug ] ノードの右側の■をクリックすると、有効/無効の切り替えができます。切り替え後は「デプロイ」が必要です。
  

 赤枠の外(下)になりますが、配列のデータを JSON 形式のデータに変換しています。
 

 [ function ({temp, humi, press } )] で、配列を JSON データに変換しています。
 
 


■赤枠の中の下のフロー
 

 [ Inject (timeatamp) ] で 1 分に 1 回の周期で、Port15 のデータとして、数値 1010 を書き込み、
 [ mqtt out (SenseWayMQTT) ] ノードでセンスウェイサーバに送信します。

 [ Inject (timeatamp) ] のプロパティです。 1 分に 1 回の繰り返しです。
 
 
 
※1分待たなくても、ノードの左側の■をクリックするとテストできます。
  

 [ kgpcomposer (Port15)] のプロパティです。Port 15 、数値 1010 のデータを作成しています。
 

 [ function (送信データ作成) ] のプロパティです。
 
 コード (javascript) では、JSON 形式の文字列を作成しています。
 結果 { conf: false, ref: "abcde", port: 15, data, "03f2" } が出力されます。
 data: "03f2" の "03f2" は、数値 1010 を16進表記の文字列のしたものです。
 
 表示を変えると、こう↓なります。
 
 
 
※デバッグウィンドウの「ゴミ箱」ボタンをクリックすると、デバッグログがクリアされます。
  


 ポート 15 にデータを書き込むとどうなるのか、よく分からななかったのですが、
 デバイス側でデータを送信したした時にその値を取得できるようです。
 その値によってデバイス側で処理を分岐するのに使うのでしょうか。
 今のところ、デバイスから送信したデータがサーバに届いた確認に使っています。
 (2019/09/05 追記)
 
送達確認付き sendDataConfirm() を使うと、その名のとおり届いた確認ができました。
 (2019/09/15 変更)
  {"conf":false,"ref":"rssi","port":15,"data":-59} で、受信信号強度 "rssi" を送るようにしました。
 どうもデータは 16 進文字列で送る必要があるようで、-59 では、デバイスまで届きませんでした。(tx_send されない)
 {"conf":false,"ref":"rssi","port":15,"data":"0037"} で、受信信号強度 "rssi" の絶対値を 16 進文字列で送っています。

 "rssi" が -110 以下の時は通信が安定しないの判断に使おうと思っています。
 下のようにフローを変更しました。最後の rssi 値は、グローバル変数に格納しています。
 
 
 

■赤枠の外
 
 ・データベース Firebase RealTime Database に保存します。
 

 [ function (date, rssi, temp, humi, press)] のプロパティです。
 

 [ Firebase ] のプロパティです。
 データベースが無いときは、新規に作成されます。
 


 Firebase に push でデータを新規作成、追加すると、ユニークな ID が自動的に作成され、その中にデータが格納されます。
 SQL データベースのようなテーブル、レコードはありません。1つの JSON データです。

   
 当初、さくらレンタルサーバの MySQL にデータを保存するフローを作成していましたが、さくら側の制限があり繋がりませんでした。

 ・データ可視化サービス Ambint にデータを送って、可視化します。

  
 
 [ function (temp, humi, press) ] のプロパティです。
 受け側 Ambint に合わせて、データ名は d1, d2 ... にしています。

 

 [ Ambient ] のプロパティです。ChannelId と WriteKey を設定するだけです。
 

 Ambient でのグラフ表示例です。
 

 棒グラフに変えると、データの欠落が分かりやすいです。
 

 ・データ異常、温度異常をメールで送信します。

 

 [ function (温度異常検知) ] のプロパティです。
 

// 温度異常発生
if (ftemp >= 33.0 && !tempHiFlag){
    global.set("global_tempHiFlag", true);
    res = 1;
}
else
// 温度異常復帰
if (ftemp > 0.0 && ftemp <= 30.0 && tempHiFlag){
    global.set("global_tempHiFlag", false);
    res = 2;
}
// 送信メッセージ
if (res == 1){
    msg.topic = "温度異常、発生しました";
    msg.payload = "温度計測値が 33 ℃を超えました";
}
else if (res == 2){
    msg.topic = "温度異常、復帰しました";
    msg.payload = "温度計測値が 30 ℃以下になりました。";
}
msg.result = res;
return msg;

  [ function (受信日付を格納) ] のプロパティです。グローバル変数に最新の受信日付を文字列で保存します。
 

 [ function (日付の比較) ] のプロパティです。
 現在の日時と受信日時を1分間に1回比較し、その差が1分を超えた時、受信異常と判断しています。
 同時に、メールのタイトルと本文を作成しています。

 

var recDate = Date.parse(global.get("global_recDate"));
var nowDate = msg.payload;
// 整数
//var sa = Math.ceil((nowDate - recDate) / 60000);
// 実数
var sa =(nowDate - recDate) / 60000;

msg.result = 0;
var ngFlag = global.get("global_ngFlag");
if (sa > 1.8 && !ngFlag){
    global.set("global_ngFlag", true);
    msg.topic = "データ受信異常が発生しました";
    msg.payload = "データ受信異常が発生しました。";
    msg.result = 1;
}
else if (sa < 1.8 && ngFlag){
    global.set("global_ngFlag", false);
    msg.topic = "データ受信異常復帰しました";
    msg.payload = "データ受信異常が復帰しました。";
    msg.result = 2;
}
return msg;

 [ switch ] のプロパティです。msg.result が 0 より大きいとき、メールを送信します。
 
 
 [ email ] のプロパティです。
  こちらの環境では、発信元の Gmail で「安全性の低いアプリの許可」を有効にする必要がありました。
 


 ・SMS 送信
 実装はしていませんが、Node-RED から データが途切れた時、SMS (ショートメッセージサービス / ショートメール)を送信するには、
 twilio for KDDI Web Communications で 海外電話番号を購入(¥150/月)すれば使えるようです。(メッセージ1通 ¥9 程度)
 Node-RED に、node-red-contrib-sms-twilio ノードを追加(インストール)する必要あります。

 ・
Node-RED での読み込みで、追加したノードがインストールされない場合があります。
  焦らずに、ブラウザの「更新」ボタンをクリックすると正常にインストールされます。(ダメな場合は、もう一度「更新」)

 

 
・サイドバー右上の[三] マークをクリックし、「読み込み」、「書き出し」を選択すると、クリップボードを使って、読み込み、書き出しが行えます。
  「書き出し」は、ノードを1つ以上アクティブにしておく必要があるようです。

■関連リンク
 ・SenseWAY(センスウェイ株式会社)
 ・SenseWay Mission Connect センスウェイ ミッション コネクト) LoRaWAN を用いた IoT 通信プラットフォームサービス

 ・LoRaWAN (LPWAを活用する為のIoTビジネスセミナーに行ってきました!
        (JapanITWeek2018年秋 IoTM2M展【センスウェイ】さんのブースの記事!)
 ・MQTT (MQTTってどんなもの?)
 
 ・Node-RED (Node-RED User Group Japan) ハードウェアデバイス、API、オンラインサービスをつなげるためのプログラミングツール
 ・enebular(運営:株式会社ウルフ) IoT製品・サービスづくりを包括的に支援する、開発・運用サービス
 ・Firebase RealTime Database (Google) NoSQL クラウド データベースでデータの保管と同期を行うことができる
 ・Ambient (運営:アンビエントデーター株式会社) IoTデータ可視化サービス 
 ・twilio(運営:株式会社 KDDI ウェブコミュニケーションズ) 様々なコミュニケーション手段を組み込むことのできるクラウドAPIサービス