前回はESP-WROOM-02 (ESP8266)を使って気温・湿度・気圧の記録を行いました。我ながらまずまずの出来だと思ったので家族に少し自慢をしたのですが「そんな物作って何になんの?」と鼻で笑われてしまいました。(ショックです) 以前何かで読みましたが、かの発明王エジソンが蓄音機を発明し、喜び勇んでプレス発表した時の新聞記者も同じ反応だったそうです。
大エジソンと私とでは比べようもないのですが、同じ悲哀を味わえてホンの少しですが人間的に成長できたような気がします。めげずに前進したいと思います。
さて、今回はIoTに適したと言われているMQTTというプロトコルの実験を行いました。ArduinoにはMQTTのライブラリがあって、非常に簡単に実現できることがわかりました。今回はこれを使って遠隔操作でLEDの点灯・消灯を行います。
MQTTについてはこちらShiguredo Inc.様のサイトに詳しい解説があります。私は始めて勉強したのですが、メールマガジンの発行購読に似たシステムの様に感じました。
メッセージの送り手(パブリッシャー),MQTTサーバ(ブローカー),メッセージの購読者(サブクライバー)三者がいて、パブリッシャーはメッセージにトピック(識別子)を付けてMQTTサーバに送ると、MQTTサーバはそのトピックを購読しているサブクライバーにメッセージを配信する仕組みのようです。パブリッシャーは同時にサブクライバーにもなる事ができます。
何から手をつければ良いかわからなかったのですが、こちらのサイトhttp://www.element14.com/community/community/design-challenges/forget-me-not/blog/2014/09/17/fmnxx-mqtt–the-language-of-iotにとても詳しく記述されておりました。 (thanks! vish)
このサイトの記述に沿って実験を行います。
全体の構成は次の図の様になります。
Localに作るMQTTサーバは当初 Raspberry Pi と思ったのですが、今回は毎度お世話になっている自宅サーバ Debian Linux (wheezy) にインストールすることにしました。brokerソフトはmosquittoになります。次のコマンドでインストールします。
sudo apt-get install mosquitto mosquitto-clients python-mosquitto
私の場合残念ながら上記だけではMQTT v3.1.1 Broker に対応するバージョンがインストールされず、Arduino スケッチがうまく動いてくれなかったので、ここに書いてある通り追加の作業を行いました。
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key sudo apt-key add mosquitto-repo.gpg.key cd /etc/apt/sources.list.d/ sudo wget http://repo.mosquitto.org/debian/mosquitto-wheezy.list sudo apt-get update sudo apt-get dist-upgrade
WindowsPC側はChrome Appの MQTT Lens を立ち上げてパブリッシャー兼サブクライバーになってもらいます。先ほどインストールしたmosquittoはデフォルトでは認証の機能はOFFになっているようなので、すぐにMQTT Lensを使いテストをする事ができます。
MQTT サーバに接続後に適当な名前でトピックを購読した後、同じトピックでメッセージを発行するとMQTTサーバから配信されたメッセージを見ることができます。
トピックはディレクトリの様に”/”で区切って記述するとワイルドカードを使って購読の指定をすることもできるそうです。
ESP-WROOM-02の回路ですが前回と同じくikesato氏の「ESP-WROOM-02 の Arduino 環境で I2C 制御」に書かれている回路図を参考にさせていただきました。
この実験のためにESP-WROOM-02を追加購入しようとしたのですが、SWITCH SCIENCE社の完成モジュールは在庫が無く注文できませんでした。しかたなく「ESP-WROOM-02ピッチ変換済みモジュール《フル版》 ボードのみ」と秋月電子通商 Wi-Fiモジュール ESP-WROOM-02を購入して半田付けをすることにしました。大した事は無いだろうと高を括っていたのですが、老眼で不器用な私には思いのほか難しかったです。
ブレッドボードに組ましたが、SWICH SCIENCE社のブレークアウトボードではESP-WROOM-02を挿すと幅いっぱいになってしまうので、写真のように内側にジャンパ線を使い配線しました。
MQTTのArduinoライブラリの入手先はhttp://pubsubclient.knolleary.net/index.htmlこちらです。Download GitHubへ進み V2.4 (2016/01/15現在) Source code (zip) をダウンロードし解凍後 ArduinoIDEのライブラリズ ホルダへコピーします。
ArduinoIDEを起動してファイル-スケッチの例-PubSubClient-mqtt_8266 をロードしたのちに一部手直しです。
[変更部分] const char* ssid = "........"; --> WiFiアクセス SSID const char* password = "........"; --> 同上 パスワード const char* mqtt_server = "broker.mqtt-dashboard.com"; --> MTQQサーバのipアドレス pinMode(BUILTIN_LED, OUTPUT); --> 4ヶ所(注釈含む) の "BUILTIN_LED" を"5"へ
/* Basic ESP8266 MQTT example This sketch demonstrates the capabilities of the pubsub library in combination with the ESP8266 board/library. It connects to an MQTT server then: - publishes "hello world" to the topic "outTopic" every two seconds - subscribes to the topic "inTopic", printing out any messages it receives. NB - it assumes the received payloads are strings not binary - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led, else switch it off It will reconnect to the server if the connection is lost using a blocking reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to achieve the same result without blocking the main loop. To install the ESP8266 board, (using Arduino 1.6.4+): - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": http://arduino.esp8266.com/stable/package_esp8266com_index.json - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" - Select your ESP8266 in "Tools -> Board" */ #include <ESP8266WiFi.h> #include <PubSubClient.h> // Update these with values suitable for your network. const char* ssid = "WifiエスエスID"; const char* password = "同上password"; const char* mqtt_server = "MTQQサーバIPアドレス"; // WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; void setup() { pinMode(5, OUTPUT); // Initialize the 5 pin as an output Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } 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(); // Switch on the LED if an 1 was received as first character if ((char)payload[0] == '1') { digitalWrite(5, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is acive low on the ESP-01) } else { digitalWrite(5, HIGH); // Turn the LED off by making the voltage HIGH } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("ESP8266Client")) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); // ... and resubscribe client.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; ++value; snprintf (msg, 75, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("outTopic", msg); } }
MQTTlens にてTopicを “outTopic” にしてSubcribeすると 2秒おきにESP-WROOM-02の発した”hello world”を受信します。
また、Publish側のTopic を”InTopc”にしてメッセージを送信するとESP-WROOM-02に配信されます。
ESP-WROOM-02では受け取ったメッセージの先頭の1文字が”1″ならばLEDが点灯しそれ以外では消灯します。参照先のwebではopenHABを使用して操作する方法が書かれていましたが、今回は一応の目的を達することができたのでこれで良しとします。(すみません、この状態では「LEDチカチカ」を継続させるためには、非常に努力が必要ですね。タイトルに偽りありでした。ごめんなさい。)
(2016/01/15 追記) ブレッドボードの写真には写っていませんがUSBプラグとPCの間には下記のような電源供給できるHUBが入っています。直接PCにUSBケーブルを繋ぐのでは電源容量が不足する可能性があります。