はじめに
Matter公式githubのコードを使ってスマートライトを作ってみました.
結果としてAlexaからのみですが普段使いできそうなものができました.
- Google Homeでは追加時に"Not a Matter-certified device"と表示され登録できなかった.
どうやら自前の証明書を発行した上で許可しないといけないっぽい
https://developers.home.google.com/matter/integration/create?hl=ja
https://developers.home.google.com/matter/build/certificates?hl=ja - Siriは環境が無いので未検証です
ポイント
できるだけシンプルかつ実用的に作るため以下のようにしています
- Matter over Wi-Fiを使用する
Threadを使わないので外部モジュール不要 - 給電制御可能なUSBハブでライトのON/OFFを制御する
市販のUSBライトが使用可能
使用した物
- Raspberry Pi 3 Model B
Ubuntu Server 22.04 LTS (64bit)が動作するもの (おそらく3B以降であればどれでも動く) - microSDカード 32GB
16GBではギリギリかも - BUFFALO 電源連動節電機能付き 4ポートセルフパワーハブ BSH4AE12BK
libusbからUSBポートの給電ON/OFF制御ができるUSBハブ - ダイソー テープライト(30LEDs、1m、ホワイト)
USBに挿すだけで点灯するシンプルなLEDストリップ - Amazon Echo
Matter対応のもの
デバイス構築
OSのインストール
- Raspberry Pi ImagerなどでUbuntu 22.04 LTSをmicroSDカードに書き込む
- 起動してユーザやNWなどを設定
wpa_supplicantの設定
アプリからのデバイス追加の際に使用するWi-Fiを設定するので、設定内容を保存できるようにwpa_supplicantの設定を変更します
- serviceの修正
/etc/systemd/system/dbus-fi.w1.wpa_supplicant1.serviceのExecStart=の行を以下のように変更
ExecStart=/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
- confの修正
/etc/wpa_supplicant/wpa_supplicant.conf の内容を以下のように変更
ctrl_interface=DIR=/run/wpa_supplicant
update_config=1
必要なライブラリのインストール
sudo apt-get install -y git gcc g++ python pkg-config libssl-dev libdbus-1-dev libglib2.0-dev ninja-build python3-venv python3-dev unzip pi-bluetooth avahi-utils
# USBハブの給電制御用
sudo apt-get install -y libusb-dev
swapの追加
アプリのビルドにメモリを使用するのでswapを追加しておく
2GB以上のメモリがあればスキップしてOK(たぶん)
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 0600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
コードのcloneと環境のセットアップ
git clone https://github.com/project-chip/connectedhomeip.git --branch v1.0.0
cd connectedhomeip
./scripts/checkout_submodules.py --shallow --platform linux
./scripts/build/gn_bootstrap.sh
source scripts/activate
サンプルアプリの変更
examples/lighting-app/linux以下のLinux用サンプルアプリをUSBハブの電源供給をON/OFFするように変更
diff --git a/examples/lighting-app/linux/BUILD.gn b/examples/lighting-app/linux/BUILD.gn
index 721f408437..edc31c6c39 100644
--- a/examples/lighting-app/linux/BUILD.gn
+++ b/examples/lighting-app/linux/BUILD.gn
@@ -94,6 +94,7 @@ executable("chip-lighting-app") {
cflags = [ "-Wconversion" ]
}
+ libs = [ "usb" ]
output_dir = root_out_dir
}
diff --git a/examples/lighting-app/linux/include/CHIPProjectAppConfig.h b/examples/lighting-app/linux/include/CHIPProjectAppConfig.h
index e919666bb9..73a6984fdf 100644
--- a/examples/lighting-app/linux/include/CHIPProjectAppConfig.h
+++ b/examples/lighting-app/linux/include/CHIPProjectAppConfig.h
@@ -40,7 +40,13 @@
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE 1
#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 257 // 0x0101 = 257 = Dimmable Bulb
+//#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 256 // 0x0100 = 256 = Light Bulb
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_NAME 1
#define CHIP_DEVICE_CONFIG_DEVICE_NAME "Test Bulb"
+
+#define FATCONFDIR "/var/tmp"
+#define SYSCONFDIR "/var/tmp"
+#define LOCALSTATEDIR "/var/tmp"
+#define CHIP_CONFIG_KVS_PATH "/var/tmp/chip_kvs"
diff --git a/examples/lighting-app/linux/main.cpp b/examples/lighting-app/linux/main.cpp
index 7813c59979..42acfd8ab8 100644
--- a/examples/lighting-app/linux/main.cpp
+++ b/examples/lighting-app/linux/main.cpp
@@ -25,6 +25,13 @@
#include <app/clusters/network-commissioning/network-commissioning.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/Linux/NetworkCommissioningDriver.h>
+#include <usb.h>
+
+#define USB_PORT_FEAT_POWER 8
+#define CTRL_TIMEOUT 1000
+#define USB_RT_PORT (USB_TYPE_CLASS|USB_RECIP_OTHER)
+#define HUB_ID_VENDOR 0x05e3
+#define HUB_ID_PRODUCT 0x0608
using namespace chip;
using namespace chip::app;
@@ -73,6 +80,55 @@ void ApplicationInit()
#endif
}
+void UsbPowerCtrl(int id_vendor, int id_product, bool pwr)
+{
+ struct usb_bus *busses;
+ struct usb_bus *bus;
+ busses = usb_get_busses();
+ for (bus = busses; bus; bus = bus->next)
+ {
+ struct usb_device *dev;
+ for (dev = bus->devices; dev; dev = dev->next)
+ {
+ usb_dev_handle *udh = NULL;
+ if (dev->descriptor.idVendor == id_vendor
+ && dev->descriptor.idProduct == id_product)
+ {
+ udh = usb_open(dev);
+ int request = pwr ? USB_REQ_SET_FEATURE : USB_REQ_CLEAR_FEATURE;
+ int feature = USB_PORT_FEAT_POWER;
+ for( int i = 1; i <= 4; i++)
+ {
+ usb_control_msg(udh, USB_RT_PORT, request, feature, i, NULL, 0, CTRL_TIMEOUT);
+ }
+ usb_close(udh);
+ }
+ }
+ }
+}
+
+void ActionInitiated(LightingManager::Action_t aAction)
+{
+ if (aAction == LightingManager::ON_ACTION)
+ {
+ UsbPowerCtrl(HUB_ID_VENDOR, HUB_ID_PRODUCT, true);
+ }
+ else if (aAction == LightingManager::OFF_ACTION)
+ {
+ UsbPowerCtrl(HUB_ID_VENDOR, HUB_ID_PRODUCT, false);
+ }
+}
+
+void ActionCompleted(LightingManager::Action_t aAction)
+{
+ if (aAction == LightingManager::ON_ACTION)
+ {
+ }
+ else if (aAction == LightingManager::OFF_ACTION)
+ {
+ }
+}
+
int main(int argc, char * argv[])
{
if (ChipLinuxAppInit(argc, argv) != 0)
@@ -80,7 +136,12 @@ int main(int argc, char * argv[])
return -1;
}
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ UsbPowerCtrl(HUB_ID_VENDOR, HUB_ID_PRODUCT, false);
LightingMgr().Init();
+ LightingMgr().SetCallbacks(ActionInitiated, ActionCompleted);
ChipLinuxAppMainLoop();
return 0;
- 簡単な説明
- CHIPProjectAppConfig.h
- (CHIP_DEVICE_CONFIG_DEVICE_TYPE: Dimmable Bulbから変更したかったが効果なしだった)
- #define 〜DIR, ~PATH: 生成ファイルの場所を再起動しても消えない/var/tmpに変更
- main.cpp
- #define HUB_ID_VENDOR, HUB_ID_PRODUCT: 該当USBハブを特定するための製品固有値
- UsbPowerCtrl(): 下記参考記載のhub-ctrl.cを参考にしたidVendor/IdProductを元に電源供給ON/OFFする関数
(おそらくハブの実装起因で)USBポート毎のON/OFFがうまく動作しないので全ポート(1~4)を一括操作 - LightingMgr().SetCallbacks(ActionInitiated, ActionCompleted)
コントローラーからのON/OFF指示に対するCallbackにUsbPowerCtrl()を呼ぶ関数を登録
- CHIPProjectAppConfig.h
サンプルアプリのビルド
cd examples/lighting-app/linux
gn gen out/debug
ninja -C out/debug
サンプルアプリの自動起動の設定
# サンプルアプリのコピー
sudo mkdir /opt/lighting-app
sudo cp out/debug/chip-lighting-app /opt/lighting-app/
# systemdのサービスファイルの用意
cat <<EOF > chip-lighting-app.service
[Unit]
Description=CHIP lighting app
After=network.target
[Service]
Type=Simple
ExecStart=/opt/lighting-app/chip-lighting-app --wifi
Restart=on-failure
[Install]
WantedBy=default.target
EOF
sudo cp chip-lighting-app.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable chip-lighting-app.service
起動
事前にUSBハブ、テープライトを接続しておく
sudo systemctl start chip-lighting-app.service
(サンプルアプリが起動できればテープライトが消灯する)
Alexaアプリから作成したデバイスを登録
Alexaアプリのデバイス追加(+ボタン)からウィザードにしたがってデバイスを追加する
- QRコードはサンプルデフォルトの以下を使用する
https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3A-24J042C00KA0648G00 - 接続するWi-FiはEchoと同じNWを指定する
デバイスの操作
アプリ上から(他のデバイスと同じように)ON/OFFが可能
※アプリ上は照度やカラーも操作できるがサンプルアプリもハードウェアも対応してないので動作しない
※登録直後の数回はON/OFF操作が効かないことがある
その他
- 一度設定すれば電源を切ってもOKだが操作可能になるまでかなり時間がかかる
(コントローラー側がデバイスを認識し直すまでにラグがある...?) - サンプルアプリを初期化したい場合は/var/tmp/chip_*を削除する
- Callbackに好きな処理書けば良いのでアイデア次第で何でもできそう...!
感想
Matterのおかげでデバイスだけの自作でAlexaから使えるスマートライトができました.
スマートデバイス作成にはデバイス管理のサーバ,Alexaスキル等のplatform連系アプリ, デバイスと管理サーバ連系まわりなどが必要だったのでMatterの登場によって非常に敷居が下がったんではないでしょうか.
追記
chi-lighting-appがかなり標準出力を吐くのでログまわりを抑制しないとディスクを使い切ります(ました).
以下の様に jounalログの最大サイズを制限し、rsyslog側へのログ転送も停止すると良いです.
/etc/systemd/journald.conf
[Journal]
SystemMaxUse=50M
ForwardToSyslog=no
変更後はOS/journaldの再起動で設定を反映させます.
参考