ども。こんばんは。
codey rockyではメッセージキューWとしてMQTTWが実装されています。
せっかくなのでちょっと試してみます。
MQTTについては少し古いですがこの辺がわかりやすいです。
MQTTで始めるIoTデバイスの作り方 第1回:「MQTT」を知り「Mosquitto」を導入する (1/3)
まずはMQTTのブローカーとしてmosquittoをRaspberry Pi上にインストールします。
※そのうちRabbit MQも試したいなと思いますがまずは手軽そうなmosquittoで試します。
ブローカーの動作環境はRaspbian GNU/Linux 9.11 (stretch)で、2020/02/16時点最新のパッケージになっています。
・mosquittoのインストール
sudo apt install mosquitto
うちの環境ではlibev4とlibwebsockets8も合わせてインストールされました。
・続いてクライアントもインストールします。
sudo apt install mosquitto-clients
libmosquitto1が合わせてインストールされました。
・ブローカーの起動
sudo systemctl start mosquitto
sudo systemctl status mosquittoで確認して特に問題なく起動していました。
1883ポートでLISTENしているみたいですね。
・テスト
以下のコマンドでtestというトピックを購読(サブスクライブ)します。
mosquitto_sub -d -t test
実行結果はこんな感じ。
※lexはうちのラズパイのホスト名です。
Client mosqsub/6162-lex sending CONNECT
Client mosqsub/6162-lex received CONNACK
Client mosqsub/6162-lex sending SUBSCRIBE (Mid: 1, Topic: test, QoS: 0)
Client mosqsub/6162-lex received SUBACK
Subscribed (mid: 1): 0
・テストメッセージ送信
別のターミナルでSSHに接続してtestトピックに投稿(publish)します。
mosquitto_pub -d -t test -m “test 1”
すると、サブスクライバー側で以下のように表示されます。
Client mosqsub/6162-lex received PUBLISH (d0, q0, r0, m0, ‘test’, … (6 bytes))
test 1
これで最低限の動作はokですね。
続いてcodey側にこんなコードをアップしてみました。
以下のリファレンスからサンプルコードを流用していますが、リファレンス内のサンプルコードの「from mqtt import MQTTClient」は誤りで、正しくは「from cloud_message.mqtt import MQTTClient 」です。
https://makeblock-micropython-api.readthedocs.io/en/latest/public_library/Third-party-libraries/mqtt.html
■サンプルコード
#import mqtt package
#リファレンスは"from mqtt import MQTTClient"となっているが実際はcloud.message.mqttが正しい
#https://forum.makeblock.com/t/importerror-no-module-named-mqtt/15029
from cloud_message.mqtt import MQTTClient
import codey, time, event
import utime
MQTTHOST = "mosquittoのサーバのIPアドレス"
MQTTPORT = 1883
#なんでもいいらしいが重複はだめっぽい。
#https://qiita.com/egnr-in-6matroom/items/3aef4bd45857e75bb1d3
client_id = "101"
# Example Path
#ここの指定方法がまだわからない・・・。全部取得してみる。
Topic = "#"
# ID / PWはオプション。今回はmosquitto側では指定していないので省略した。
#mqttClient = MQTTClient(client_id, MQTTHOST, port=MQTTPORT, user='test', password='test', keepalive=0, ssl=False)
mqttClient = MQTTClient(client_id, MQTTHOST, port=MQTTPORT, keepalive=0, ssl=False)
# Connect to the MQTT server
def on_mqtt_connect():
mqttClient.connect()
# publish a message
def on_publish(topic, payload, retain=False, qos = 0):
mqttClient.publish(topic, payload, retain, qos)
# message processing function
def on_message_come(topic, msg):
#print(topic + " " + ":" + str(msg))
#b'test'みたいな表示になるので、文字列化して分割。なおメッセージ自体に'(シングルクォーテーション)がある場合は""で囲まれるが未対応
temp_msg = str(msg).split("'")[1]
codey.display.show(temp_msg,wait=True)
# subscribe message
def on_subscribe():
mqttClient.set_callback(on_message_come)
mqttClient.subscribe(Topic, qos = 1)
@event.button_a_pressed
def on_button_a_pressed():
codey.display.show("Start",wait=True)
codey.wifi.start('SSID', 'パスワード', codey.wifi.STA)
time.sleep(1)
if codey.wifi.is_connected():
codey.emotion.smile()
on_mqtt_connect()
on_subscribe()
codey.display.show("Ready!",wait=True)
while True:
#RTCがついてないので起動からの時間となる。
#nowtime = utime.time()
#codey.display.show(nowtime,wait=True)
#codey.display.show(codey.battery.get_percentage(),wait=True)
# Blocking wait for message
mqttClient.wait_msg()
#ブロッキングしない方
#mqttClient.check_msg()
time.sleep(1)
else:
codey.emotion.shiver()
@event.button_b_pressed
def on_button_b_pressed():
codey.display.show("Stopped",wait=True)
codey.stop_all_scripts()
これをcodeyにアップロードすると、パブリッシュされたメッセージを表示するようになります。
だいぶ前に作ったbrouteから消費電力を取得するスクリプトを少し改変して、取得した結果を単純にmosquitto_pub -d -t test -m 値で投稿(publish)するようにしました。
#python上からosコマンドを実行しています。こういう移植性のないことしちゃだめですね。ちゃんとmqttをpythonから操作するように変更しないと・・・
動作の様子はこんな感じです。
エアコンを入れると消費電力がちゃんと上がってますね。
本当はメッセージが無い間は、時計にでもしようと思ったのですが、odey rockyにはRTCが搭載されていないようで、utime.time()で取得した値は、電源投入後からの起動時間(秒)となります。
mqttClient.wait_msg()はブロックされますが、mqttClient.check_msg() はブロックされないので、まぁバッテリーの残量を出すとかそういう感じのことはできそうですね。
あと、MQTTのトピックの指定の仕方がよくわかりませんでしたので”#”としています。一応トピックは「test」で来てるみたいですが、「/test/」とかにしてもうまく拾えないんですよね。
これはもうちょっと調べないと。
次は赤外線周りをなんかやってみようかな。
【バックナンバー】
ではでは。またの機会に。