ESP32でMatterデバイスを作成してHomeKitから操作
Matterとは
- スマートホームの標準規格
- 2022年に1.0がリリースされたばかりの新しい規格
- Connectivity Standards Alliance (CSA)が策定
- CSAは元々Zigbee Allianceという名前で、その名の通りZigbee規格を策定している団体
Matterが生まれるまでの流れ
- ビックテック各社がお得意の囲い込みでスマートホーム業界を独占しようと独自規格を策定
- 独自規格が乱立した結果、互換性の無いデバイスが溢れ、スマートどころかカオスとなる
- 元凶たちが集まり、ロイヤリティーフリーな共通規格としてMatterが作られる
という経緯があるため、Matterでは相互接続性が重視されており、
- Amazon Alexa
- Apple HomeKit
- Google Home
などの各社スマートホームシステムに接続することができます。
Matterデバイスを作ってみる
今回は、ESP32 + Arduino IDEで開発します。ボードマネジャーをインストールしておいてください。
https://github.com/espressif/arduino-esp32
Important
arduino-esp32 v3.3.7, v3.3.8にはバグがあり、Matterが動作しません。
https://github.com/espressif/arduino-esp32/issues/12403
ハードウェア
ESP32-C3を使いました。
このサンプルはESP32-C6やESP32-S3でも動きますが、ESP32, ESP32-S2ではSSIDとパスワードでWiFiに接続する必要があります。
Note
MatterはWi-Fi, Ethernet, Threadに対応しています。BLEは接続時のCommissioningに使われます。
- ESP32-H2,C5はThreadで接続されます
- ESP32-C3,C6,S3はWiFi接続ですが、BLE-Commissioningで認証情報を渡すためパスワードは不要です
- ESP32, ESP32-S2はBLE-Commissioningに対応していないのでSSIDとパスワードを設定してWiFiに接続する必要があります
アプリ
林檎畑の住人なのでiPhoneに標準でインストールされているホームappを使いました。
先述の通り、Matterはスマートホームの標準規格なので他のアプリからも操作できます。(持ってないので未検証)
iOS18以降のiPhoneであればMatterハブ(HomePodとか)が無くても接続できますが、使おうとしたときに接続中と表示され待たされたり、あまり実用的と言えるものではありませんでした。
https://support.apple.com/ja-jp/102135
サンプルコード
0番ピンに接続したLEDをMatterでオンオフする最小限のコードです。
書き込む前にArduinoのツールから以下のように設定します。
USB CDC On Boot → Enable
Partition Scheme → Huge APP (3MB No OTA/1MB SPIFFS)(フラッシュを2MBくらい使います)
Erase All Flash Before Sketch Upload → Enable
#include <Matter.h>
#define LED_PIN 0
MatterOnOffLight OnOffLight;
bool led_toggle(bool state) {
digitalWrite(LED_PIN, state);
return true;
}
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
OnOffLight.begin();
OnOffLight.onChange(led_toggle);
Matter.begin();
if (!Matter.isDeviceCommissioned()) {
Serial.printf("Pairing code: %s\n", Matter.getManualPairingCode().c_str());
Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
}
}
void loop() {}
接続
シリアルモニターに出力されるURLにアクセスするとQRコードが表示されます。
これをホームappの右上の+ボタン→"アクセサリを追加"から読み取ります。
途中、"認定されていないアクセサリ"と表示されますが、当然なので気にせず続けます。
接続されるとホームappの他にも、ウィジェットやコントロールセンターに追加して操作することができるようになります。
HomeKitではデバイスがiCloud同期されるので、iPhoneで追加すればmacやApple Watchなどからも操作できます。
また、自宅にホームハブに対応したAppleデバイス(HomePodかApple TV)を設置していれば、設定をせずとも外出先から操作できるようになります。
その他サンプル
Dimmable Light
調光可能なライト
コード
#include <Matter.h>
#define LED_PIN 0
MatterDimmableLight DimmableLight;
bool set_light(bool state, uint8_t brightness) {
Serial.printf("Status: %s, Brightness: %d\n", state?"ON":"OFF", brightness);
if (state) {
analogWrite(LED_PIN, brightness);
} else {
digitalWrite(LED_PIN, LOW);
}
return true;
}
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
DimmableLight.begin();
DimmableLight.onChange(set_light);
Matter.begin();
if (!Matter.isDeviceCommissioned()) {
Serial.printf("Pairing code: %s\n", Matter.getManualPairingCode().c_str());
Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
}
}
void loop() {}
Color Light
WS2812 (NeoPixel)
コード
0番ピンにNeoPixelのDataピンを接続#include <Matter.h>
#define LED_PIN 0
MatterColorLight ColorLight;
bool setRGBLight(bool state, espHsvColor_t colorHSV) {
if (state) {
espRgbColor_t rgbColor = espHsvColorToRgbColor(colorHSV);
rgbLedWrite(LED_PIN, rgbColor.r, rgbColor.g, rgbColor.b);
} else {
digitalWrite(LED_PIN, LOW);
}
return true;
}
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
ColorLight.begin();
ColorLight.onChange(setRGBLight);
Matter.begin();
if (!Matter.isDeviceCommissioned()) {
Serial.printf("Pairing code: %s\n", Matter.getManualPairingCode().c_str());
Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
}
}
void loop() {}
温度センサー
ESP32内蔵の温度センサーの測定値を表示します。
ESP32自体の発熱があるので気温より高い温度が表示されます。
コード
内蔵のセンサーを使うので配線は不要です#include <Matter.h>
MatterTemperatureSensor TempSensor;
void setup() {
Serial.begin(9600);
TempSensor.begin();
Matter.begin();
if (!Matter.isDeviceCommissioned()) {
Serial.printf("Pairing code: %s\n", Matter.getManualPairingCode().c_str());
Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
}
}
void loop() {
TempSensor.setTemperature(temperatureRead());
Serial.printf("Temp: %.02fC\n", TempSensor.getTemperature());
delay(5000);
}
おわりに
arduino-esp32のexampleには、これ以外にも様々なサンプルがあるので、参考にしてみてください。
https://github.com/espressif/arduino-esp32/tree/master/libraries/Matter/examples