ブロックを積みながら(54) Node-RED、ATOMLiteフローにSqlite追加

Joseph Halfmoon

トンガでの噴火の後、日本時間の夜中の「津波」警報には驚きました。巨大噴火の恐ろしさ。残念だったことがあります。気圧センサを常時動かしていたらもしかすると前兆の気圧変化波形とれていたんじゃないかと。でもATOMLiteに取り付けた気圧センサ動かしてなかったです。それにDBへの記録機能なし。これはイケない。

※「ブロックを積みながら」投稿順 index はこちら

M5ATOMLite利用の「システム」

別シリーズでやっているM5ATOMLite利用のシステムは以下のような構成です。

    • M5Stack社製の超小型デバイス M5ATOMLite (ESP32搭載)
    • ESP32 generic ポートのMicroPythonで動作させている
    • 定番の複数のセンサ等を接続済(DHT-11温湿度センサ、BMP280圧力センサ、CDSセルなど)
    • 測定値はWiFi経由で、Raspberry Pi 3上のMQTTブローカに報告
    • 同じRaspberry Pi 3上で Node-REDも走っている。
    • Node-REDは、M5ATOMLiteから送られてきた情報をダッシュボードに表示

ダッシュボードに表示するのは良いのですが、現状、ダッシュボード上のグラフに1日分のデータを表示するだけで、1日経てば消えてしまいます。

一方、Raspberry Pi 3上にはSqilteデータベースを準備済です。micro:bit v2をつかった「センサノード」がセンスしたデータをBluetooth使ってラズパイ3に送信し、Sqliteデータベースに格納する実験もやってみてます。

micro:bit v2の実験のときに作ってあった Node-RED フローをコピペして改造すれば、M5ATOMLiteのデータをデータベースに記録するのは簡単じゃね。本当か?

Sqliteノード

過去記事で何度も使わせていただいているNode-REDのSqliteノードですが、念のためマニュアルページへのリンクを貼り付けさせていただきます。

node-red-node-sqlite

基本、Sql文を走らせると結果はJSONオブジェクトで返ってくる使い易いノードです。

ATOMLite用フロー「改造前」の全貌

以下がATOMLite用のフローの今回改造前の全貌です。ATOMLite側からはStatusや温度、湿度、気圧などの測定値を送ってくるのでNode-REDではそれらをDashboard上に表示しています。また、Dashボード上のスイッチやプルダウンメニューを操作すると、M5ATOMLite内蔵のLEDを発光させたり、接続してあるブザーを鳴らしたりすることもできます。(別シリーズの目次はこちら

ATOMLiteBefore
現状のATOMLite用ダッシュボード(一部)の様子が以下に。グラフを中心に雑多なUIを並べています。

ATOMLiteDashBoard

DataBaseへの項目追加

用意してあるデータベースの基本的な構造(フィールド)は以下の様です。

    1. いつ
    2. どのデバイスが
    3. どんな種類のデータを
    4. その生データ

M5ATOMなど、データを送ってくるデバイス類はテーブルに登録してデバイスIDを割り当ててあります。また、「どんな種類」の部分は、keyテーブルに登録してあります。今回、M5ATOMのセンサ類のデータを記録するにあたってkeyテーブルのエントリを追加したので、以下にその様子を示します。

DB_KEY_ADDED
kid=7,8,9,10が今回追加したキーです。

DataBaseアクセスの準備フロー

さて、SQLデータベースにセンサデータを書きこむにあたって、デバイスID、キーIDは必須なので、以下のフローでデバイスIDテーブル、キーIDテーブルを読み取り、それをflowの変数として記録することにしました(フローの起動時の1回実行すれば、後はflowオブジェクトから読み出されます。自動起動しかけてもよし。)

その初期化のフローは micro:bit v2用のものをほぼほぼそのまま流用いたしました(コピペですな。Node-REDはNode-REDエディタ上でのフローのコピペができるだけでなく、JSON形式でのファイルへの読み書きもできるので便利です。)

ATOMLiteInitializeKeys
実際にデバイスIDテーブルを読み取る Sqliteノードの設定は、データベースの在り処を指定しているだけで、肝心のSQL文は上流からもらっています(デバイスIDテーブルを取得する select * 文。)

DeviceIDtable
selectの結果は、普通にmsg.payloadに載ってくるので、そこからATOMLiteを探し出し、そのデバイスIDを flowのプロパティとして記憶させています。

getDeviceIDキーIDの抽出処理では、ノードの中に select 文を直接コードしてありました。多分、サンプルとして両方のやり方をやってみたかっただけのような気がします。もはや理由は忘却の彼方。この処理なら固定文を直接書く方が、後になると分かり易い。

getKeyID
ちゃんとテーブルからIDを読み取れていることをデバッグウインドウで確認しているところが以下です。

ATOMLiteInitDebug

JSONデータの処理とDataBaseへの記録

本物のデータの記録部分が以下に(フロー下側のSelect Objects以下の部分。)準備が終われば結構簡単な追加。

ATOMLiteAfter

M5ATOMLiteから送信されてくるJSONオブジェクトにはいろいろプロパティが載っているので、まず split ノードでプロパティ毎に分けます。こんな設定。

SplitJSON
splitすると以下のような「個別」オブジェクトが得られます。

SplitOBJsample
個別ノードの中から記録したいデータのみ選んでSQL文を付けて送り出すのが以下のfunctionノードです。ここはfunctionノードでなくても書けそう、と思いつつ、以前の方法をそのまま踏襲。汚い。

funcJSONさて、データベースにレコードを記録する Sqlite ノードの実体は書き込み先のファイルを指定しているだけ。SQL文は到来したmsg.topicの中のものをそのまま使う設定。

sqliteJSON

動作結果

さて、ラズパイ3上でデータベースに書き込まれている様子の確認が以下に。

kvData
書き込まれとります。BMP280からの温度の生データの桁数が多いですが、複雑な補償計算の結果がこうなるというだけで、精度はそんなにありません。精度は後で処理するときに考慮。こうしてデータベースに書き込まれてくると、今度はそれを処理するフローが欲しくなりますな。また今度だな。

ブロックを積みながら(53) Node-RED、csvノードでcsvファイルの変換 へ戻る

ブロックを積みながら(55) Node-RED、Pingでネットワークへの接続を確認 へ進む