スマートホームの新標準「Matter」のサンプルを動かしてみる

Nature株式会社ファームウェアエンジニアの中林 (id:tomo-wait-for-it-yuki) です。スマートリモコンNature Remoシリーズを手がけるNatureでは、スマートホーム新標準のMatter1に注目しています。

GitHubでMatterのプロトコルスタックやいくつかのサンプルが公開されて2います。今回は比較的簡単に動かせるM5Stack3のBLE/無線LANを使ったサンプルを試しながらMatterについて学んでみたいと思います。

Matter

MatterはCSA (Connectivity Standards Alliance) が策定している新しいスマートホームの標準規格です。これまでのスマートホームバイスは各デバイスメーカーがそれぞれの規格に沿って開発していましたが、各社のデバイスが共通して使う規格を決めることで、デバイス間の相互接続性を高めよう、という狙いです。Google, Apple, Amazonなどが参画しており、今後スマートホームバイスの標準になっていくことが期待できます。

無線LAN, BLE, Threadといった通信規格の上位にIPv6をベースとする共通プロトコルを定義しています。このことにより、下位の通信規格に依存せず、相互接続を可能とします。元々CHIP (Connected Home over IP) という名称で、まだところどころにその名残が残っています。技術者視点だとConnected Home over IPはずばり何したいのかそのまんまの名称だったわけですね。

サンプル動かしてみる

注意!

  • 2021/09/29時点の手順です
  • 著者の環境はUbuntu20.04です

用意するものはこれだけです。

  • ホストPC
  • M5Stack BASICを1つ

M5Stack Core2はディスプレイ非対応とのことなので、動かせるものを全て動かしたい場合、M5Stack BASICが安定択です。

M5Stackでall-clusters-appサンプルを動かし、ホストPCのデバイス制御用CLIツールからコミッショニングおよび制御を行います。

all-clusters-app

これまでいくつかサンプル動かしてみましたが、お手軽に雰囲気掴みたい場合、examples/all-clusters-app/esp324を使うのがおすすめです。all-clusters-appではデバイスのコミッショニング (機器の初期設定) とデバイスの制御を試すことが可能です。

今回はM5Stackを使用しますが、DevKitCなどもっと安価なデバイスでも動きます。RISC-Vコアが搭載されたESP32C3-DevKitMで動かすこともできます。デバイスを用意したら、all-clusters-appのREADME.md5に記載の手順通り進めていきます。

all-clusters-appでは、次のようなデバイスがあるかのようにM5Stackが振る舞います。

  • 時計 (バッテリ、心拍計歩数計)
  • ライト2つ
  • 温度計
  • ドアロック
  • ガレージ2つ (ドア)

時計のバッテリ残量やドアロックの状態などは、M5Stackの画面とボタンから変更することができます。ライトのようなコントローラから制御するデバイスは制御に合わせて画面の表示内容が変わります。

サンプルのビルド

次の手順でサンプルをビルドします。

  1. ESP-IDF v4.3のセットアップ
  2. Matter開発環境のセットアップ
  3. サンプルアプリケーションのビルド

ESP-IDF v4.3のセットアップ

ESP-IDF (Espressif ESP32 IoT Development Framework) とxtensa用のビルドツールチェインをセットアップします。セットアップ手順は下記を参照ください。

https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/get-started/index.html

環境変数IDF_PATHが設定されていることを確認した上で、ESP-IDFの環境をセットアップし、Matter開発環境をセットアップします。

source $IDF_PATH/export.sh
# このコンソールで次の手順へ

Matter開発環境のセットアップ

submoduleのcloneなどあるので、サンプルをビルドする前に実行します。

git clone https://github.com/project-chip/connectedhomeip.git
cd connectedhomeip
source ./scripts/bootstrap.sh
source ./scripts/activate.sh

2回目以降はsource ./scripts/activate.shだけでOKです。

サンプルアプリケーションのビルド

# connectedhomeipのルートディレクトリから
cd examples/all-clusters-app/esp32

デフォルトではESP32-DevKitCがターゲットになっているので、M5Stackに切り替えます。

idf.py menuconfig

Demo -> Device TypeからM5Stackを選択して、保存します。

サンブルアプリケーションをビルドします。

idf.py build

サンプルの実行

M5StackをホストPCにUSBケーブルで接続して、ファームウェアを書き込みます。

idf.py flash monitor

次のような画面が表示されればOKです。CHIPと表示されているのはご愛嬌ですね。

f:id:tomo-wait-for-it-yuki:20210927164500p:plain
all-clusters-app起動画面

コミッショニングと制御

ホストPCからM5Stackのコミッショニング (初期設定) を実施して、Matterデバイスとして制御します。具体的にはBLE経由でコミッショニングして、M5StackをホストPCと同じ無線LANアクセスポイントに接続し、無線LAN経由で制御します。

CLIツールのセットアップ

ホストPCからM5Stackのコミッショニングと制御を行うためのCLIツールをセットアップします。

# connecteddhomeipのルートディレクトリ
./scripts/build_python.sh -m platform
source ./out/python_env/bin/activate

python contollerを起動します。

$ chip-device-ctrl
[1632729563.198847][112356:112356] CHIP:DL: Avahi client registered
[1632729563.199274][112356:112356] CHIP:ZCL: Using ZAP configuration...
# ...
[1632729563.200628][112356:112356] CHIP:CTL: Loaded credentials successfully
[1632729563.203879][112356:112364] CHIP:DL: Platform main loop started.
Chip Device Controller Shell

chip-device-ctrl >

BLE経由のコミッショニング

まずBLEをスキャンします。無事見つかりました。

chip-device-ctrl > ble-scan

2021-09-29 09:52:43,642 ChipBLEMgr   INFO     scanning started
2021-09-29 09:52:45,344 ChipBLEMgr   INFO     Name            = None
2021-09-29 09:52:45,344 ChipBLEMgr   INFO     ID              = 5f294ca3-b123-465a-aa2f-e48633e07dbe
2021-09-29 09:52:45,345 ChipBLEMgr   INFO     RSSI            = -56
2021-09-29 09:52:45,345 ChipBLEMgr   INFO     Address         = 08:3A:F2:68:37:1E
2021-09-29 09:52:45,347 ChipBLEMgr   INFO     Pairing State   = 0
2021-09-29 09:52:45,347 ChipBLEMgr   INFO     Discriminator   = 3840
2021-09-29 09:52:45,347 ChipBLEMgr   INFO     Vendor Id       = 9050
2021-09-29 09:52:45,347 ChipBLEMgr   INFO     Product Id      = 17729
2021-09-29 09:52:45,348 ChipBLEMgr   INFO     Adv UUID        = 0000fff6-0000-1000-8000-00805f9b34fb
2021-09-29 09:52:45,348 ChipBLEMgr   INFO     Adv Data        = 00000f5a234145
2021-09-29 09:52:45,348 ChipBLEMgr   INFO

M5StackにBLEで接続します。

chip-device-ctrl > connect -ble 3840 20202021 135246

Device is assigned with nodeid = 135246
[1632877083.478955][19975:19979] CHIP:BLE: BLE removing known devices.
[1632877083.487762][19975:19979] CHIP:BLE: BLE initiating scan.
[1632877084.025243][19975:19979] CHIP:BLE: New device scanned: 08:3A:F2:68:37:1E
[1632877084.025283][19975:19979] CHIP:BLE: Device discriminator match. Attempting to connect.

# たくさんログが出る

[1632877096.354977][19975:19983] CHIP:ZCL: NOCResponse:
[1632877096.354993][19975:19983] CHIP:ZCL:   StatusCode: 0
[1632877096.355000][19975:19983] CHIP:ZCL:   FabricIndex: 0
[1632877096.355007][19975:19983] CHIP:ZCL:   DebugText: 0
[1632877096.355018][19975:19983] CHIP:CTL: Device returned status 0 on receiving the NOC
[1632877096.355028][19975:19983] CHIP:CTL: Operational credentials provisioned on device 0x23baba8
Secure Session to Device Established
Device temporary node id (**this does not match spec**): 135246

これでデバイスとのセキュアセッションが確立できたようです。おおよそ10秒くらいでしょうか?ちょっとわかりにくいですが、BLE接続ができるとM5Stack画面の左側にある青色の四角が明るくなります。

f:id:tomo-wait-for-it-yuki:20210929133413p:plain
BLE接続後

少しコマンド connect -ble 3840 20202021 135246 のパラメータを説明しておきます。384020202021は、それぞれ識別用のIDとPINコードで、ビルド時のパラメータとして設定可能です。135246はノードIDでこの後のコマンドでは一貫してこのIDを使用しなければなりません。接続時の最後のログにDevice temporary node id (**this does not match spec**): 135246と出ていて、一時的なデバイスノードIDであろうことがわかります。ちなみにconnect-ble実行時にこのパラメータを指定しなければ、chip-device-ctrlがIDを生成して表示してくれます。

無線LANアクセスポイントに接続するために、SSID/passwordを設定し、無線LANネットワークを有効化します。

chip-device-ctrl > zcl NetworkCommissioning AddWiFiNetwork 135246 0 0 ssid=str:TESTSSID credentials=str:TESTPASSWD breadcrumb=0 timeoutMs=1000
chip-device-ctrl > zcl NetworkCommissioning EnableNetwork 135246 0 0 networkID=str:TESTSSID breadcrumb=0 timeoutMs=1000

1つ目のコマンドでSSID/passwordをM5Stackに送信します。TESTSSIDTESTPASSWDの部分は使用するアクセスポイントのものに置き換えて実行します。2つ目のコマンドでnetworkIDで指定したアクセスポイントに接続します。

M5Stack側のログでもアクセスポイントに接続したことがわかります。

I (390625) wifi:new:<3,1>, old:<1,1>, ap:<255,255>, sta:<3,1>, prof:1
I (391125) wifi:state: init -> auth (b0)
I (391135) wifi:state: auth -> assoc (0)
I (391155) wifi:state: assoc -> run (10)
I (391165) wifi:connected with TESTSSID, aid = 3, channel 3, 40U, bssid = xx:xx:xx:xx:xx:xx
I (391175) wifi:security: WPA2-PSK, phy: bgn, rssi: -50
I (391185) wifi:pm start, type: 1

I (391185) wifi:AP's beacon interval = 102400 us, DTIM period = 3

アクセスポイントに接続すると黄色い四角が明るくなります。

f:id:tomo-wait-for-it-yuki:20210929133526p:plain
アクセスポイント接続後

もうBLEは使わないのでBLEを切断します。これ以降はBLEのadvertiseをしなくなるようで、scanに引っかからなくなります。BLE切断しても青色の四角は明るいままのようです。

chip-device-ctrl > close-ble

M5StackのIPアドレスを取得します。M5Stack上でmDNSが動いており、これで通信するIPアドレスが取得できます。

chip-device-ctrl > resolve 0 135246

[1632878616.341733][38115:38123] CHIP:DL: Avahi resolve found
[1632878616.341806][38115:38123] CHIP:DIS: Node ID resolved for 0x000000000002104E to [192.168.1.16]:5540
Node address has been updated
[1632878616.342207][38115:38123] CHIP:CTL: OperationalDiscoveryComplete for device ID 135246
[1632878618.350885][38115:38123] CHIP:EM: Received message of type 0x31 with vendorId 0x0000 and protocolId 0x0000 on exchange 39023
Commissioning complete
Current address: 192.168.1.16:5540

ログを見ると0x000000000002104E (135246)[192.168.1.16]:5540に解決された、とあります。これでコミッショニングは完了です。次はデバイスの制御を試します。

バイスの制御

まずはライトのOn/Offを制御してみます。上から1番目の緑の四角が明るくなります。

chip-device-ctrl > zcl OnOff On 135246 1 1

f:id:tomo-wait-for-it-yuki:20210929133625p:plain
ライトON

ライトは2つあるので、もう1つの方を制御してみます。上から3番目の水色の四角が明るくなります。

chip-device-ctrl > zcl OnOff On 135246 2 1

f:id:tomo-wait-for-it-yuki:20210929133647p:plain
別のライトON

コマンドのフォーマットはこのような感じです。先程はendpointを変えることで、異なるライトを制御しました。

zcl <cluster> <command> <nodeid> <endpoint> <groupid> [key=value]

次は温度計から温度を読み取ってみます。

chip-device-ctrl > zclread TemperatureMeasurement MeasuredValue 135246 1 0

#...

[1632883644.088914][38115:38123] CHIP:ZCL: ReadAttributesResponse:
[1632883644.088919][38115:38123] CHIP:ZCL:   ClusterId: 0x0000_0402
[1632883644.088922][38115:38123] CHIP:ZCL:   attributeId: 0x0000_0000
[1632883644.088924][38115:38123] CHIP:ZCL:   status: Success                (0x0000)
[1632883644.088925][38115:38123] CHIP:ZCL:   attribute TLV Type: 0x00
[1632883644.088930][38115:38123] CHIP:ZCL:   attributeValue: 2100

#...

2100が返ってきています。これはZigBee Cluster Library Specificationによると21.0℃を表しています。

MeasuredValue = 100 x temperature in degrees Celsius.

値はプログラムの初期化時に設定されたものがそのまま返ってきています。M5Stackの画面とボタンから温度の値を変更すると、取得できる値も変わります。

大体雰囲気はつかめてきましたね。

サンプルを動かしてわかったこと

けっこうZigBee

Matterを策定しているCSA (Connectivity Standard Alliance)6は元々ZigBee Allianceだったこともあり、随所にZigBeeの資産を活用している様子が伺えます。プロトコルスタックの少し下の方をみると、ZigBee Cluster Library (zcl) を利用しているのも見て取れます。clusterの仕様などはZigBee Cluster Library Specification7を見ると読み解くことができます。

バイス初期設定も標準化

バイスの初期設定 (コミッショニング) が標準の中に含まれていて、その実装も与えられているのは嬉しいですね。今は各デバイスで独自の初期設定を持っていると思いますが (Nature Remoも)、これも統一化されることでユーザーが戸惑うことも少なくなるのではないか、と期待できます。BLE/IP/QRコードあたりが初期設定で使えるようになりそうです。

C++実装

ぱっと見、スタックもAPIC++です。スマートホーム用の標準でその実装なので当然マイコンをターゲットとしていますし、サンプルも複数のマイコン上で動くものが提供されています。こういうところもCではなくC++で作っていく感じなのでしょうね。Matterに関しては少なくとも暗号化処理やIPスタックが必要になってくるため、それなりの性能があるマイコン使うのが前提というのも言語選定の根底にありそうです。

今後C言語のbinding作られるのかどうかは少し注目です。

他のサンプル

今回はall-clusters-appサンプルをM5Stackで動かしましたが、複数のサンプルがいくつかのターゲットデバイスに対して提供されています。

nRF52840を使ったサンプルでは、モバイルアプリも含めてサンプルが提供されているので、けっこうそれっぽい雰囲気を味わうことができます。が、nRF52840を2台用意して、1台をThread Border Routerにして…、みたいな感じで動かすのが大変です。興味がある場合は、lock-app8を見てください。

Matterでこまったーこと

CLIツールを起動するとBluetoothペアリングが解除される

ホストPCからBLE接続するときにCLIツールを起動するとBluetoothのペアリングが解除されてしまいます。初回Bluetoothイヤホンで音楽聞きながら作業していたわけですが、急に音が止まりました。BLE使うししゃーないか、と思って改めてMatterのサンプル動かし終わった後にWeb会議のためBluetoothイヤホン接続しようとしたら、接続できなくて焦りました。

あとからペアリング自体が解除されていることに気づいてことなきを得ました。

2回目以降のコミッショニング方法が謎

M5Stackにファームウェアを書き込んで、CLIツールでBLE接続するところからコミッショニングすれば制御できるのですが、M5Stackを再起動したあとにコミッショニングする方法がわからず、事故ったら最初からやり直していて不便です!助けてください!

ツールをしらばく起動しているとCPU使用率が100%になる

Matterのサンプルで遊んでいると、特にPCに負荷かけていないはずなのに急にファンが唸りだしました。なんだろう?と思ってシステム負荷確認してみると…

f:id:tomo-wait-for-it-yuki:20210929135244p:plain
chip-device-ctrlがCPUを1個持っていく…

うーん、なんかイベントループの実装ミスってたりするのでしょうか…。

最後に

簡単にではありますが、Matterのサンプルを動かしてみました。ホストPCとM5Stack間のやり取りしかしていないのであまりスマートホーム感は出ませんでしたが。…スマートホームのデモとしてはやはりスマートスピーカーから制御できるようなものがあると見栄えが良いですね。

ソースコードもそれなりに読んでいるので、別の機会で紹介していければ良いな、と考えています。今後、Matterがもっと盛り上がるとおもしろいな、と思っているのでぜひ皆様もお試しください。

エンジニア積極採用中です

We are hiringです。ファームウェアのポジションもオープンしていますので、一緒にMatterでこまったー、となってくれる方からのご応募をお待ちしております。カジュアル面談等も歓迎なので、その場合はTwitterなどでお声がけくださると嬉しいです。

nature.global