Chapter 21
デバッグとテスト — 切り分けの技術
この章がなぜ必要なのか——Matter の障害は「症状から原因が読めない」.
「機器が見つかりません」——この 1 つのメッセージの裏に、 IPv6・mDNS・BLE・証明書・ACL・ファームウェアのバグ、 あらゆる可能性がある。
闇雲にログを読むのではなく、層ごとに切り分ける技術が要る。 この章はそのための道具立てである。
この章で使う既出の用語(定義は各リンク先). Matter(01 章 3 節)、コミッショニング(01 章 3 節)、ネットワーク(01 章 3 節)、Cluster(02 章 2 節)、Command(02 章 2 節)、IPv6(02 章 1 節)、MRP(02 章 1 節)、リンク(02 章 1 節)、mDNS(03 章 4 節)、マルチキャスト(03 章 3 節)、Router(04 章 2 節)、Wi-Fi(04 章 9 節)、BLE(05 章 1 節)、Ethernet(05 章 1 節)、必要(05 章 5 節)、DNS-SD(06 章 1 節)、PASE(06 章 4 節)、SAI(06 章 3 節)、SII(06 章 3 節)、SRP(06 章 2 節)、再送(06 章 3 節)、AttributeList(07 章 2 節)、OnOff(08 章 2 節)、Fail-Safe(09 章 9 節)、Read(09 章 1 節)、ステータスコード(09 章)、パスコード(11 章 5 節)、証明書(11 章 5 節)、CSA(12 章 3 節)、DAC(12 章 11 節)、初期状態(13 章 6 節)、ロールバック(18 章 5 節)
1. 切り分けの基本方針
下の層から順に確認する。上から見ると必ず迷子になる。
[7] ACL / アプリケーション ← 最後
[6] CASE / セッション
[5] 証明書 / PASE
[4] mDNS / DNS-SD
[3] IPv6 到達性
[2] ネットワーク参加(Wi-Fi / Thread)
[1] 電源・起動・ログ出力 ← 最初| 層 | 確認方法 |
|---|---|
| 1 | シリアルログが出るか |
| 2 | ot-ctl state / Wi-Fi の接続状態 |
| 3 | ping6 ff02::1、ping6 <addr> |
| 4 | dns-sd -B _matter._tcp / avahi-browse / ot-ctl srp server service |
| 5 | 機器ログの PASE / Attestation |
| 6 | 機器ログの CASE、--paa-trust-store-path |
| 7 | ステータスコード 0x7E、ACL の読み出し |
2. ログ
レベル
| レベル | 内容 |
|---|---|
Error | エラーのみ |
Progress | 主要な進行(通常はこれ) |
Detail | 詳細 |
Automation | テスト自動化向けの構造化出力 |
# chip-tool のログレベル
chip-tool --trace_decode 1 onoff toggle 1 1
# 機器側は SDK のビルド設定で(例)
CHIP_CONFIG_LOG_LEVEL=Detail読むべきキーワード
| キーワード | 意味 |
|---|---|
Commissioning の各ステージ名 | どこまで進んだか |
PASE, SPAKE2p | パスコードの検証 |
Attestation, DAC, CD | 証明書の検証 |
AddNOC, AddTrustedRootCertificate | Fabric の追加 |
CASE, Sigma1/2/3 | 運用セッションの確立 |
MRP, retransmission | 再送 |
Access Control, denied | ACL の拒否 |
Fail-safe | 巻き戻し |
「どこまで進んだか」が分かれば、原因の範囲は一気に狭まる. ログの最後に出ているステージの次が失敗している。
3. パケットキャプチャ
Wi-Fi / Ethernet
# Wireshark で Matter のフィルタ
udp.port == 5540
mdns
icmpv6Wireshark は Matter のディセクタを持っている. ただし暗号化されているので中身は見えない。 セッション鍵をログから取り出して復号する仕組みもあるが、手間がかかる。
見えるのは「パケットが飛んでいるか」「ACK が返っているか」。 それだけでも切り分けには十分役立つ。
Thread
Thread のパケットを見るにはスニファが要る。
[nRF52840 dongle など] + [nRF Sniffer for 802.15.4 / Silicon Labs の Network Analyzer]
→ Wireshark に流し込む
→ Thread のネットワーク鍵を入れれば、リンク層は復号できるThread のスニファは、Thread レベルの問題を切り分けるのに極めて有効である. 「機器がそもそも送信しているのか」「親に届いているのか」 「SED が Poll しているのか」が見える。
ネットワーク鍵を入れれば 802.15.4 の暗号は解けるが、 その上の Matter のセッションは別鍵なので中身は見えない。
BLE
nRF Sniffer for Bluetooth LE、または各社のスニファ
→ コミッショニングの BLE 段階を観測できる4. 症状別の診断
「BLE で見つからない」
| 確認 | 方法 |
|---|---|
| 機器がアドバタイズしているか | BLE スキャナアプリ(nRF Connect など) |
| Discriminator が一致しているか | ログと QR コードを突き合わせる |
| Commissioning Window が開いているか | 機器のログ |
| スマホの BLE 権限 | OS の設定 |
| 既にコミッショニング済み | ファクトリリセット |
「ネットワーク参加後に見つからない」(最頻出)
1. 機器が IP アドレスを取得しているか
→ 機器のログ、ot-ctl ipaddr
2. ping6 が通るか
→ ping6 <addr>%<iface>
3. mDNS が出ているか
→ dns-sd -B _matter._tcp / avahi-browse -r _matter._tcp
4. Thread なら SRP 登録
→ ot-ctl srp client state / ot-ctl srp server service
5. マルチキャストが通る環境か
→ ping6 ff02::1 で機器が見えるか「コマンドが失敗する」
| ステータス | 原因 |
|---|---|
0x7E UNSUPPORTED_ACCESS | ACL(14 章) |
0x81 UNSUPPORTED_COMMAND | 未実装 |
0x86 UNSUPPORTED_ATTRIBUTE | 未実装 or ID の誤り |
0x87 CONSTRAINT_ERROR | 値域外 |
0xC3 UNSUPPORTED_CLUSTER | クラスタ未実装 |
0xC6 NEEDS_TIMED_INTERACTION | Timed Request が必要 |
# ACL を確認する
chip-tool accesscontrol read acl <node-id> 0
# 実装されている属性を確認する
chip-tool any read-by-id 0x0006 0xFFFB <node-id> 1 # AttributeList
chip-tool any read-by-id 0x0006 0xFFF9 <node-id> 1 # AcceptedCommandList「時々失敗する」
最も厄介な種類。疑うべきもの:
| 原因 | 確認 |
|---|---|
| スレッドセーフティ違反 | 別スレッドから SDK を呼んでいないか(16 章) |
| 電波干渉 | チャネルを変えて再現するか(04 章) |
| メモリ不足 | ヒープの使用量、RESOURCE_EXHAUSTED |
| SED の Poll タイミング | SII/SAI の設定、再送ログ |
| メッセージカウンタ | 再起動後に失敗するか(06 章) |
| 電源の不安定 | 電流測定 |
「たまにクラッシュする」の第 1 容疑者はスレッドセーフティである. 割り込みハンドラやセンサーのタスクから 直接 SDK の属性 API を呼んでいないか、コードを全部確認すること。
5. 自動テスト
YAML テスト(従来型)
SDK には YAML で記述されたテストスクリプトがある。
tests:
- label: "Read OnOff attribute"
cluster: "On/Off"
command: "readAttribute"
attribute: "OnOff"
response:
value: false./scripts/tests/run_test_suite.py --target TestOnOff runPython テスト(推奨)
from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main
import chip.clusters as Clusters
from mobly import asserts
class TestMyDevice(MatterBaseTest):
@async_test_body
async def test_onoff(self):
# 初期状態
v = await self.read_single_attribute(
self.default_controller, self.dut_node_id,
endpoint=1, attribute=Clusters.OnOff.Attributes.OnOff)
asserts.assert_false(v, "初期状態は OFF のはず")
# ON にする
await self.send_single_cmd(Clusters.OnOff.Commands.On(), endpoint=1)
v = await self.read_single_attribute(
self.default_controller, self.dut_node_id,
endpoint=1, attribute=Clusters.OnOff.Attributes.OnOff)
asserts.assert_true(v, "ON になっているはず")
if __name__ == "__main__":
default_matter_test_main()認証テスト(22 章)も Python で書かれるようになっている. 自社のテストを同じ枠組みで書いておけば、 認証テストの実行環境をそのまま流用できる。
CI に入れるべきもの
| 項目 | 内容 |
|---|---|
| ビルド | 全ターゲット |
| ZAP の再生成差分 | .zap と生成コードの整合(16 章) |
| 単体テスト | ロジック部分 |
| 統合テスト | Linux 上のサンプルと chip-tool で往復 |
| 静的解析 | メモリ安全性 |
| テスト証明書の混入チェック | 量産ビルドに VID 0xFFF1 が入っていないか(12 章) |
最後の項目は必ず入れること. テスト証明書で量産する事故を、仕組みで防ぐ。
6. 実機テストのチェックリスト
基本
- ☐ コミッショニング(QR / 手動コード両方)
- ☐ 全属性の読み取り
- ☐ 全コマンドの実行
- ☐ サブスクリプションの動作
- ☐ 物理操作 → Matter への反映(16 章)
- ☐ ファクトリリセット(消え残りの確認、14 章)
マルチアドミン
- ☐ 3 つ以上の Fabric に同時参加
- ☐ 各 Fabric から独立に操作
- ☐ 1 つの Fabric を削除しても他が動く
- ☐
SupportedFabricsの上限まで追加 - ☐ 上限を超えたときのエラー
異常系
- ☐ コミッショニング中に電源断 → Fail-Safe の巻き戻し
- ☐ コミッショニング中に電波断
- ☐ ネットワーク切断 → 復帰
- ☐ Border Router 再起動 → 復帰
- ☐ 停電からの一斉復帰(17 章)
- ☐ OTA 中の電源断 → ロールバック
- ☐ 不正な引数のコマンド
- ☐ 大量のサブスクリプション要求
長期
- ☐ 電池寿命の実測(17 章)
- ☐ 数週間の連続動作(メモリリーク)
- ☐ 繰り返しのコミッショニング/リセット
- ☐ OTA を複数世代
「停電からの一斉復帰」は必ずテストすること. 実験室で 1 台ずつ動かしても発見できない。 家中の機器を模擬して、同時に電源を入れるテストが要る。
7. 便利なツール一覧
| ツール | 用途 |
|---|---|
chip-tool | CLI コントローラ(15 章) |
chip-repl | Python 対話環境 |
chip-cert | 証明書の生成・検証 |
ota_image_tool.py | OTA イメージの作成・確認(18 章) |
spake2p | SPAKE2+ 検証子の生成 |
chip-tool payload | QR / 手動コードの解析 |
ot-ctl | Thread の操作(04 章) |
dns-sd / avahi-browse | mDNS の確認 |
| Wireshark | パケット解析 |
| nRF Connect(モバイル) | BLE スキャン |
| Thread スニファ | 802.15.4 の解析 |
| 電流計 / パワーアナライザ | 電池寿命の実測 |
# QR コードを解析する
chip-tool payload parse-setup-payload MT:Y.K9042C00KA0648G00
# 手動コードを解析する
chip-tool payload parse-setup-payload 34970112332
# SPAKE2+ 検証子を生成する
./out/spake2p/spake2p gen-verifier -f - -i 10000 -s <base64-salt> -p 202020218. 問い合わせ・情報源
| 情報源 | 内容 |
|---|---|
| 仕様書(CSA) | 最終的な正 |
| GitHub Issues(connectedhomeip) | 同じ問題に他の人が当たっている可能性が高い |
| SDK のソース | 仕様書で分からないときの実装の実際 |
| SoC ベンダーのフォーラム | プラットフォーム固有の問題 |
| CSA の会員向けリソース | 認証関連 |
GitHub の Issue 検索は極めて有効である. Matter は新しい標準なので、あなたが遭遇する問題の多くは既知である。 エラーメッセージをそのまま検索するだけで解決することが多い。
9. まとめ
- 障害は 必ず下の層から切り分ける。 電源 → ネットワーク参加 → IPv6 → mDNS → 証明書 → CASE → ACL。
- 最頻出は「ネットワーク参加後に見つからない」。mDNS / SRP を疑う(03 章・06 章)。
- ステータスコード、特に
0x7E= ACL を覚えておく。 - 「時々失敗する」の第 1 容疑者はスレッドセーフティ違反(16 章)。
- パケットキャプチャは中身は見えないが、「飛んでいるか」が分かるだけで有用。 Thread はスニファが強力。
- 自動テストは Python テストフレームワークで書く。認証テストと同じ枠組み。
- CI に ZAP 再生成差分 と テスト証明書の混入チェックを必ず入れる。
- 実機テストでは マルチアドミン(3 Fabric 以上)、異常系、 停電の一斉復帰、電池寿命の実測を外さない。