PubったりSubったり。
いままでの話
今回はMQTT
IBM Cloud上のNode-REDとESP8266をMQTTで双方向通信をしてみようと思います。
所謂HTTPな通信に比べて軽量なデータなのでIoTに向いていると言われています。ただ、実際は送受信をする際に、データを送る側(Publisher)と受ける側(Subscriber)の間に仲介をする役目(Broker)が必要になってくるわけですが、このBrokerの機能を無料で提供しているサービスがあまり少なく、ウィークエンドプログラマーには厳しいものがあります。
Mosquittoという痒くなりそうな名前のオープンソースなBrokerもあって、これをローカルのマシンに入れれば、同じネットワーク内ではMQTT通信が可能ですが・・・やっぱり、サクッとNATを超えていい感じに通信したい。そこで、IBM CloudのWatson IoT Platformなわけです。
これ、IBM Cloudのライト・アカウントでも無料で使えるんですね・・・(多分200MB/月まで)。IBMは本当に神ですね・・・。ドキュメントも充実しているところも、流石IBMという感じ。IBM様ですね。
ちょうどいい記事があったので、これを参考に実装してみようと思います。
Watson IoT Platformを使ってみる
前置きが長くなりましたが。
IBM CloudでInternet of Things Platform
を有効にします。
Watson IoT Platformのダッシュボードのメニュー>Devicesから、デバイスの登録をしていきます。最初にDevice Type
を新規登録します。ここでは一旦、MQTTDevice
としました。
次にDeviceの新規登録。先程作ったMQTTDevice
をDevice Type
として、新規登録します。Device ID
は多分ユニークな値なら良いはず・・・(震え声)テキトーに設定していきます。
セキュリティの設定は甘くしておきます・・・
Watson IoT Platformのダッシュボードのメニュー>SECURITY>Connection Securityで、接続時に必要とされるセキュアさが設定できるのですが、TLS Optional
にしておきます。これは後々使うESP8266のライブラリのためです・・・。
次にNode−REDをいじります
今回は、とりあえず動かしてみるくらいのモチベーションなので「ESP8266からMQTTを受け取ったらLog出力」「Node-REDからESP8266にMQTT送信」の2つのフローを作ってみました。Watson IoTのノードはそれぞれこんな感じに設定しました。
まず、MQTTを受け取る側は、Watson IoT Platformで受け取ったすべてのDevice Eventを受けるようにしておきます。なので、すべてのAll
にチェックを入れておきます。
一方、MQTTを送信する側はこんな感じで設定します。先程設定したDevice ID
やらDevice Type
などを設定していきます。
最後にESP8266の実装
今回は、このライブラリを使ってMQTTしていきます。
大まかに言うと、以下のことを実装します。
- Wi-Fi接続
- Brokerに接続
- Brokerに対してSubscribe登録
- MQTT受信した時の挙動を指定
- Brokerに対してPublishする実装
実際のコードはこんな感じです。
#include <ESP8266WiFi.h> #include <PubSubClient.h> #define SSID "xxxxx" // アクセスポイントのSSID #define PASSWORD "xxxxx" // アクセスポイントのパスワード #define ORG "xxxxx" // Watson IoT Platformで割り振られているID(My Organization) #define DEVICE_TYPE "MQTTDevice" // Device Type #define DEVICE_ID "xxxxx" // Device ID #define TOKEN "xxxxx" // Deviceを登録した時に発行されるトークン char server[] = ORG ".messaging.internetofthings.ibmcloud.com"; // Brokerのサーバーはこんな感じに決まる char subTopic[] = "iot-2/cmd/notify/fmt/json"; // Subscribeするトピックの設定(Node-REDのノードで設定したコマンド名) char pubTopic[] = "iot-2/evt/request/fmt/json"; // Publishするトピックの設定(Node-REDのノードで設定したイベント名) char authMethod[] = "use-token-auth"; // トークンを使って認証をしていくというお気持ち表明 char token[] = TOKEN; char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID; WiFiClient wifiClient; PubSubClient client(wifiClient); void setup() { Serial.begin(115200); Serial.println(""); // 最初にWi-Fi接続 connectWifi(); // MQTTクライアントの初期化 client.setServer(server, 1883); client.setCallback(callback); } void loop() { // MQTTクライアントが未接続だったら・・・ if (!client.connected()) { // 接続して、Subscribe登録して、一発Publishする connectMqtt(); subscribeMqtt(); publishMqtt(); } client.loop(); } // Subscribeしてるトピックに対して、なにかMQTTを受け取ったときの挙動を記述(ただLog表示するだけ) void callback(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(); } // Wi-Fi接続 void connectWifi() { WiFi.mode(WIFI_STA); WiFi.begin(SSID, PASSWORD); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(1000); // Blink.softly(&pixels, NUMLED, 255, 255, 255); } Serial.println("connected!"); } // Brokerに接続 void connectMqtt() { if (!!!client.connected()) { Serial.print("Reconnecting client to "); Serial.println(server); while (!!!client.connect(clientId, authMethod, token)) { Serial.print("."); delay(500); } Serial.println(); } } // Brokerに対してSubscribe void subscribeMqtt() { Serial.print("subscribe to "); Serial.print(subTopic); if (client.subscribe(subTopic)) { Serial.println(" OK"); } else { Serial.println(" FAILED"); } } // Brokerに対してPublish void publishMqtt() { Serial.print("publish to "); Serial.print(pubTopic); if (client.publish(pubTopic, "{\"d\":\"request\"}")) { Serial.println(" OK"); } else { Serial.println(" FAILED"); } }
ここで、Watson IoT Platformのセキュリティ設定を変更したのは、このPubSubClientでAPI Keyを使った認証がうまくいかなかったので、トークンだけで認証ができるようにしたかったからです。(ちょっとセキュリティがアレかもしれないですが・・・)
動作させてみます!
ESP8266が起動すると、スグにPublishしてきますが・・・
Node-RED上のLog出力にもちゃんと表示されていますね。
また、Node-REDからPublishしてやると、ESP8266のログ出力にも表示されてます。いい感じに双方向通信できてますねー。
mqttできたーーーーーーーーーーーーーcmdとevt間違えてただけだったーーーーーーーーーーーーーーーIBM Cloudのドキュメントは神ですぅーーーーーーーーーーうおおおおおおおーーーーーーーー!
— ポキオ (@pokiiio) 2017年12月20日
いやー、IBMはドキュメントが豊富で助かりますね。というわけで、MQTTをESP8266で触ってみた話でした!