この記事では、ESP32のオンボードボタンとLEDを、MQTTを介してHomeKitに接続します。その結果、iPhoneやMacのホーム.appには、このESP32が照明器具として表示されて、LEDのOn/Offが可能になります。ESP32/ESP8266で電子工作して、HomeKitに組み込む際の参考になればと思います。
MQTTをHomeKitと接続するために、この記事ではHomebridgeとmqttthingプラグインを使いました。Home Assistantでも同様のことが可能です。Home Assistantを使えば、Apple以外に, Google, Amazonのすべてのエコシステムに接続できるはずです。
MQTTを使うメリット
最近はEspressif社のArduinoサポートが充実して、ESP32でのMatterプログラミングが楽になりました。MQTTではなく、Matterで作成すれば、MQTTブローカーや、Homebridge, Home Assistantなどが不要で、ESP32単独で、Apple, Google, Amazonのエコシステムに接続できます。
でも軽くてわかりやすいMQTTには、いまだに以下のメリットがあると考えてます。
- ESPのプログラムサイズがコンパクト
- 非力だけど安価なESP8266でも使える
- Mosquitto_subコマンドなどでMQTTのメッセージ交換の様子をモニターできるので動作確認が楽
- Mosquitto_pubコマンドなどでESPやHomeKitの動作を確認できるので、デバッグが楽
システムの構成
Raspberry Piで、HomebridgeとMosquittoが動いている環境で作成しました。また、Homebridgeには、mqttthingプラグインを入れてます。
Mosquittoは、MQTTブローカーとして動作し、ESP32/ESP8266と、mqttthingプラグインの間でMQTTメッセージを仲介します。Homebridgeは、mqttthingプラグインとともに、MQTTメッセージに基づいてHomeKitアクセサリを作り上げます。そして、HomeKit上のiPhoneやMacとHomeKit Accessory Protocol (HAP) で通信します。
HomebridgeとMosquittoは、Rasbpetty Pi以外に、Linux, Windows, 各種NAS、Macなどで動作します。HomebridgeをRaspberry Piにインストールする場合は、Raspberry Pi ImagerのOS選択で、Homebridgeを選択してインストールするのが簡単です。(64bit版が推奨です)
Mosquittoは、
apt install mosquitto mosquitto-clients
などすればインストールできます。
ESP32でMQTTプログラミング
ESP32/ESP8266で使えるMQTTライブラリは多数あります。ここでは、EspMQTTClientを使いました。ESP32とESP8266の両方で使えます。APIも洗練されていて、使いやすいです。ただ、最近アップデートが滞っています。ずっとESP8266ばかり使っていたのですが、今回久々にESP32でコンパイルしたら、エラーで止まりました。Espressifのボードマネージャが更新されて、ESP32用のWiFiのヘッダファイルが変更されて動かなくなったようです。ライブラリのEspMQTTClient.hファイルを開いて、WiFiClient.hをインクルードする行を、WiFi.hに書き換えるとコンパイルできました。diffで説明すると以下です。この情報はこちらに書かれてます。
% diff EspMQTTClient.h.old EspMQTTClient.h.new
22c22
< #include <WiFiClient.h>
---
> #include <WiFi.h>
今回は、たまたま手元にあったので、ESP32を使います。これで、On/Offする照明器具を模したプログラムを作ります。ESP32には、オンボードの青色LEDが付いています。GPIOピンの2番に接続されてます。また、タクトスイッチのBOOTボタンがあり、これはGPIO 1番に接続されています。このLEDを照明、BOOTボタンを照明器具のOn/Offボタンに見立てます。下の写真では、スイッチとLEDの場所を白丸で示してます。
人が、BOOTボタンを押すと、青色LEDがOn/Offとトグル変化します。この時、MQTTのmqttthing/LEDLight/setトピックスに、"true", "false"の文字メッセージを流します。
また、MQTTのmqttthing/LEDLight/getトピックスに、"true"または"false"のメッセージが流れてきたら、青色LEDをOnまたはOffします。
このプログラムが動くESP32のGPIOピンに、ちゃんとしたスイッチと、リレーなどを接続すれば、室内に設置するネット対応照明器具が作れるでしょう。
プログラムは以下です。詳細な説明は、EspMQTTClientのgithubにあるプログラム例を見てください。
#include "EspMQTTClient.h"
const int LEDpin = 2; //ESP32 onboard blue LED
const int BTNpin = 0; //ESP32 onboard BOOT button
const char SUBTOPIC[] = "mqttthing/LEDLight/set"; //mqtt topic to subscribe
const char PUBTOPIC[] = "mqttthing/LEDLight/get"; //mqtt topic to publish
EspMQTTClient client(
"WifiSSID",
"WifiPassword",
"192.168.xxx.xxx",// MQTT Broker server ip (RPi)
"MQTTUsername", // Can be omitted if not needed
"MQTTPassword", // Can be omitted if not needed
"TestClient" // Client name that uniquely identify your device
);
void setup() {
pinMode(LEDpin,OUTPUT);
pinMode(BTNpin,INPUT);
}
void onConnectionEstablished() {
client.subscribe(SUBTOPIC, onMessageReceived); //set callback
}
void onMessageReceived(const String& msg) {
if(msg.compareTo("true")==0) digitalWrite(LEDpin,HIGH);
else if(msg.compareTo("false")==0) digitalWrite(LEDpin,LOW);
}
int previousBTN = HIGH;
void loop() {
int currentBTN = digitalRead(BTNpin);
if(previousBTN != currentBTN) { //toggle LED when BTN HIGH-to-LOW
if(currentBTN == LOW) {
bool targetLED = !digitalRead(LEDpin);
digitalWrite(LEDpin, targetLED);
client.publish(PUBTOPIC,(targetLED ? "true" : "false"));
}
previousBTN = currentBTN;
}
client.loop();
}
簡単に説明すると、
- EspMQTTClientをインスタンス化するとWiFiとMQTTの設定が始まる
- 設定が終わると、onConnectionEstablished()が呼ばれるので、その中でcallback関数 onMessageReceived()を設定する
- メッセージが来るとonMessageReceived()が呼ばれるので、メッセージがtrueならLEDをOn、falseならOffにする
- loop()ではBOOTスイッチを読み込み、HIGH->LOWと変化したら、LEDをトグルする。同時に、trueまたはfalseをパブリッシュする
という流れです。
Raspberry Piの上で、mosquitto_subとmosquitto_pubコマンドでこの様子を確認できます。BOOTボタンを4回押すと、
$ mosquitto_sub -t mqttthing/LEDLight/# -v
mqttthing/LEDLight/get true
mqttthing/LEDLight/get false
mqttthing/LEDLight/get true
mqttthing/LEDLight/get false
というようにメッセージが流れます。また、mosquitto_pubコマンドで以下のようにtrue, falseメッセージを流すと、
$ mosquitto_pub -t mqttthing/LEDLight/set -m true
$ mosquitto_pub -t mqttthing/LEDLight/set -m false
$ mosquitto_pub -t mqttthing/LEDLight/set -m true
$ mosquitto_pub -t mqttthing/LEDLight/set -m false
LEDが、点灯、消灯、点灯、消灯します。この例は、Mosquittoが作動している同一のRaspberry Piで動かしているので、IPアドレスを省略しています。
Homebridgeで設定
ここまで動作したら、次はHomebridgeの設定ファイルの、accessoriesの項目に、以下を追加します。
"accessories": [
{
"accessory": "mqttthing",
"type": "switch",
"name": "LEDLight",
"topics": {
"getOn": "mqttthing/LEDLight/get",
"setOn": "mqttthing/LEDLight/set"
}
},
accessoryの項目は、担当するプラグインを指定します。switchとして設定し、getOnとsetOnに対応するトピックスを指定します。getOnのトピックスは、物理スイッチなど外部からの操作でOn/Offしたことを、HomeKit側へ伝える場合に使います。setOnトピックスは、HomeKitからの指令でOn/Offすることを、デバイス側へ伝える場合に使います。それぞれ、Onの時にデフォルトで"true"という文字メッセージが、Offの時に"false"という文字メッセージが流れます。On/Offに対応するこのメッセージは、変更可能です。
HomeKitでの動作確認
設定が終了し、Homebridgeを再起動すると、iPhoneやMacのホーム.appに以下のようなスイッチが現れます。
これをクリックすると、ESP32の青色LEDがOn/Offします。またESP32のBOOTスイッチをクリックすると、ホーム.appのスイッチがOn/Offします。
まとめ
MQTTメッセージに従って、ESP32のLEDをOn/Offするプログラムを作りました。これをHomebridgeと連動させることで、HomeKit上のアクセサリとして、iPhoneやMacのホーム.appから使えるようにしました。
今回作成したプログラムのサイズは、980kBでした。安価なESP8266ボードでも問題なく動作します。同様の機能のプログラムをMatterで作成すると、1.7MBです。一般的なESP32ボードが4MBなので、OTAでの運用を考えるとギリギリのサイズです。
mqttthingにより、HomeKitにつながるほとんどの種類のアクセサリを定義できます。例えば、照明器具、スマートプラグ、スイッチ、温度計、湿度計、光センサ、人感センサ、振動センサ、開閉センサ、炭酸ガスセンサ、煙センサ、漏水センサ、ドアベル、冷暖房機器、扇風機、電動カーテン、電動ブラインド、自動ドア、ガレージドア、電気錠、電動バルブ、テレビ、アンプ、防犯システムなどを作ることができます。
mqttthingのgithubページには、これらのアクセサリ一覧と、MQTTトピックスが説明されてます。メッセージの内容やタイミングが分かりにくい場合は、本文で示したようにHomebridgeに設定し、mosquittto_subでモニターし、mosquitto_pubで応答を返し、HomeKitでの振る舞いを理解することもできます。それに従って、MQTTメッセージを出して受け取るプログラムを作れば、アクセサリを作れます。あとはESP32/ESP8266を使った電子工作の腕次第です。



