とくに詰まるとこも無かったけど、一応備忘録も兼ねて。
MQTTとは
IoT向けの軽量で比較的低遅延な通信プロトコル。TCP/IPの上に乗っかってる。Brokerと呼ばれる中央のサーバーが通信のルーティングを行う。メッセージの発信者をPublisher、受信者をSubscriberと呼ぶ。各メッセージには「トピック」と呼ばれる属性が設定されており、Subscriberは事前にBrokerに読みたいトピックを通知しておく必要がある(この作業をSubscribeと呼ぶ)。
実際に触ってみる
Windows PCの準備
まず、Brokerの準備をしてやらなきゃいけない。今回はWindowsにmosquittoというソフトをインストールすることでBrokerの機能を持たせる。
mosquittoはCUIで動くオープンソースなMQTTのBrokerソフトだ。これはインストールして初めて分かったことだが、MQTTのClient用のソフトもついてくる。Windows、Mac、Linux、raspiなどでバイナリが配布されてるので、Windowsでテストした後にraspiに移植するのもかなり楽にできる。
さて、では実際にインストールしていこう。僕は64bit版Windowsを使っているので、mosquittoの64bit版インストーラをダウンロードしてきて実行した。インストール先は規定通り、C:\Program Files以下。
インストールしたフォルダを見ると、readme-windows.txtなるものが生成されているので、一応確認する(メモ帳では改行が上手く表示されないので他のエディタを使用した方が良い)。すると、OpenSSLをインストールしろ、と書いてあったので、指示通りインストールした。dllの配置先にはbin以下を選択(システムディレクトリは何となく嫌だったので)。本当はこの後dllをmosquittoのインストール先へコピーしなきゃいけないはずなんだけど、なぜかすでに配置されていた(もしかしたらreadmeの方が更新されていないだけで、opensslのインストールも不要になっているのかもしれない)。
これでmosquittoのインストールは完了。
mosquittoの使い方
コマンドプロンプトを起動して、インストール先(僕の場合はC:\Program Files\mosquitto)へ移動。 ここでmosquittoコマンドを打つことで起動できる。-hオプションでヘルプ表示、-vオプションでverbose mode(詳細なログを表示するモード)。検証時は-v付けといたほうがいいと思う。終了するにはCtrl+C。
あと、上でも書いたけど、publishするclientとしても使える(もちろんsubscribeもできるけど、今回は使わない)。使い方は、「mosquitto_pub -d -t (トピック名) -m (メッセージ)」って感じ。動作の様子は下の動画を参照。
ESP32の準備(Publishテスト編)
次に、子機側となるESP32の準備をしていく。
Publishテスト用のプログラムはQiitaの記事で公開されていたので、こちらを使わせていただく。
使用しているライブラリは、PubSubClientというもの。IDEのライブラリマネージャからもインストールできる。 僕はライブラリフォルダをあまり汚したくないので、inoファイルと同じ階層にsrcディレクトリを作成して、その下に配置した。
あとは、Qiitaのプログラムを拝借してちょっといじるだけ。変更点は主に次の通り。
さてmosquittoを-vオプション付きで起動して、ESP32にプログラムを転送すると動くはず(画像取り忘れた)。
ESP32の準備(Subscribe編)
さて、次はsubscribeの方をテストする。今(ブログ記事編集時点)考えてみると、たぶんネットの海のどこかにプログラムあるんだろうけど、そんなことには気づかず、自分で書いてしまったのでもう遅い。
さて、動作の様子は次の動画の通り。基本はPubSubClientのexamples/mqtt_basicをさっきのQiitaに上がってたプログラムを参考にしつつESP32に移植したもの。
コードは以下の通り。
#include <WiFi.h> #include "src\PubSubClient.h" //WiFiの設定 const char ssid[] = "######"; const char pass[] = "######"; const char mqttBrokerAddress[] = "192.168.11.###"; //自PCのipアドレス const int mqttBrokerPort = 1883; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); void connectWiFi(); void connectMqtt(); void setup() { Serial.begin(115200); connectWiFi(); connectMqtt(); } void loop() { if (WiFi.status() == WL_DISCONNECTED) { connectWiFi(); } if (!mqttClient.connected()) { connectMqtt(); } mqttClient.loop(); } void connectWiFi() { WiFi.begin(ssid, pass); Serial.print("WiFi connecting..."); while(WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(100); } Serial.print(" connected. "); Serial.println(WiFi.localIP()); } void connectMqtt() { mqttClient.setServer(mqttBrokerAddress, mqttBrokerPort); mqttClient.setCallback(mqttReceiveCallback); while( ! mqttClient.connected() ) { Serial.println("Connecting to MQTT..."); String clientId = "ESP32-" + String(random(0xffff), HEX); if ( mqttClient.connect(clientId.c_str()) ) { Serial.println("connected"); mqttClient.publish("outTopic","hello world"); mqttClient.subscribe("inTopic"); } delay(1000); randomSeed(micros()); } } void mqttReceiveCallback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i=0;i<length;i++) { Serial.print((char)payload[i]); } Serial.println(); }