ESP8266 (ESP-01) をArduino IDEで使う(3: MQTT編)

DIYする

前回、ESP8266を搭載したESP-01を、Arduino IDEでプログラミングできるよう設定し、OTAによりプログラム更新しました。今回は、MQTTメッセージをパブリッシュ、サブスクライブしてみます。OTAも引き続き有効にします。

ESP8266 (ESP-01) をArduino IDEで使う(1: Lチカ編)
これまで、ESP32を使ってHomeKitで動作するアクセサリをDIYしてきました。ESP32の下位モデルにESP8266があります。シンプルなアクセサリならばESP8266でも作れますし、市販のスマートプラグ、スイッチ、センサー類にはES...
ESP8266 (ESP-01) をArduino IDEで使う(2: OTA編)
前回、ESP8266を搭載したESP-01を、Arduino IDEでプログラミングできるよう設定し、単体で動作させました。 今回は、USBアダプタに接続しないで、ESP-01単体のままプログラム更新できるように、Arduino OTAを使...

以下は、上記の記事の続きです。

MQTTメッセージをパブリッシュ

まずは、helloという文字列メッセージを毎秒パブリッシュする、MQTTクライアントプログラムを作りました。使用するMQTTトピックスはmqttthing/testとしました。

#include <EspMQTTClient.h>

EspMQTTClient *client; //instance of MQTT
const char SSID[] = "xxxxxxxx"; //WiFi SSID
const char PASS[] = "XXXXXXXX"; //WiFi password
char CLIENTID[] = "ESP8266_8465"; //something random 何でも良いです
const char  MQTTADD[] = "192.168.xxx.xxx"; //MQTT Broker IP address
const short MQTTPORT = 1883; //Broker port
const char  MQTTUSER[] = "";//Can be omitted if not needed
const char  MQTTPASS[] = "";//Can be omitted if not needed
const char  PUBTOPIC[] = "mqttthing/test";

void setup() {
  client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
}

void onConnectionEstablished() {
}

void loop() {
  client->publish(PUBTOPIC,"hello");
  client->loop();
  delay(1000);
}

これをコンパイルして、ESP-01にダウンロードして、動作させます。一方で、このトピックスをmosquitto_subコマンドでサブスクライブします。MQTTブローカーが稼働するRaspberry Piにsshして、以下のコマンドを出します。すると、helloの文字が、1秒ごとに表示されます。

$ mosquitto_sub -t mqttthing/test/#
hello
hello
hello
hello
hello

MQTTプログラムをOTA対応する

次に、このプログラムもOTAで更新できるようにします。前回の記事と同様に、Arduino OTAを動かします。追加するのは、以下でハイライトした5行です。

#include <EspMQTTClient.h>
#include <ArduinoOTA.h>

EspMQTTClient *client; //instance of MQTT
const char SSID[] = "xxxxxxxx"; //WiFi SSID
const char PASS[] = "XXXXXXXX"; //WiFi password
char CLIENTID[] = "ESP8266_8465"; //something random 何でも良いです
const char  MQTTADD[] = "192.168.xxx.xxx"; //Broker IP address
const short MQTTPORT = 1883; //Broker port
const char  MQTTUSER[] = "";//Can be omitted if not needed
const char  MQTTPASS[] = "";//Can be omitted if not needed
const char  PUBTOPIC[] = "mqttthing/test";

void setup() {
  client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
}

void onConnectionEstablished() {
  ArduinoOTA.setHostname("ESP8266_OTA");
  ArduinoOTA.setPasswordHash("3294................105f4241e");
  ArduinoOTA.begin(); 
} 

void loop() { 
  ArduinoOTA.handle();
  client->publish(PUBTOPIC,"hello"); 
  client->loop(); 
  delay(1000); 
} 

OTAを開始するためには、OTAのホスト名、パスワードを設定して、ArduinoOTA.begin()を呼び出します。先の記事のプログラムではsetup()の中でWi-Fiを設定し、Wi-Fi接続終了した段階で、OTAの設定をしました。今回は、MQTTクライアントライブラリを使ったので、Wi-Fi接続はMQTTライブラリがやってくれます。そして、Wi-Fi接続完了するとonConnectionEstablished()関数が呼ばれます。なので、その関数の中に、Arduino OTAの初期化にあたる部分を記述しました。

これでOTAが有効になったので、ESP-01をUSBアダプターから外して、単体で動作させても、Wi-Fi経由でプログラム書き換え可能になりました。

MQTTメッセージをサブスクライブする

上のプログラムは、MQTTメッセージをパブリッシュするプログラムでした。次に、MQTTメッセージをサブスクライブするプログラムを作ります。具体的には、mqttthing/esp8266/setトピックスに流れるメッセージをサブスクライブします。さらに、そのメッセージがtrueだったら青色LEDを点灯し、falseだったら消灯するプログラムを作ります。このため、先のプログラムを以下に書き換えます。ハイライトした8行が追加された部分です。

#include <EspMQTTClient.h>
#include <ArduinoOTA.h>

EspMQTTClient *client; //instance of MQTT
const char SSID[] = "xxxxxxxx"; //WiFi SSID
const char PASS[] = "XXXXXXXX"; //WiFi password
char CLIENTID[] = "ESP8266_8465"; //something random 何でも良いです
const char  MQTTADD[] = "192.168.xxx.xxx"; //Broker IP address
const short MQTTPORT = 1883; //Broker port
const char  MQTTUSER[] = "";//Can be omitted if not needed
const char  MQTTPASS[] = "";//Can be omitted if not needed
const char  SUBTOPIC[] = "mqttthing/esp8266";
const int blueLED=1;

void setup() {
  pinMode(blueLED,OUTPUT);
  client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
}

void onConnectionEstablished() {
  ArduinoOTA.setHostname("ESP8266_OTA");
  ArduinoOTA.setPasswordHash("3294................105f4241e");
  ArduinoOTA.begin(); 
  client->subscribe(SUBTOPIC, onMessageReceived); //callback for subscription
} 

void onMessageReceived(const String& msg) {
  if(msg.compareTo("true")==0) digitalWrite(blueLED,LOW);
  else if(msg.compareTo("false")==0) digitalWrite(blueLED,HIGH);
}

void loop() { 
  ArduinoOTA.handle();
  client->loop(); 
} 

MQTTの設定が終わったところ(onConnectionEstablished()の場所)で、mqttthing/esp8266トピックにメッセージが来た時に起動するコールバック関数を定義してます。この名前をonMessageReceived()としています。コールバック関数の中では、メッセージを検査し、trueだったらLED点灯、falseだったら消灯してます。

このプログラムを起動し、MQTTブローカーが動作しているRaspberry Piにsshして、

$ mosquitto_pub -t mqttthing/esp8266 -m true

というコマンドをタイプして、トピックスにメッセージtrueを流すと、LEDが点灯します。

また、

$ mosquitto_pub -t mqttthing/esp8266 -m false

というコマンドをタイプして、トピックスにメッセージfalseを流すと、LEDが消灯します。

HomeKitからLチカする

MQTTで制御できれば、HomeKitからも制御可能です。以下の図のように、Raspberry Piがサーバとして用意されていて、その上でMQTTブローカーのMosquittoと、Homebridgeが動作している環境を前提とします。また、MQTTベースのHomeKitアクセサリを作り出すためのプラグインとしてMQTTThingがインストールされているとします。

この環境で、Homebridgeの設定ファイルに以下の記述をすると、MQTTメッセージでOn/Offする電球アクセサリを定義できます。

{
  "type": "lightbulb-OnOff",
  "name": "ESP01LED",
  "topics": {
    "setOn": "mqttthing/esp8266"
  },
  "accessory": "mqttthing"
}

この結果、iPhoneやMacのホーム.appに、電球アクセサリが現れます。タップまたはクリックすると、On/Offが切り替わり、これに連動してESP-01の青色LEDもOn/Offします。

   

   

動画も撮影しましたのでご覧ください。

まとめ

ESP8266開発ボードESP-01に搭載の青色LEDを、MQTTメッセージによりOn/Offするプログラムを作成しました。OTAにも対応しています。MQTTThingプラグインを入れたHomebridgeにより、HomeKitからスマート電球として操作できました。

ESP-01でOTA対応のMQTTプログラムが作れるようになったので、HomeKitで動かすアクセサリをいろいろDIYできそうです。ESP32よりも安価に小型に作れるので、活用していきたいと思います。

コメント

タイトルとURLをコピーしました