Matter 19 · ブリッジ — 既存機器を Matter に見せる

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 を割り当ててよいか?

実装方針としては、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 ControlMatter の Level Control
Zigbee の Color ControlMatter の 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 章の単位に注意
サブスクリプションのリソース不足規模を見積もる
ブリッジ自体の障害単一障害点。落ちると配下が全滅

ブリッジは単一障害点である. これは構造上避けられない。

ユーザーへの説明としても、「ハブが必要」という事実は明示すべきである。

9. まとめ