ESP32H2 と ESP Thread ボーダー ルーター ボードを使用して Thread ネットワークを構築する

1. はじめに

26b7f4f6b3ea0700.png

Google Nest チームがリリースした OpenThread は、Thread® ネットワーク プロトコルのオープンソース実装であり、スマートホーム製品の開発を加速させることを目的としています。Thread 仕様は、家庭用および商業ビルのアプリケーション向けに、IPv6 ベースの信頼性、安全性、低消費電力のワイヤレス デバイス間通信プロトコルを定義しています。

Espressif は、FreeRTOS と LwIP をベースとした OpenThread スタックを移植し、開発者が Thread ネットワークを迅速に構築できるようにしました。関連するソースコードは GitHub から入手できます。同時に、Espressif は RTOS に基づく Thread ボーダー ルーターも実装しています。

この Codelab では、実際のハードウェアで OpenThread をプログラミングし、Thread ネットワークを作成して管理し、ノード間でメッセージを渡します。

Espressif_hardware_setup.jpg

学習内容

  • OpenThread CLI バイナリをビルドして ESP ボードに書き込む。
  • ボーダー ルーターの構築と ESP Thread ボーダー ルーター ボードへのフラッシュ。
  • ESP Monitor と OpenThread CLI で Thread ノードを手動で管理する。
  • Thread ボーダー ルーターで Thread ネットワークを形成する
  • Thread ネットワークに対するデバイスのコミッショニングを保護する。
  • Thread ノード間で IPv6 アドレスを ping する。
  • UDP を使用して Thread ノード間でメッセージを受け渡す。

必要なもの

ハードウェア:

  • IEEE 802.15.4 モジュール搭載の ESP ボード 2 個。
  • ESP Thread ボーダー ルーター ボード 1 枚。

ソフトウェア:

2. 開始するには

  1. ESP-IDF のインストール。

ESP-IDF プログラミング ガイドに沿ってソフトウェア開発環境をインストールしてください。

  1. ESP Thread Border Router SDK のクローンを作成します。

ESP-THREAD-BR は公式の ESP Thread ボーダー ルーター SDK です。Thread ボーダー ルーターを構築するためのすべての基本的なネットワーク機能をサポートし、製品レベルの豊富な機能を統合して迅速な製品化を実現します。

$ cd <your-local-workspace>
$ git clone --recursive https://github.com/espressif/esp-thread-br.git

3. ビルドとフラッシュ

IEEE 802.15.4 モジュールを備えた ESP ボードで ot-cli-ftd バイナリ ファイルをビルドおよびフラッシュする方法については、ot_cli の ESP-IDF の例をご覧ください。

$ cd <your-idf-path>/examples/openthread/ot_cli
$ idf.py set-target <your-board-type>

メニュー構成で結合機能を有効にします。

$ idf.py menuconfig

[Component config] > [OpenThread] > [Enable Joiner] をオンにしてから、ビルドとフラッシュを行います。

$ idf.py -p <your-local-port> build flash monitor

ESP Thread ボーダー ルーター ボードで ot-br バイナリ ファイルをビルドおよびフラッシュするには、まず RCP バイナリ ファイルをビルドする必要があります。この RCP バイナリ ファイルは、ESP Thread ボーダー ルーター ボード上のデバイスに明示的に書き込む必要はありません。これはボーダー ルーターのバイナリ ファイルに含まれ、初回起動時(または RCP ファームウェアの変更時)に ESP32-H2 チップにフラッシュされます。詳しくは、ESP Thread BR のドキュメントをご覧ください。

$ cd <your-idf-path>/examples/openthread/ot_rcp
$ idf.py set-target esp32h2
$ idf.py build
$ cd <your-esp-thread-br-path>/examples/basic_thread_border_router
$ idf.py set-target esp32s3

メニュー構成を使用してコミッショナー機能を有効にします。

$ idf.py menuconfig

[Component config] > [OpenThread] > [ Commissioner] を有効にしてから、ビルドとフラッシュを行います。

$ idf.py -p <your-local-port> build flash monitor

4. Thread ボーダー ルーターで Thread ネットワークを形成する

ESP Thread ボーダー ルーター ボード(BR Commissioner)で OpenThread コマンドラインを使用して Thread ネットワークを形成できるようになりました。

## BR Commissioner ##
----------------------
> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 21
Channel Mask: 0x07fff800
Ext PAN ID: 151975d11bea97b5
Mesh Local Prefix: fd6a:b54b:d6a3:b05a::/64
Network Key: 731ab6a60a64a0a0b14b259b86b2be01
Network Name: OpenThread-1444
PAN ID: 0x1444
PSKc: 54e7f18d2575014da94db09df29c5df0
Security Policy: 672 onrc 0
Done

このデータセットをアクティブなデータセットとして commit します。

> dataset commit active
Done

IPv6 インターフェースを起動します。

> ifconfig up
I (59329) OPENTHREAD: Platform UDP bound to port 49153
Done
I (59329) OT_STATE: netif up

Thread プロトコル オペレーションを開始します。

> thread start
I(61709) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
Done
> I(62469) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition reattaching with Active Dataset
I(69079) OPENTHREAD:[N] RouterTable---: Allocate router id 11
I(69079) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> 2c00
I(69089) OPENTHREAD:[N] Mle-----------: Role detached -> leader
I(69089) OPENTHREAD:[N] Mle-----------: Partition ID 0x28b518c6
I (69099) OPENTHREAD: Platform UDP bound to port 49154

しばらく待ってから、デバイスの状態を確認します。リーダーになるはずです。

> state
leader
Done
> 

5. ネットワークキーを使用して Thread ネットワークに接続する

この Codelab では、BR 形式のネットワークに接続するために、IEEE 802.15.4 モジュールを搭載した 2 つの ESP ボードを用意します。このセッションでは、Board1 をネットワークに追加します。

BR からネットワークキーを取得します。

## BR Commissioner ##
----------------------
> networkkey
731ab6a60a64a0a0b14b259b86b2be01
Done
> 

このネットワークキーを、IEEE 802.15.4 モジュールを備えた 1 つの ESP ボード(Board1 Joiner)に設定します。

## Board1 Joiner ##
----------------------
> dataset networkkey 731ab6a60a64a0a0b14b259b86b2be01
Done

このデータセットをアクティブなデータセットとして commit します。

> dataset commit active
Done

IPv6 インターフェースを起動します。

> ifconfig up
Done
I (20308) OT_STATE: netif up

Thread プロトコル オペレーションを開始します。

> thread start
I(23058) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
Done
> I(23408) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition reattaching with Active Dataset
I(30028) OPENTHREAD:[N] Mle-----------: Attach attempt 1 unsuccessful, will try again in 0.288 seconds
I(30328) OPENTHREAD:[N] Mle-----------: Attach attempt 2, AnyPartition 
I(33498) OPENTHREAD:[N] Mle-----------: Delay processing Announce - channel 21, panid 0x1444
I(33758) OPENTHREAD:[N] Mle-----------: Processing Announce - channel 21, panid 0x1444
I(33758) OPENTHREAD:[N] Mle-----------: Role detached -> disabled
I(33758) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
I(34178) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition 
I(35068) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> 2c01
I(35068) OPENTHREAD:[N] Mle-----------: Role detached -> child

しばらく待ってから、デバイスの状態を確認します。「Child」である必要があります。

> state
child
Done

ロールを [ルーター] に設定します。

> state router
Done
I(51028) OPENTHREAD:[N] Mle-----------: RLOC16 2c01 -> 2800
I(51028) OPENTHREAD:[N] Mle-----------: Role child -> router
I(51028) OPENTHREAD:[N] Mle-----------: Partition ID 0x28b518c6
> 

esp_ot_tp_LR.jpg

6. 安全なコミッショニングで Thread ネットワークに接続

このセッションでは、セキュリティ コミッショニングを介して Board2 をネットワークに追加します。

BR コミッショナーから PSKc とパニドを入手:

## BR Commissioner ##
----------------------
> pskc
54e7f18d2575014da94db09df29c5df0
Done
> panid
0x1444
Done

ネットワーク情報を Board2 に構成します。

## Board2 Joiner ##
----------------------
> dataset pskc 54e7f18d2575014da94db09df29c5df0
Done
> dataset panid 0x1444
Done

このデータセットをアクティブなデータセットとして commit します。

## Board2 Joiner ##
----------------------
> dataset commit active 
Done

IPv6 インターフェースを起動します。

## Board2 Joiner ##
----------------------
> ifconfig up
Done
I (29146) OT_STATE: netif up

Board2 から eui64 を取得します。

## Board2 Joiner ##
----------------------
> eui64
4831b7fffec02be1
Done

BR Commissioner で、コミッショナーを起動し、参加可能なデバイスの eui64 と、Joiner の認証情報(J01NME など)を指定します。Joiner Credential は、6 ~ 32 文字のデバイス固有の文字列で、すべて大文字の英数字(読みやすくするために I、O、Q、Z を除く 0 ~ 9 と A ~ Y は除く)で構成されます。

## BR Commissioner ##
----------------------
> commissioner start
Commissioner: petitioning
Done
Commissioner: active
> commissioner joiner add 4831b7fffec02be1 J01NME
Done

[Board2 Joiner] に切り替えます。BR コミッショナーで設定した結合者認証情報で結合者ロールを開始します。

## Board2 Joiner ##
----------------------
> ifconfig up
Done
> joiner start J01NME
Done

1 分以内に、認証が成功したことを示す確認メッセージが表示されます。

## Board2 Joiner ##
----------------------
>
Join success

その後、BR コミッショナーが形成する Thread ネットワークを開始して参加できます。

Thread プロトコル オペレーションを開始します。

> thread start
I(35727) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
Done
> I(36197) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition reattaching with Active Dataset
I(37007) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> 2801
I(37007) OPENTHREAD:[N] Mle-----------: Role detached -> child

ロールを [ルーター] に設定します。

> state router
Done
I(46057) OPENTHREAD:[N] Mle-----------: RLOC16 2801 -> 4400
I(46057) OPENTHREAD:[N] Mle-----------: Role child -> router
I(46057) OPENTHREAD:[N] Mle-----------: Partition ID 0x28b518c6
> 

これで、次のようなトポロジを持つ Thread ネットワークが確立されます。

esp_ot_tp_LRR.jpg

7. Thread ノード間で IPv6 アドレスを ping する

ping コマンドを使用して、任意の 2 つのボード間で通信できます。ipaddr コマンドを使用して、各ボードの IPv6 アドレスを出力します。

## BR Commissioner ##
----------------------
> ipaddr
fd6a:b54b:d6a3:b05a:0:ff:fe00:fc00          # Leader Anycast Locator (ALOC)
fd6a:b54b:d6a3:b05a:0:ff:fe00:2c00          # Routing Locator (RLOC)
fd6a:b54b:d6a3:b05a:a8df:eb43:63d8:bda0     # Mesh-Local EID (ML-EID) 
fe80:0:0:0:687c:7248:cc14:9c4d              # Link-Local Address (LLA)
Done
> 
## Board1 Joiner ##
----------------------
> ipaddr
fd6a:b54b:d6a3:b05a:0:ff:fe00:2800          # Routing Locator (RLOC)
fd6a:b54b:d6a3:b05a:e461:db08:c833:1248     # Mesh-Local EID (ML-EID)
fe80:0:0:0:18ac:df04:4671:6a45              # Link-Local Address (LLA)
Done
## Board2 Joiner ##
----------------------
> ipaddr
fd6a:b54b:d6a3:b05a:0:ff:fe00:4400          # Routing Locator (RLOC)
fd6a:b54b:d6a3:b05a:d7dc:8e90:9bc9:ecbc     # Mesh-Local EID (ML-EID)
fe80:0:0:0:a8cc:1483:f696:91a2              # Link-Local Address (LLA)
Done

たとえば、BR コミッショナーから Board2 MLE-ID に ping するには、BR コミッショナーで次のコマンドを実行します。

## BR Commissioner ##
----------------------
> ping fd6a:b54b:d6a3:b05a:d7dc:8e90:9bc9:ecbc
16 bytes from fd6a:b54b:d6a3:b05a:d7dc:8e90:9bc9:ecbc: icmp_seq=1 hlim=255 time=123ms
1 packets transmitted, 1 packets received. Packet loss = 0.0%. Round-trip min/avg/max = 123/123.0/123 ms.
Done

8. UDP を使用して Thread ノード間でメッセージを受け渡す

このセッションでは、2 つの Thread デバイス間でメッセージを送信する方法について説明します。たとえば、UDP を開いてポート 20617 にバインドし、BR のすべてのアドレスをリッスンします。

## BR Commissioner ##
----------------------
> udp open
Done
> udp bind :: 20617
I (1298739) OPENTHREAD: Platform UDP bound to port 20617
Done

次に、Board1 から BR MLE-ID アドレスとポート 20617 にメッセージを送信します。

## Board1 Joiner ##
----------------------
> udp open
Done
> udp send fd6a:b54b:d6a3:b05a:a8df:eb43:63d8:bda0 20617 ESP

BR で受信したメッセージは次のように確認できます。

## BR Commissioner ##
----------------------
3 bytes from fd6a:b54b:d6a3:b05a:e461:db08:c833:1248 49154 ESP

9. 完了

ESP ボードを使用して、物理的な Thread ネットワークを構築できました。

esp_ot_final_topology.jpg

ここまでの学習内容は次のとおりです。

  • OpenThread CLI バイナリをビルドして ESP ボードに書き込む。
  • ESP Thread ボーダー ルーター ボードにフラッシュするボーダー ルーターを構築しています。
  • ESP Monitor と OpenThread CLI で Thread ノードを手動で管理する。
  • Thread ボーダー ルーターで Thread ネットワークを形成する
  • Thread ネットワークに対するデバイスのコミッショニングを保護する。
  • Thread ノード間で IPv6 アドレスを ping する。
  • UDP を使用して Thread ノード間でメッセージを受け渡す。

参考資料

以下を含むさまざまな OpenThread リソースについては、openthread.ioGitHub をご覧ください。

関連資料: