1. はじめに
Google がリリースした OpenThread は、Thread ネットワーク プロトコルのオープンソース実装です。Google Nest は、Google Nest 製品で使用されている技術を幅広く利用できるようにし、スマートホーム製品の開発を加速させるため、OpenThread をリリースしました。
Thread 仕様は、家庭用アプリケーション向けに、IPv6 ベースの信頼性、安全性、消費電力の少ないワイヤレス デバイス間通信プロトコルを定義しています。OpenThread は、IPv6、6LoWPAN、MAC セキュリティを備えた IEEE 802.15.4、メッシュリンク確立、メッシュルーティングなど、すべての Thread ネットワーキングレイヤを実装しています。
この Codelab では、Docker を使用して、エミュレートされたデバイスで Thread ネットワークをシミュレートする手順を説明します。
学習内容
- OpenThread ビルド ツールチェーンの設定方法
- Thread ネットワークをシミュレートする方法
- Thread ノードの認証方法
- OpenThread Daemon を使用して Thread ネットワークを管理する方法
必要なもの
- Docker
- Linux、ネットワーク ルーティングに関する基本的な知識
2. Docker を設定する
この Codelab は、Linux、Mac OS X、または Windows マシンで Docker を使用するように設計されています。推奨される環境は Linux です。
Docker のインストール
任意の OS に Docker をインストールします。
Docker イメージを pull する
Docker がインストールされたら、ターミナル ウィンドウを開き、openthread/environment
Docker イメージを pull します。このイメージは、ビルド済みの OpenThread と OpenThread Daemon を特徴としており、この Codelab ですぐに使用できます。
$ docker pull openthread/environment:latest
ダウンロードが完了するまで数分かかることがあります。
ターミナル ウィンドウで、イメージから Docker コンテナを起動し、その bash
シェルに接続します。
$ docker run --name codelab_otsim_ctnr -it --rm \ --sysctl net.ipv6.conf.all.disable_ipv6=0 \ --cap-add=net_admin openthread/environment bash
--rm
オプションを指定すると、コンテナの終了時にコンテナが削除されます。コンテナを削除したくない場合は、このオプションを使用しないでください。
この Codelab に必要なフラグに注意してください。
--sysctl net.ipv6.conf.all.disable_ipv6=0
- コンテナ内で IPv6 を有効にします。--cap-add=net_admin
- NET_ADMIN 機能を有効にします。これにより、IP ルートの追加など、ネットワーク関連の操作を実行できます。
コンテナに格納すると、次のようなプロンプトが表示されます。
root@c0f3912a74ff:/#
上記の例では、c0f3912a74ff
がコンテナ ID です。Docker コンテナ インスタンスのコンテナ ID は、この Codelab のプロンプトに表示されるものとは異なります。
Docker の使用
この Codelab は、Docker の基本的な使用法を理解していることを前提としています。Codelab の全体を最後まで Docker コンテナ内にとどめる必要があります。
3. Thread ネットワークをシミュレートする
この Codelab で使用するサンプル アプリケーションは、基本的なコマンドライン インターフェース(CLI)を介して OpenThread 構成および管理インターフェースを公開する、最小限の OpenThread アプリケーションを示しています。
この演習では、エミュレートされた Thread デバイスを別のエミュレートされた Thread デバイスから ping するために必要な最小限の手順を説明します。
下図は、基本的な Thread ネットワーク トポロジを示しています。この演習では、緑色の円内の 2 つのノード、すなわち 1 つの接続を持つスレッド リーダーと Thread ルーターをエミュレートします。
ネットワークを作成する
1. Node 1 の起動
まだ行っていない場合は、ターミナル ウィンドウで Docker コンテナを起動し、その bash
シェルに接続します。
$ docker run --name codelab_otsim_ctnr -it --rm \ --sysctl net.ipv6.conf.all.disable_ipv6=0 \ --cap-add=net_admin openthread/environment bash
Docker コンテナで、ot-cli-ftd
バイナリを使用して、エミュレートされた Thread デバイスの CLI プロセスを生成します。
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 1
注: このコマンドを実行した後に >
プロンプトが表示されない場合は、enter
を押してください。
このバイナリは OpenThread デバイスを実装します。IEEE 802.15.4 無線ドライバは UDP の上位に実装されています(IEEE 802.15.4 フレームは UDP ペイロード内で渡されます)。
1
の引数は、「factory-assigned」の最下位ビットを表すファイル記述子です。エミュレートされたデバイスでは IEEE EUI-64。この値は、IEEE 802.15.4 無線エミュレーション用に UDP ポートにバインドする場合にも使用されます(ポート = 9000 + ファイル ディスクリプタ)。この Codelab でエミュレートされた Thread デバイスのインスタンスは、それぞれ異なるファイル記述子を使用します。
注: エミュレートされたデバイスのプロセスを生成するときは、この Codelab に記載されているように、1
以上のファイル記述子のみを使用してください。0
のファイル記述子は、他の用途のために予約されています。
新しい運用データセットを作成し、アクティブ データセットとして commit する。運用データセットは、作成する Thread ネットワークの構成です。
> dataset init new Done > dataset Active Timestamp: 1 Channel: 20 Channel Mask: 07fff800 Ext PAN ID: d6263b6d857647da Mesh Local Prefix: fd61:2344:9a52:ede0/64 Network Key: e4344ca17d1dca2a33f064992f31f786 Network Name: OpenThread-c169 PAN ID: 0xc169 PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4 Security Policy: 0, onrcb Done
このデータセットをアクティブなデータセットとして commit します。
> dataset commit active Done
IPv6 インターフェースを起動します。
> ifconfig up Done
スレッド プロトコル オペレーションを開始します。
> thread start Done
数秒待ってから、デバイスが Thread Leader になったことを確認します。リーダーは、ルーター ID の割り当てを管理するデバイスです。
> state leader Done
ノード 1 の Thread インターフェースに割り当てられた IPv6 アドレスを表示します(実際の出力は異なります)。
> ipaddr fd61:2344:9a52:ede0:0:ff:fe00:fc00 fd61:2344:9a52:ede0:0:ff:fe00:5000 fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6 fe80:0:0:0:94da:92ea:1353:4f3b Done
特定の IPv6 アドレスタイプに注意してください。
- 先頭は
fd
= mesh-local - 先頭が「
fe80
」 = リンクローカル
メッシュローカル アドレス タイプは次のように分類されます。
ff:fe00
= ルーター ロケータ(RLOC)を含むff:fe00
= エンドポイント識別子(EID)を含まない
コンソール出力で EID を特定し、後で使用できるようにメモしておきます。上記のサンプル出力では、EID は次のようになります。
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
2. Node 2 の起動
新しいターミナルを開き、現在実行中の Docker コンテナで Node 2 に使用する bash
シェルを実行します。
$ docker exec -it codelab_otsim_ctnr bash
この新しい bash
プロンプトで、引数 2
を指定して CLI プロセスを生成します。これは、エミュレートされた 2 つ目の Thread デバイスです。
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2
注: このコマンドを実行した後に >
プロンプトが表示されない場合は、enter
を押してください。
ノード 1 の運用データセットと同じ値を使用して、Thread ネットワーク キーと PAN ID を構成します。
> dataset networkkey e4344ca17d1dca2a33f064992f31f786 Done > dataset panid 0xc169 Done
このデータセットをアクティブなデータセットとして commit します。
> dataset commit active Done
IPv6 インターフェースを起動します。
> ifconfig up Done
スレッド プロトコル オペレーションを開始します。
> thread start Done
デバイスは子として初期化されます。Thread の子はエンドデバイスと同等です。エンドデバイスは、親デバイスとのみユニキャスト トラフィックを送受信する Thread デバイスです。
> state child Done
2 分以内に、child
から router
に状態が切り替わるはずです。Thread ルーターは、Thread デバイス間でトラフィックをルーティングできます。「親」とも呼ばれます。
> state router Done
ネットワークを確認する
ルーター テーブルを見ると、メッシュ ネットワークを簡単に確認できます。
1. 接続を確認する
Node 2 で RLOC16 を取得します。RLOC16 は、デバイスの RLOC IPv6 アドレスの最後の 16 ビットです。
> rloc16 5800 Done
Node 1 のルーター表で Node 2 の RLOC16 を確認します。まず、ノード 2 がルーターの状態に切り替わったことを確認してください。
> router table | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+--------+-------+---+--------------------+ | 20 | 0x5000 | 63 | 0 | 0 | 0 | 0 | 96da92ea13534f3b | | 22 | 0x5800 | 63 | 0 | 3 | 3 | 23 | 5a4eb647eb6bc66c |
ノード 2 の 0x5800
の RLOC がテーブルに表示され、メッシュに接続されていることを確認します。
2. ノード 2 からノード 1 に ping を実行する
エミュレートされた 2 つの Thread デバイス間の接続を検証します。Node 2 で、Node 1 に割り当てられた EID を ping
します。
> ping fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6 > 16 bytes from fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6: icmp_seq=1 hlim=64 time=12ms
enter
キーを押して、>
CLI プロンプトに戻ります。
ネットワークをテストする
エミュレートされた 2 つの Thread デバイス間で正常に ping を実行できるようになったので、1 つのノードをオフラインにしてメッシュ ネットワークをテストします。
Node 1 に戻り、Thread を停止します。
> thread stop Done
Node 2 に切り替えて、状態を確認します。2 分以内に、ノード 2 はリーダー(ノード 1)がオフラインであることを検出し、ノード 2 がネットワークの leader
に遷移します。
> state router Done ... > state leader Done
確認したら、Thread を停止して Node 2 を出荷時の設定にリセットしてから、Docker bash
プロンプトに戻ります。この演習で使用した Thread ネットワーク認証情報が次の演習に引き継がれないようにするため、出荷時設定へのリセットが行われます。
> thread stop Done > factoryreset > > exit root@c0f3912a74ff:/#
factoryreset
コマンドの後に >
プロンプトが再度表示されるように、enter
を数回押す必要がある場合があります。Docker コンテナは終了しないでください。
また、ノード 1 を出荷時の設定にリセットして終了します。
> factoryreset > > exit root@c0f3912a74ff:/#
使用可能なすべての CLI コマンドについては、OpenThread CLI リファレンスをご覧ください。
4. コミッショニングでノードを認証する
前の演習では、シミュレートされた 2 台のデバイスで Thread ネットワークを設定し、接続を検証しました。ただし、これにより、認証されていない IPv6 リンクローカル トラフィックのみがデバイス間で送受信されます。グローバル IPv6 トラフィックを両者間で(および Thread ボーダー ルーター経由でインターネットに)ルーティングするには、ノードを認証する必要があります。
認証を行うには、1 つのデバイスがコミッショナーとして機能する必要があります。コミッショナーは現在、新しい Thread デバイスの認証サーバーで選出されており、デバイスがネットワークに接続するために必要なネットワーク認証情報の提供を承認しています。
この演習では、前と同じ 2 ノード トポロジを使用します。認証については、Thread Leader はコミッショナー、Thread Router は Joiner として、
Docker
残りの演習の各ノード(ターミナル ウィンドウ)で、必ず OpenThread ビルドで Docker コンテナが実行されていることを確認します。前の演習から続行する場合、同じ Docker コンテナ内で 2 つの bash
プロンプトがすでに開いているはずです。実行されていない場合は、Docker のトラブルシューティングの手順を確認するか、Thread ネットワークをシミュレートするの演習をやり直します。
1. ネットワークの作成
Node 1 で、CLI プロセスを生成します。
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 1
注: このコマンドを実行した後に >
プロンプトが表示されない場合は、enter
を押してください。
新しい運用データセットを作成し、それをアクティブなデータセットとして commit して、スレッドを開始します。
> dataset init new Done > dataset Active Timestamp: 1 Channel: 12 Channel Mask: 07fff800 Ext PAN ID: e68d05794bf13052 Mesh Local Prefix: fd7d:ddf7:877b:8756/64 Network Key: a77fe1d03b0e8028a4e13213de38080e Network Name: OpenThread-8f37 PAN ID: 0x8f37 PSKc: f9debbc1532487984b17f92cd55b21fc Security Policy: 0, onrcb Done
このデータセットをアクティブなデータセットとして commit します。
> dataset commit active Done
IPv6 インターフェースを起動します。
> ifconfig up Done
スレッド プロトコル オペレーションを開始します。
> thread start Done
数秒待ってから、デバイスがスレッド リーダーになっていることを確認します。
> state leader Done
2. コミッショナー ロールを開始する
まだノード 1 でコミッショナー ロールを開始します。
> commissioner start Done
J01NME
Joiner 認証情報を持つ任意の Joiner(*
ワイルドカードを使用)がネットワークへのコミッショニングを許可します。Joiner は、人間の管理者が委託した Thread ネットワークに追加するデバイスです。
> commissioner joiner add * J01NME Done
3. Joiner ロールを開始する
Docker コンテナの 2 つ目のターミナル ウィンドウで、新しい CLI プロセスを生成します。これがノード 2 です。
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2
Node 2 で、J01NME
Joiner 認証情報を使用して Joiner ロールを有効にします。
> ifconfig up Done > joiner start J01NME Done
... 確認されるまで数秒お待ちください ...
Join success
Joiner として、デバイス(ノード 2)はコミッショナー(ノード 1)で自身を正常に認証し、Thread ネットワーク認証情報を受信しました。
Node 2 が認証されたので、Thread を開始します。
> thread start Done
4. ネットワーク認証を検証する
Node 2 の state
をチェックして、ネットワークに参加したことを確認します。2 分以内に、ノード 2 は child
から router
に移行します。
> state child Done ... > state router Done
5. 構成をリセット
次の演習の準備をするために、構成をリセットします。各ノードで Thread を停止し、出荷時の設定にリセットして、エミュレートされた Thread デバイスを終了します。
> thread stop Done > factoryreset > > exit root@c0f3912a74ff:/#
factoryreset
コマンドの後に >
プロンプトが再度表示されるように、enter
を数回押す必要がある場合があります。
5. OpenThread Daemon を使用してネットワークを管理する
この演習では、1 つの CLI インスタンス(1 つの埋め込み SoC Thread デバイス)と 1 つの無線コプロセッサ(RCP)インスタンスをシミュレートします。
ot-daemon
は OpenThread Posix アプリのモードであり、入力と出力として UNIX ソケットを使用するため、OpenThread コアをサービスとして実行できます。クライアントは、OpenThread CLI をプロトコルとして使用してソケットに接続することで、このサービスと通信できます。
ot-ctl
は、RCP の管理と構成のために ot-daemon
が提供する CLI です。これにより、RCP を Thread デバイスによって作成されたネットワークに接続します。
Docker
この演習の各ノード(ターミナル ウィンドウ)で、OpenThread ビルドで Docker コンテナが実行されていることを確認します。前の演習から続行する場合、同じ Docker コンテナ内で 2 つの bash
プロンプトがすでに開いているはずです。それ以外の場合は、Docker のトラブルシューティングの手順をご覧ください。
ot-daemon を使用する
この演習では、以下に対応する 3 つのターミナル ウィンドウを使用します。
- シミュレートされた Thread デバイスの CLI インスタンス(ノード 1)
ot-daemon
プロセスot-ctl
CLI インスタンス
1. Node 1 の起動
最初のターミナル ウィンドウで、エミュレートされた Thread デバイスの CLI プロセスを生成します。
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 1
注: このコマンドを実行した後に >
プロンプトが表示されない場合は、enter
を押してください。
新しい運用データセットを作成し、それをアクティブなデータセットとして commit して、スレッドを開始します。
> dataset init new Done > dataset Active Timestamp: 1 Channel: 13 Channel Mask: 07fff800 Ext PAN ID: 97d584bcd493b824 Mesh Local Prefix: fd55:cf34:dea5:7994/64 Network Key: ba6e886c7af50598df1115fa07658a83 Network Name: OpenThread-34e4 PAN ID: 0x34e4 PSKc: 38d6fd32c866927a4dfcc06d79ae1192 Security Policy: 0, onrcb Done
このデータセットをアクティブなデータセットとして commit します。
> dataset commit active Done
IPv6 インターフェースを起動します。
> ifconfig up Done
スレッド プロトコル オペレーションを開始します。
> thread start Done
ノード 1 の Thread インターフェースに割り当てられた IPv6 アドレスを表示します。
> ipaddr fd55:cf34:dea5:7994:0:ff:fe00:fc00 fd55:cf34:dea5:7994:0:ff:fe00:d000 fd55:cf34:dea5:7994:460:872c:e807:c4ab fe80:0:0:0:9cd8:aab6:482f:4cdc Done >
Thread ネットワークをシミュレートするの手順で説明したように、1 つのアドレスはリンクローカル(fe80
)、3 つのアドレスはメッシュローカル(fd
)です。EID が、アドレスに ff:fe00
を含まないメッシュローカル アドレスである。このサンプル出力では、EID は fd55:cf34:dea5:7994:460:872c:e807:c4ab
です。
ipaddr
出力で、ノードとの通信に使用される特定の EID を特定します。
2. ot-daemon の起動
2 つ目のターミナル ウィンドウで、tun
デバイスノードを作成し、読み取り/書き込み権限を設定します。
root@c0f3912a74ff:/# mkdir -p /dev/net && mknod /dev/net/tun c 10 200 root@c0f3912a74ff:/# chmod 600 /dev/net/tun
このデバイスは、仮想デバイスでパケットの送受信に使用されます。デバイスがすでに作成されている場合、エラーが表示されることがあります。これは正常であり、無視してかまいません。
RCP ノードの ot-daemon
を開始します。RCP ノードはノード 2 と呼びます。-v
詳細フラグを使用して、ログ出力を表示し、実行中であることを確認します。
root@c0f3912a74ff:/# /openthread/build/posix/src/posix/ot-daemon -v \ 'spinel+hdlc+forkpty:///openthread/build/examples/apps/ncp/ot-rcp?forkpty-arg=2'
成功すると、詳細モードの ot-daemon
は次のような出力を生成します。
ot-daemon[31]: Running OPENTHREAD/297a880; POSIX; Feb 1 2022 04:43:39 ot-daemon[31]: Thread version: 3 ot-daemon[31]: Thread interface: wpan0 ot-daemon[31]: RCP version: OPENTHREAD/297a880; SIMULATION; Feb 1 2022 04:42:50
ターミナルを開いたまま、バックグラウンドで動作させます。ここにはこれ以上コマンドを入力する必要はありません。
3. ot-ctl を使用してネットワークに参加する
ノード 2(ot-daemon
RCP)はまだ Thread ネットワークへのコミッショニングを行っていません。そこで役立つのが ot-ctl
です。ot-ctl
は OpenThread CLI アプリと同じ CLI を使用します。そのため、シミュレートされた他の Thread デバイスと同じ方法で ot-daemon
ノードを制御できます。
3 つ目のターミナル ウィンドウを開き、既存のコンテナを実行します。
$ docker exec -it codelab_otsim_ctnr bash
コンテナで、ot-ctl
を起動します。
root@c0f3912a74ff:/# /openthread/build/posix/src/posix/ot-ctl >
この 3 番目のターミナル ウィンドウで ot-ctl
を使用して、2 番目のターミナル ウィンドウで ot-daemon
で開始したノード 2(RCP ノード)を管理します。Node 2 の state
を確認します。
> state disabled Done
Node 2 の eui64
を取得して、参加を特定の Joiner に制限します。
> eui64 18b4300000000001 Done
Node 1(最初のターミナル ウィンドウ)でコミッショナーを起動し、参加をその eui64 のみに制限します。
> commissioner start Done > commissioner joiner add 18b4300000000001 J01NME Done
3 つ目のターミナル ウィンドウで、ノード 2 のネットワーク インターフェースを表示し、ネットワークに参加します。
> ifconfig up Done > joiner start J01NME Done
... 確認されるまで数秒お待ちください ...
Join success
Joiner として、RCP(ノード 2)はコミッショナー(ノード 1)で自身を正常に認証し、Thread Network 認証情報を受け取りました。
次に、ノード 2 を Thread ネットワークに接続します(3 つ目のターミナル ウィンドウで再度もあります)。
> thread start Done
4. ネットワーク認証を検証する
3 番目のターミナルで、Node 2 の state
をチェックして、ネットワークに参加したことを確認します。2 分以内に、ノード 2 は child
から router
に移行します。
> state child Done ... > state router Done
5. 接続を検証する
3 つ目のターミナル ウィンドウで、Ctrl+D または exit
コマンドを使用して ot-ctl
を終了し、コンテナの bash
コンソールに戻ります。このコンソールから、ping6
コマンドで EID を使用してノード 1 に ping を実行します。ot-daemon
RCP インスタンスが正常に Thread ネットワークに参加して通信している場合、ping は成功します。
root@c0f3912a74ff:/# ping6 -c 4 fd55:cf34:dea5:7994:460:872c:e807:c4ab PING fd55:cf34:dea5:7994:460:872c:e807:c4ab (fd55:cf34:dea5:7994:460:872c:e807:c4ab): 56 data bytes 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=0 ttl=64 time=4.568 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=1 ttl=64 time=6.396 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=2 ttl=64 time=7.594 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=3 ttl=64 time=5.461 ms --- fd55:cf34:dea5:7994:460:872c:e807:c4ab ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max/stddev = 4.568/6.005/7.594/1.122 ms
6. Docker のトラブルシューティング
Docker コンテナを終了した場合
bash
プロンプトが表示された場合は、実行中かどうかを確認し、必要に応じて再起動または再入力する必要がある場合があります。--rm
オプションを使用せずに作成した Docker コンテナは、引き続き存在します。
実行中の Docker コンテナを表示するには:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 505fc57ffc72 environment "bash" 10 minutes ago Up 10 minutes codelab_otsim_ctnr
すべての Docker コンテナ(実行中と停止中の両方)を表示するには:
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 505fc57ffc72 environment "bash" 10 minutes ago Up 10 minutes codelab_otsim_ctnr
いずれかの docker ps
コマンドの出力にコンテナ codelab_otsim_ctnr
が表示されない場合は、もう一度実行します。
$ docker run --name codelab_otsim_ctnr -it --rm \ --sysctl net.ipv6.conf.all.disable_ipv6=0 \ --cap-add=net_admin openthread/environment bash
--rm
オプションは、コンテナの終了時にコンテナを削除する場合にのみ使用します。
コンテナが停止している場合は(docker ps -a
にリストされ、docker ps
にはリストされません)、再起動します。
$ docker start -i codelab_otsim_ctnr
Docker コンテナがすでに実行中(docker ps
に表示)の場合は、各ターミナルでコンテナに再接続します。
$ docker exec -it codelab_otsim_ctnr bash
「操作は許可されていません」エラー
mknod
コマンドを使用して新しい OpenThread ノードを作成するときに Operation not permitted
エラーが発生した場合は、この Codelab で紹介しているコマンドに従い、root ユーザーとして Docker を実行していることを確認します。この Codelab では、Docker をルートレス モードで実行することはサポートされていません。
7. 完了
OpenThread を使用して最初の Thread ネットワークのシミュレートに成功しました。うまくできました。
この Codelab では、以下について学びました。
- OpenThread Simulation Docker コンテナの起動と管理
- Thread ネットワークをシミュレートする
- Thread ノードを認証する
- OpenThread Daemon を使用して Thread ネットワークを管理する
Thread と OpenThread について詳しくは、以下のリファレンスをご覧ください。
- openthread.io の Thread Primer
- Thread の仕様
- OpenThread GitHub リポジトリ
- OpenThread CLI リファレンス
- OpenThread Docker の追加サポート
または、Docker コンテナで OpenThread ボーダー ルーターを使用してみます。