MicroPython的午睡(45) MQTTでJSON-OBJ受信、M5ATOMLite

Joseph Halfmoon

前回が「送信」であったので、今回は当然「受信」です。しかし受信で想定しているのは何か設定値がホストから指令されてくるというシーン。「設定値」ともなるとそれを保存しておく場所から用意しておかないとマズイ気がします。そこで、設定値はNode-REDからアクセスできるSQLiteのデータベースに記録しておき、それを取り出して送ることに。今のところ何も効果はないですが。

※「MicroPython的午睡」投稿順 Indexはこちら

データベース側の設定

サーバー(Raspberry Pi 3)側でNode-REDに接続しているSQLiteデータベースに、各デバイス毎の設定値など格納するために新しいテーブルを1個追加することにいたしました。ベタな名前で “settings” という名のテーブルです。DB Browser for SQLiteでみたテーブルの定義がこちら。SQLsettingTable

uidはレコードの管理のユニーク番号、deviceidはデバイス名テーブルを参照するためのid番号、keyidは、キーワードテーブルを参照するためのキーワード番号です。

ATOMLiteは、今までデータベースに接続するようなノードを使っていなかったので、deviceテーブルに登録されていませんでした。そこで、ATOMLiteをdeviceテーブルに追加。ようやく他のデバイス等と肩を並べた?

SQLdevicekeyidは、キーワード表のid番号です。今までキーワード表には、温度とか、ステータスとか、デバイス側から上がってくる情報を分類するための言葉を登録してきましたが、今回から、設定値のような「下り」に使う情報のお名前も一元管理といたしました。とりあえずまだ用途が定まっていないので、追加したのはベタなお名前、PARAM_AとPARAM_Bであります。

SQLkeysそして今回新設のSettingsテーブルの中身はこちら。まだレコードは2つだけ。

SQLsettingsATOMLite用に、パラメータが2つだけ。

Node-REDフロー

Node-RED側のフローを冒頭のアイキャッチ画像に掲げましたが、簡単なものです。設定値ということで、フローを新たにデプロイしたときや、設定値を変更したときに「たまに」送信するだけと考えました。普段使うダッシュボードに置いておく機能でもあるまいということで、とりあえず手動で送信にトリガをかけることにいたしました。フローは以下の通り。

    1. Node-REDエディタの上でInjectノードを押すと起動
    2. キメウチのSQL文でDBからATOMLite用の設定パラメータを取り出す
    3. 取り出したオブジェクトを「そのまま」MQTTでトピック “ATOMLite/Seggings”に送信

SQLで取り出した結果も結局Node-REDのフロー上では、msg.payloadに乗ってくるjavascriptのオブジェクトになっているので、それをそのまま流せば「あちら」のMicroPythonにはJSONオブジェクト(をバイト列化したもの)に見えるに違いない、というズボラな考えです。

肝心のDBからの設定値取り出し用のSQL文がこちら。SQLも勉強しないとなあ。

SQLnode

MicroPython側のスクリプト(更新部分)

前回、スクリプト全文を掲載しているので、今回は差分部分のみ以下に掲げました。やっていることは少ないです。

    • MQTTで subscribeするトピック ATOMLite/Settings を追加
    • subscribeのコールバック関数に Settings を送られたときの処理を追加

先ほど述べたとおり、Node-RED側では、SQLのselect文で取り出したデータを何も加工せず送信しています。成り行きのJSONオブジェクト。今回は、それを ujsonモジュールを使って読み出して、各項目をダラダラと表示することにいたしました。本当なら、設定用の変数などに値を代入して役立てるのですが、今のところ具体的な目的なしなので。

def callbackSub(topic, msg):
    topicS = topic.decode('utf-8')
    msgS = msg.decode('utf-8')
    print(topicS, msgS)
    if topicS=="ATOMLite/Color":
        print("ATOMLite/Color Message: ", msgS)
    if topicS=="ATOMLite/Settings":
        msgJ = ujson.loads(msgS)
        print("ATOMLite/Settings: ")
        for item in msgJ:
            for k,v in item.items():
                if k=="key":
                    ky = v
                if k=="value":
                    vl = v
            print(ky, " = ", vl)

def connectMqttBroker(bAdr, bPort, clientId):
    global client
    try:
        client = umqtt.simple.MQTTClient(clientId, bAdr, port=bPort)
        client.set_callback(callbackSub)
        client.connect()
        client.subscribe("ATOMLite/Color")
        client.subscribe("ATOMLite/Settings")
    except:
        return False
    return True

ホスト側のDBに書き込んであった値が、Node-REDからMQTTを介してM5ATOMLite上のMicroPythonへと伝わってまいりました。それだけではツマラナイな。

MicroPython的午睡(44) MQTTでJSON-OBJ送信、M5ATOMLite へ戻る

MicroPython的午睡(46) uasyncioでMQTT送受信、ATOMLite へ進む