Chapter 19
ブリッジ — 既存機器を Matter に見せる
この章がなぜ必要なのか——既存の資産を捨てずに Matter へ移行する道だから.
すでに Zigbee や独自プロトコルの製品を大量に出荷しているメーカーにとって、 「全製品を Matter 対応に作り直す」のは非現実的である。
ブリッジは、既存機器のファームウェアを一切変えずに、Matter 対応にする手段である。 ユーザーから見れば、古い機器が突然 Apple Home で使えるようになる。
実装の要点は「動的エンドポイント」と「マッピング設計」、 そして到達不能時の扱いである。
この章で使う既出の用語(定義は各リンク先). Matter(01 章 3 節)、コミッショニング(01 章 3 節)、相互運用性(01 章 2 節)、Attribute(02 章 2 節)、Bridge(02 章 5 節)、Report(02 章 6 節)、データモデル(02 章 1 節)、NDP(03 章 5 節)、必要(05 章 5 節)、Aggregator(08 章 4 節)、Descriptor(08 章 1 節)、Identify(08 章 2 節)、NodeLabel(08 章 1 節)、OnOff(08 章 2 節)、UniqueID(08 章 1 節)、イベント(08 章 8 節)、DataVersion(09 章 4 節)、Info(10 章 5 節)、メーカー(12 章 3 節)、ZAP(16 章 1 節)、List(17 章 4 節)
1. ブリッジとは
[Matter コントローラ]
│ Matter / IP
↓
[ブリッジ] ← 1 台の Matter Node
│ Zigbee / Z-Wave / 独自 RF / クラウド API
├── 既存の電球 A
├── 既存のセンサー B
└── 既存のロック Cブリッジ自体が 1 台の Matter Node であり、 その中の Endpoint として、配下の機器を表現する。
| 項目 | 内容 |
|---|---|
| Matter から見える数 | Node は 1 台(Endpoint が複数) |
| 配下機器の改造 | 不要 |
| コミッショニング | ブリッジ 1 台だけ |
| 配下機器の追加 | Endpoint の動的な増減 |
2. Endpoint の構成
Endpoint 0 ── Root Node (0x0016)
└── ユーティリティクラスタ(通常どおり)
Endpoint 1 ── Aggregator (0x000E)
├── Descriptor
│ └── PartsList = [2, 3, 4, ...] ← 配下機器の Endpoint
└── Actions(任意。シーンやグループ操作)
Endpoint 2 ── Bridged Node (0x0013) + On/Off Light (0x0100)
├── Bridged Device Basic Information (0x0039)
│ ├── NodeLabel = "リビングの電球"
│ ├── Reachable = true/false ← 重要
│ ├── VendorName, ProductName, ...
│ └── UniqueID
├── Descriptor
├── Identify
└── On/Off
Endpoint 3 ── Bridged Node + Temperature Sensor
└── ...Aggregator (0x000E)
「この配下にブリッジされた機器がある」ことを示す Endpoint。 PartsList に配下の Endpoint を列挙する。
Bridged Node (0x0013)
ブリッジされた機器であることを示すデバイスタイプ。 実際の機能を表すデバイスタイプ(On/Off Light など)と組み合わせて使う。
つまり 1 つの Endpoint の DeviceTypeList に 2 つのデバイスタイプが入る。
Bridged Device Basic Information (0x0039)
通常の Basic Information(0x0028)の、ブリッジ機器版。
| 属性 | 内容 |
|---|---|
VendorName / ProductName | 配下機器のメーカー・製品名 |
NodeLabel | ユーザーが付ける名前 |
UniqueID | 配下機器の一意な識別子 |
Reachable | 配下機器と通信できているか |
ProductURL, SerialNumber など | 任意 |
Reachableが最重要である.Zigbee の電球の電源が抜かれた、電波が届かない、電池が切れた—— ブリッジ自体は生きているので Matter の通信は成功するが、 配下機器には届かない。
このとき
Reachable = falseにすれば、コントローラは 「この機器はオフラインです」と正しく表示できる。
Reachableを実装せず、常にtrueにしていると、 アプリ上では操作できているように見えるのに何も起きない—— ユーザーにとって最悪の体験になる。
ReachableChangedイベントで変化を通知することもできる。
3. 動的エンドポイント
配下機器は実行時に増減する。ZAP で静的に定義するだけでは足りない。
// ZAP で「テンプレート」となる Endpoint 定義を用意しておく
// (必要なクラスタを含む雛形)
// 実行時に追加
CHIP_ERROR AddBridgedDevice(Device * dev, EmberAfEndpointType * ep,
const Span<const EmberAfDeviceType> & deviceTypeList,
EndpointId parentEndpointId)
{
for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; index++)
{
if (gDevices[index] != nullptr) continue;
gDevices[index] = dev;
CHIP_ERROR err = emberAfSetDynamicEndpoint(
index, gCurrentEndpointId, ep,
Span<DataVersion>(gDataVersions[index]),
deviceTypeList, parentEndpointId);
if (err == CHIP_NO_ERROR) return err;
gDevices[index] = nullptr;
}
return CHIP_ERROR_NO_MEMORY;
}
// 削除
emberAfClearDynamicEndpoint(index);上限は
CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNTで決まる. メモリを消費するので、現実的な最大数を決めて設計する。 「Zigbee は最大 50 台」なら 50 + 余裕、といった具合。
Endpoint 番号の再利用
難しい判断が要る.
機器 X が Endpoint 2 だったとする。X を取り外し、後に機器 Y を追加した。 Y に Endpoint 2 を割り当ててよいか?
- よくない。 コントローラが「Endpoint 2 = リビングの電球」と覚えていると、 別の機器が同じ名前で表示される。
- 番号を再利用しない(単調増加)方が安全だが、いずれ枯渇する。
UniqueIDを必ず設定することで、コントローラ側が同一性を判断できる。実装方針としては、
UniqueIDを配下機器の一意な ID(Zigbee なら IEEE アドレスなど) から導出し、番号は再利用を避けるのが無難である。
構成変更の通知
配下機器が増減したら、Aggregator の PartsList が変わる。 この属性の変更を報告することで、コントローラが再スキャンする。
MatterReportingAttributeChangeCallback(kAggregatorEndpointId,
Descriptor::Id,
Descriptor::Attributes::PartsList::Id);これを忘れると「新しい機器を追加したのにアプリに出てこない」となる。
4. マッピング設計 — ここが本当の難所
既存プロトコルの機能を、Matter のクラスタにどう対応づけるか。
素直に対応するもの
| 既存 | Matter |
|---|---|
| Zigbee の On/Off クラスタ | Matter の On/Off(ほぼ同一) |
| Zigbee の Level Control | Matter の Level Control |
| Zigbee の Color Control | Matter の Color Control |
| 温度センサー | Temperature Measurement |
Zigbee からの移行は比較的楽である. Matter のデータモデルは ZCL を継承しているので、 クラスタ ID も属性 ID もほぼ同じであることが多い。
対応が難しいもの
| 状況 | 対処 |
|---|---|
| 既存機器に Matter の必須属性がない | 固定値を返す、または推定する |
| 既存機器の機能が Matter にない | 独自クラスタ、または諦める |
| 値域・単位が違う | 変換する(単位の取り違えに注意、08 章) |
| 状態の取得ができない(送信専用の機器) | 最後に送った値をキャッシュする |
| 応答が遅い | 楽観的更新 + 後で訂正 |
「必須属性がない」問題の例. 古い調光器が
MinLevel/MaxLevelを持っていない。 Matter の Level Control では必須かもしれない。 → ブリッジが妥当な固定値を返すしかない。重要なのは「嘘をつきすぎない」ことである。 実際にはできないことを「できる」と宣言すると、 ユーザーが操作しても何も起きない。 できない機能はクラスタごと載せない方が誠実である。
応答の遅さへの対処
コントローラ → ブリッジ: On コマンド
↓ ブリッジは即座に Success を返す(Matter のタイムアウトを避ける)
↓ 裏で Zigbee にコマンドを送る(数百 ms〜数秒)
↓ 実際に点いたら OnOff 属性を更新 → 報告楽観的更新をするかどうかは設計判断である.
- すぐ属性を更新する → アプリの反応が速いが、失敗したら訂正が必要
- 実際の応答を待つ → 正確だが遅い
どちらにせよ、Matter のコマンド応答をブロックして待ってはいけない(09 章)。 ブリッジ全体が止まる。
5. ブリッジの規模と制約
| 項目 | 考慮 |
|---|---|
| 配下機器数 | 動的 Endpoint の上限、メモリ |
| Fabric 数 | ブリッジ 1 台が複数 Fabric に所属(14 章) |
| サブスクリプション | 配下機器の数 × 属性数 × Fabric 数。膨大になる |
| イベントバッファ | 配下機器全部のイベント |
| 応答性 | ブリッジがボトルネックになる |
サブスクリプションのリソースが最も厳しい. 50 台の配下機器 × 各 5 属性 × 3 Fabric = 750 パス。 これを保持するのは組み込み機器には重い。
ブリッジは Linux ベース(Raspberry Pi クラス)で作られることが多いのは このためである。MCU では厳しい規模になる。
6. Actions クラスタ(任意)
Actions クラスタ (0x0025) を使うと、 「リビングの照明を全部消す」といったブリッジ固有の操作を公開できる。
| 概念 | 内容 |
|---|---|
| EndpointList | 「リビング」などの Endpoint のグループ |
| ActionList | 「全部消す」などの実行可能な操作 |
既存システムのシーンやグループを Matter に見せる手段である. ただし対応しているコントローラは限られる。 標準のグループ機能(09 章)で足りるなら、そちらの方が相互運用性は高い。
7. 実装の出発点
# SDK のサンプル
./scripts/examples/gn_build_example.sh examples/bridge-app/linux out/bridge
./out/bridge/chip-bridge-app
# コミッショニング
chip-tool pairing onnetwork 1 20202021
# 構成を確認
chip-tool descriptor read parts-list 1 0 # Endpoint 0 の子
chip-tool descriptor read parts-list 1 1 # Aggregator の配下
chip-tool descriptor read device-type-list 1 3 # ある Endpoint の種別
chip-tool bridgeddevicebasicinformation read reachable 1 3
chip-tool onoff toggle 1 3
bridge-appは動的 Endpoint の追加・削除の実例として非常に有用である. ここから始めて、配下プロトコルの部分を自社のものに差し替えるのが最短経路である。
8. 落とし穴
| 落とし穴 | 対処 |
|---|---|
Reachable を実装しない | オフライン機器が操作できるように見える |
UniqueID を設定しない | 機器の同一性が判定できない |
PartsList の変更を報告しない | 新機器がアプリに出てこない |
| Endpoint 番号の安易な再利用 | 別機器が前の名前で表示される |
| 動的 Endpoint の上限不足 | 機器を追加できない |
| Matter のコマンドをブロックして待つ | ブリッジ全体が停止 |
| できない機能を宣言する | 操作しても何も起きない |
| 単位変換のミス | 08 章の単位に注意 |
| サブスクリプションのリソース不足 | 規模を見積もる |
| ブリッジ自体の障害 | 単一障害点。落ちると配下が全滅 |
ブリッジは単一障害点である. これは構造上避けられない。
- 冗長化は困難(1 台の Matter Node なので)
- ブリッジ自身の安定性が全体の可用性を決める
- ウォッチドッグ、自動再起動、状態の永続化が重要
ユーザーへの説明としても、「ハブが必要」という事実は明示すべきである。
9. まとめ
- ブリッジは 1 台の Matter Node として振る舞い、 配下機器を Endpoint として表現する。配下機器の改造は不要。
- 構成は Aggregator (
0x000E) + Bridged Node (0x0013) + 実機能のデバイスタイプ。 Bridged Device Basic InformationのReachableが最重要。 実装しないと、オフライン機器が操作可能に見える。- 動的エンドポイントで実行時に増減させる。上限はメモリで決まる。
PartsListの変更報告を忘れない。 - マッピング設計が本当の難所。できない機能を宣言しない。単位変換に注意。
- Matter のコマンド応答をブロックしない。楽観的更新か非同期通知で。
- サブスクリプションのリソースが厳しいので、規模を見積もる。 だからブリッジは Linux クラスで作られることが多い。
- ブリッジは単一障害点。安定性が全体の可用性を決める。