Chapter 20
コントローラ/アプリ側の開発
この章がなぜ必要なのか——「操作する側」を作る道は 1 本ではない.
スマホアプリを作りたいのか、ハブを作りたいのか、 既存のホームオートメーションに Matter を組み込みたいのか。
各エコシステムが提供する API を使う道と、 自前で Matter コントローラを実装する道があり、できることが大きく違う。
この選択を間違えると、開発の後半で「その機能は使えません」に突き当たる。
この章で使う既出の用語(定義は各リンク先). Matter(01 章 3 節)、コミッショニング(01 章 3 節)、ネットワーク(01 章 3 節)、Administrator(02 章 5 節)、Attribute(02 章 2 節)、Cluster(02 章 2 節)、Command(02 章 2 節)、Commissioner(02 章 5 節)、Controller(02 章 5 節)、Endpoint(02 章 2 節)、Report(02 章 6 節)、Server(02 章 5 節)、mDNS(03 章 4 節)、Router(04 章 2 節)、BLE(05 章 1 節)、必要(05 章 5 節)、PASE(06 章 4 節)、FeatureMap(07 章 2 節)、Binding(08 章 2 節)、Descriptor(08 章 1 節)、NodeLabel(08 章 1 節)、OnOff(08 章 2 節)、Toggle(08 章 2 節)、Invoke(09 章 1 節)、Read(09 章 1 節)、Write(09 章 1 節)、ワイルドカード(09 章 11 節)、Info(10 章 5 節)、MaxInterval(10 章 1 節)、証明書(11 章 5 節)、DAC(12 章 11 節)、Passcode(13 章 2 節)、List(17 章 4 節)
1. 3 つの道
| 道 | 内容 | Fabric |
|---|---|---|
| (a) エコシステムの API を使う | Apple / Google / Amazon の SDK 経由 | エコシステムの Fabric |
| (b) 自前のコントローラを作る | Matter SDK で独自の Fabric を持つ | 自分の Fabric |
| (c) 既存の OSS を使う | Home Assistant、python-matter-server など | その実装の Fabric |
(a) エコシステムの API
| プラットフォーム | 提供されるもの |
|---|---|
| Apple | HomeKit フレームワーク経由(MatterSupport でコミッショニングを委譲) |
| Home APIs / Google Home Mobile SDK | |
| Amazon | Alexa の各種 SDK |
| Samsung | SmartThings SDK |
| 利点 | 欠点 |
|---|---|
| ユーザーの既存の家に統合される | できることが API の範囲に限られる |
| コミッショニングをエコシステムに任せられる | エコシステムごとに実装が必要 |
| 音声アシスタント・自動化と連携 | 独自クラスタは扱えないことが多い |
メーカーのアプリは、多くの場合 (a) を選ぶ. ユーザーはすでに Apple Home や Google Home を使っている。 そこに自社製品を載せるのが自然である。
ただし独自機能の扱いが制約される。 「Matter で基本操作、独自機能は自社アプリの直接通信で」という ハイブリッド構成が現実的な落としどころになることが多い。
(b) 自前のコントローラ
Matter SDK の Controller API を使い、自分の Fabric を持つ。
| 利点 | 欠点 |
|---|---|
| すべての機能にアクセスできる | Fabric 管理を自分でやる |
| 独自クラスタも扱える | CA の運営が必要(NOC の発行) |
| プラットフォーム非依存 | 実装量が多い |
CA の運営が最大の負担である. Fabric の Root CA を作り、機器ごとに NOC を発行する必要がある(14 章)。 スマホアプリなら鍵をどこに置くか、複数端末でどう共有するか—— 設計判断が多い。
ハブ製品(Linux ベース)なら現実的だが、 スマホアプリで自前 Fabric を持つのは相応の覚悟が要る。
(c) 既存の OSS
| プロジェクト | 内容 |
|---|---|
| Home Assistant | Matter 統合を持つ。python-matter-server が実体 |
| python-matter-server | WebSocket API で Matter を操作できるサーバ |
| chip-tool / chip-repl | 開発・検証用(15 章) |
プロトタイプや社内ツールなら (c) が圧倒的に速い.
python-matter-serverを立てれば、WebSocket 経由で コミッショニングも属性の読み書きもできる。 自社製品の検証環境としても有用である。
2. 自前コントローラの実装(SDK)
C++ / Linux
// おおまかな流れ
chip::Controller::DeviceCommissioner commissioner;
chip::Controller::SetupParams params;
params.operationalCredentialsDelegate = &opCredsIssuer; // ← NOC を発行する実装
commissioner.Init(params);
// コミッショニング
commissioner.PairDevice(nodeId, "MT:Y.K9042C00KA0648G00");
// 操作
chip::Controller::ClusterBase cluster(...);
cluster.InvokeCommand(OnOff::Commands::Toggle::Type{}, ...);Python(chip-repl / Matter Python API)
from chip import ChipDeviceCtrl
from chip.clusters import Objects as Clusters
devCtrl = ChipDeviceCtrl.ChipDeviceController(...)
# コミッショニング
devCtrl.CommissionOnNetwork(nodeId=1, setupPinCode=20202021)
devCtrl.CommissionWithCode("MT:Y.K9042C00KA0648G00", nodeId=1)
# 読み取り
res = await devCtrl.ReadAttribute(1, [(1, Clusters.OnOff.Attributes.OnOff)])
# 書き込み
await devCtrl.WriteAttribute(1, [(0, Clusters.BasicInformation.Attributes.NodeLabel("居間"))])
# コマンド
await devCtrl.SendCommand(1, 1, Clusters.OnOff.Commands.Toggle())
# サブスクリプション
sub = await devCtrl.ReadAttribute(
1, [(1, Clusters.OnOff.Attributes.OnOff)],
reportInterval=(1, 60), keepSubscriptions=True)
sub.SetAttributeUpdateCallback(lambda path, tx: print("changed:", path))モバイル
| OS | 提供 |
|---|---|
| Android | Matter SDK に Java/Kotlin バインディングがある。Google の Home Mobile SDK も |
| iOS | Matter framework(Darwin プラットフォーム実装) |
モバイルでは BLE の権限とバックグラウンド動作が課題になる.
- コミッショニングには BLE のスキャン権限が要る(位置情報権限が絡む OS もある)
- バックグラウンドでのサブスクリプション維持は OS の制約を受ける
- 「アプリを閉じたら通知が来ない」を前提に設計する
3. コントローラが実装すべきこと
最小限
- ☐ QR / 手動コードのパース(13 章)
- ☐ 機器の発見(BLE / mDNS)
- ☐ PASE 確立
- ☐ デバイス認証の検証(DAC チェーン、CD)
- ☐ NOC の発行(CA 機能)
- ☐ ネットワーク認証情報の受け渡し
- ☐ CASE 確立
- ☐ 属性の読み書き・コマンド
- ☐ Fabric 情報の永続化
実用に必要
- ☐ サブスクリプションと再確立
- ☐ Descriptor による機器構造の把握
- ☐ マルチアドミン(他エコシステムへの共有)
- ☐ Fabric の削除
- ☐ グループ管理
- ☐ Binding の設定
- ☐ OTA Provider(自分で配信するなら)
- ☐ エラーハンドリングと再試行
4. 機器の構造を把握する定石
# 1. Endpoint 0 の PartsList を読む
parts = await read(node, 0, Clusters.Descriptor.Attributes.PartsList)
# 2. 各 Endpoint の DeviceTypeList と ServerList を読む
for ep in parts:
types = await read(node, ep, Clusters.Descriptor.Attributes.DeviceTypeList)
servers = await read(node, ep, Clusters.Descriptor.Attributes.ServerList)
# 3. 必要なクラスタの FeatureMap を読んで、UI を出し分ける
fm = await read(node, ep, Clusters.ColorControl.Attributes.FeatureMap)
if fm & 0x10: # CT ビット
show_color_temperature_slider()
FeatureMapを読まずに UI を作ると、対応していない操作を出してしまう. 「色温度スライダーを動かしても何も起きない」という体験になる。必ず FeatureMap と AttributeList を見て、UI を出し分けること(07 章)。
5. 状態管理の設計
アプリの内部状態 ← サブスクリプションの Report で更新
↑
ユーザー操作 → コマンド送信 → (応答)→ Report で確認| 設計上の問い | 選択肢 |
|---|---|
| コマンド送信後、すぐ UI を更新するか | 楽観的更新(速いが訂正が要る)/Report を待つ(正確だが遅い) |
| Report が来ないとき | タイムアウトして読み直す |
| オフライン機器の表示 | 最後の既知の状態 + オフライン表示 |
| 複数コントローラの同時操作 | Report を信頼の源にする |
楽観的更新は必須に近い. Thread の SED 相手だと、コマンドの反映に数秒かかることがある。 その間 UI が固まっていると、ユーザーは「壊れた」と思う。
すぐスイッチを動かし、失敗したら戻す——ただし 「戻る」ことがユーザーに伝わる UI にすること。
6. マルチアドミンの提供
自社アプリで設定した機器を、他のエコシステムにも追加できるようにする(14 章)。
# 既存の管理者としてウィンドウを開く
await devCtrl.SendCommand(nodeId, 0,
Clusters.AdministratorCommissioning.Commands.OpenCommissioningWindow(
commissioningTimeout=300,
PAKEPasscodeVerifier=verifier,
discriminator=disc,
iterations=iters,
salt=salt),
timedRequestTimeoutMs=5000) # ← Timed Request が必須これを実装しないと「他社エコシステムに追加できない製品」になる. Matter の売りであるマルチアドミンが使えない。
ユーザーからは「なぜ Google Home に追加できないのか」という 問い合わせになる。アプリの必須機能と考えるべきである。
OpenCommissioningWindowは Timed Request が必要(09 章)。
7. エコシステム別の実情
| エコシステム | 特徴 |
|---|---|
| Apple | Home アプリ/HomeKit と統合。Thread Border Router が広く普及(Apple TV、HomePod) |
| Nest Hub 等が Border Router。Home APIs を提供 | |
| Amazon | Echo が Border Router。対応デバイスタイプは順次拡大 |
| Samsung SmartThings | ハブが Border Router。比較的広い対応 |
| Home Assistant | OSS。対応が早く、開発者に人気 |
対応するデバイスタイプ・クラスタはエコシステムごとに違う. 仕様に定義されていても、そのエコシステムが対応していなければ使えない。
製品を出す前に、ターゲットとするエコシステムでの動作を必ず確認すること。 「仕様上は動くはず」で出荷すると、 「Apple では動くが Google では出てこない」という事態になる。
各社の対応状況は変化するので、開発中に定期的に再確認する。
8. 落とし穴
| 落とし穴 | 対処 |
|---|---|
| 独自クラスタが使えると思い込む | エコシステム API 経由では扱えないことが多い |
| FeatureMap を見ずに UI を作る | 対応していない操作を出してしまう |
ワイルドカード */*/* の多用 | Thread 機器で失敗する(09 章) |
| サブスクリプションを張りすぎる | 機器のリソースを枯渇させる(10 章) |
| MaxInterval を機器の返答より短く要求し続ける | 電池を消耗させる |
| マルチアドミンを実装しない | 他社エコシステムに追加できない |
| Timed Request の未対応 | NEEDS_TIMED_INTERACTION (0xC6) |
| Fabric 情報の永続化漏れ | アプリ再起動で全機器が消える |
| BLE 権限の取得漏れ(モバイル) | コミッショニングできない |
| オフライン機器の扱いが雑 | 操作できるように見えて何も起きない |
| PAA トラストストアの未設定 | 実機の証明書検証に失敗する |
9. まとめ
- コントローラ開発の道は 3 つ。 (a) エコシステム API(統合されるが制約あり)、 (b) 自前 Fabric(自由だが CA 運営が必要)、 (c) 既存 OSS(速い)。
- 自前 Fabric は NOC の発行(CA 機能)が必要。ここが最大の負担。
- 機器の構造は Descriptor → DeviceTypeList / ServerList → FeatureMap の順に読む。 FeatureMap を見て UI を出し分ける。
- 状態はサブスクリプションの Report を信頼の源にする。 UX のために楽観的更新は必要だが、訂正できるようにする。
- マルチアドミン(
OpenCommissioningWindow)はアプリの必須機能。 実装しないと他社エコシステムに追加できない。 - エコシステムごとに対応状況が違う。出荷前にターゲット全社で実機確認する。