前回、センサノードとしたmicro:bitの測定データを無線/有線経由してNode-Redのダッシュボードへ「上り方向」に伝えました。一方、別件ではmicro:bitにスピーカを接続し無線で鳴らしています。再びこれをMQTT経由でガチャンコすれば、今度は下り方向ができる筈。ついでにNode-Redのdropdownメニューの使い方をお勉強。
※「IoT何をいまさら」投稿順Indexはこちら
ということで、センサノードのmicro:bit 緑号機と、無線中継器になっているmicro:bit 赤号機のMicroPythonスクリプトは別件で作ったものをとりあえずそのまま使っています。今回追加作業するのは Node-RED上のフローとRaspberry Pi(3B)上で走っている「MQTTクライアント」スクリプトです。
Node-Red エディタ上での設定
やりたいことは、ダッシュボード上に配置したドロップダウン・メニューから「曲名」を選んだら、「先っぽ」のmicro:bit 緑号機が音楽を奏でるというだけ。micro:bitは任意の「楽譜(単音ですが)」を結構いい音で鳴らせるのですが、今回はROM内蔵の楽譜から味もそっけもないお知らせ音的なものを3つだけ選択できるようにプログラムしてあります。もっと荘厳?に「ジャジャジャジャーン」とか出来るのですが、鳴っている間はセンサの計測がお留守になるので、短いもののみ。
さて、Node-Red上で追加したのは以下の3つです。
-
- ダッシュボードにグループ MBGreen/MUSIC を追加
- フローにダッシュボード上のドロップダウンuiを追加
- フローにMQTT-outノードを追加
勿論、2と3を接続し、全ての設定が完了した後で忘れずにデプロイします。追加部分のフローはこれだけ。
ダッシュボードへのグループの追加は画面レイアウトなど「成行まかせ」であるので、Groupのお名前を登録するだけ。
ドロップダウンノードの方は、メニューに表示する値とそれを選択したときに送り出す値のペアを設定しないとなりません。こんな感じ。
最初、Optionsのところには1個しか欄がなく、3個ペアをどこに設定するの?とちょっと戸惑ったです。よく見ると上のキャプチャの左下(実際画面ではこの下にも欄がいくつかあります)に
+optionという小さなボタン
があり、これをプチプチ押していけば所望の数だけペアを作れました。始めてだと戸惑うことバカリ。なお、左が送出する「値」(数値、文字列など選択可能)で、右がプルダウンメニューに表示する文字列です。
MQTT-outノードの設定は、前回のMQTT-inノードの設定と変わりませぬ。接続する先のMQTTブローカとトピックを記入するだけで動作します。
Python3スクリプトにMQTTサブスクライバ追加
前回までラズパイ上で走っているスクリプトは、無線中継器となっているmicro:bit 赤号機がUartで垂れ流してくるメッセージをMQTTブローカに向かってパブリッシュするというお役目でした。今回は逆にMQTTブローカにMBGreen/MUSICトピックのサブスクライブをお願いしないとなりません。サブスクリプトしていると、ダッシュボードのdropdownメニューからMQTT-outノードを経由してパブリッシュされた情報が送られてくる、というわけです。
前回は、パブリッシュだけだったので何のコールバック関数も無しの簡単なコードでしたが、今回は両方向なので、最低限の「クライアント」を実装せねばなりません。今回
のページの”Getting Started” のサンプルをほぼそのまま下敷きにさせていただきました。一応、本投稿の末尾に全スクリプトを掲げましたが、大したことはしてないです。ただね、別件のMicroPythonネタでdecode()が無くて結構なやんだbytesからstr型への変換、こちらのスクリプトではその逆のstr型からbytes型への変換しないとならないですが一撃で出来ました(Python3なので当然だけれども。)
実行したところがこちら。MBGreen/Music b’2′ などと表示されているところで、ダッシュボードのドロップダウンメニューから曲名選んでます(アイキャッチ画像ご参照ください。)すると、micro:bit 緑号機のスピーカが鳴ります。一方、サーミスタの測定値は前回同様、送られてきます。
Raspberry Pi上のPython3で実行しているコードの全体はこちら。
#! /usr/bin/python3 import serial import paho.mqtt.client as mqtt def on_connect(client, userdata, flags, rc): print("Connected with result code " + str(rc)) client.subscribe("MBGreen/Music") def on_message(client, userdata, msg): print(msg.topic + " " + str(msg.payload)) ser.write(bytes(msg.payload)) def processThemistor(dat): global client print("REC={0} Thermistor={1} ChipTemp={2}".format(dat[0], dat[1], dat[2])) client.publish("MBGreen/Thermistor", dat[1]) recMax = 500 rec = 0 ser = serial.Serial('/dev/ttyACM0', '115200', timeout=0.5) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("127.0.0.1", 1883, 60) client.loop_start() client.publish("MBGreen/Status", "Running") def main(): global rec, recMax, ser, client try: while True: mes = ser.readline().decode('utf-8').strip() dat = mes.split(":") if len(dat) == 3: processThemistor(dat) rec = (rec + 1) if rec < recMax else 0 except KeyboardInterrupt: ser.close() print("Terminated by KBD interrupt.") client.publish("MBGreen/Status", "STOP") client.loop_stop() if __name__ == '__main__': main()
ま、かなりいい加減なもんだけれど、とりあえず、「上り」も「下り」もOKっと。