nRF52840 ボードと OpenThread で Thread ネットワークを構築

1. はじめに

26b7f4f6b3ea0700.png

Google がリリースした OpenThread は、Thread® ネットワーキング プロトコルのオープンソース実装です。Google Nest は、Google Nest 製品で使用されているテクノロジーをデベロッパーが幅広く利用できるように OpenThread をリリースし、スマートホーム向け製品の開発を加速させています。

Thread 仕様は、ホーム アプリケーション向けの IPv6 ベースの信頼性が高く安全な低電力のワイヤレス デバイス間通信プロトコルを定義しています。OpenThread は、IPv6、6LoWPAN、MAC セキュリティ付き IEEE 802.15.4、メッシュリンク確立、メッシュ ルーティングなど、すべての Thread ネットワーキング レイヤを実装しています。

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

4806d16a8c137c6d.jpeg

学習内容

  • OpenThread CLI バイナリをビルドして開発ボードに書き込む
  • Linux マシンと開発ボードで構成される RCP の構築
  • OpenThread Daemon と ot-ctl を使用して RCP と通信する
  • GNU Screen と OpenThread CLI を使用して Thread ノードを手動で管理する
  • Thread ネットワークへのデバイスの安全なコミッショニング
  • IPv6 マルチキャストの仕組み
  • UDP を使用して Thread ノード間でメッセージを渡す

必要なもの

ハードウェア:

  • Nordic Semiconductor nRF52840 開発ボード x 3
  • ボードを接続するための USB - マイクロ USB ケーブル 3 本
  • 3 つ以上の USB ポートを備えた Linux マシン

ソフトウェア:

  • GNU ツールチェーン
  • Nordic nRF5x コマンドライン ツール
  • Segger J-Link ソフトウェア
  • OpenThread
  • Git

2. 開始するには

OpenThread シミュレーション

始める前に、OpenThread シミュレーション Codelab を実行して、Thread の基本的なコンセプトと OpenThread CLI について理解しておくことをおすすめします。

シリアルポート ターミナル

ターミナルを通じてシリアルポートに接続する方法に精通している必要があります。この Codelab では GNU Screen を使用して説明しますが、その他のターミナル ソフトウェアも使用できます。

Linux マシン

この Codelab は、i386 ベースまたは x86 ベースの Linux マシンを使用して、無線コプロセッサ(RCP)Thread デバイスのホストとして機能し、すべての Thread 開発ボードをフラッシュすることを前提として設計されています。すべての手順は Ubuntu 14.04.5 LTS(Trusty Tahr)でテストしました。

Nordic Semiconductor nRF52840 ボード

この Codelab では、3 つの nRF52840 PDK ボードを使用します。

a6693da3ce213856.png

SEGGER J-Link を使用して、オンボード JTAG モジュールを備えた nRF52840 ボードをプログラミングします。Linux マシンにインストールします。

マシンに適したパッケージをダウンロードし、適切な場所にインストールします。Linux では /opt/SEGGER/JLink です。

nRF5x コマンドライン ツールをインストールする

nRF5x コマンドライン ツールを使用すると、OpenThread バイナリを nRF52840 ボードに書き込むことができます。Linux マシンに適切な nRF5x-Command-Line-Tools-<OS> ビルドをインストールします。

抽出したパッケージをルートフォルダ ~/ に配置します。

ARM GNU ツールチェーンをインストールする

ビルドには ARM GNU ツールチェーンが使用されます。

抽出したアーカイブは、Linux マシンの /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/ に配置することをおすすめします。インストール手順については、アーカイブの readme.txt ファイルの手順に沿ってください。

Screen をインストールする(省略可)

Screen は、シリアルポートで接続されたデバイスにアクセスするためのシンプルなツールです。この Codelab では Screen を使用しますが、任意のシリアルポート ターミナル アプリケーションを使用できます。

$ sudo apt-get install screen

3. リポジトリのクローンを作成する

OpenThread

OpenThread のクローンを作成してインストールします。script/bootstrap コマンドは、ツールチェーンがインストールされ、環境が正しく構成されていることを確認します。

$ mkdir -p ~/src
$ cd ~/src
$ git clone --recursive https://github.com/openthread/openthread.git
$ cd openthread
$ ./script/bootstrap

OpenThread デーモンをビルドします。

$ script/cmake-build posix -DOT_DAEMON=ON

これで、nRF52840 ボードに OpenThread をビルドしてフラッシュする準備が整いました。

4. RCP Joiner を設定する

ビルドとフラッシュ

Joiner とネイティブ USB 機能を使用して OpenThread nRF52840 のサンプルをビルドします。デバイスは Joiner ロールを使用して、Thread ネットワークで安全に認証され、コミッショニングされます。ネイティブ USB を使用すると、nRF52840 とホスト間のシリアル トランスポートとして USB CDC ACM を使用できます。

常に rm -rf build を実行して、以前のビルドのリポジトリをクリーンアップします。

$ cd ~/src
$ git clone --recursive https://github.com/openthread/ot-nrf528xx.git
$ cd ot-nrf528xx
$ script/build nrf52840 USB_trans

OpenThread RCP バイナリを含むディレクトリに移動し、16 進数形式に変換します。

$ cd ~/src/ot-nrf528xx/build/bin
$ arm-none-eabi-objcopy -O ihex ot-rcp ot-rcp.hex

nRF52840 ボードの外部電源ピンの横にあるマイクロ USB デバッグポートに USB ケーブルを取り付け、Linux マシンに差し込みます。nRF52840 ボードの [nRF power source] スイッチを [VDD] に設定します。正しく接続されると、LED5 が点灯します。

20a3b4b480356447.png

Linux マシンに初めて接続されたボードの場合、シリアルポート /dev/ttyACM0 として表示されます(すべての nRF52840 ボードはシリアルポート識別子に ttyACM を使用します)。

$ ls /dev/ttyACM*
/dev/ttyACM0

RCP に使用されている nRF52840 ボードのシリアル番号をメモします。

c00d519ebec7e5f0.jpeg

nRFx コマンドライン ツールの場所に移動し、ボードのシリアル番号を使用して、OpenThread RCP の 16 進ファイルを nRF52840 ボードに書き込みます。--verify フラグを省略すると、エラーなしでフラッシュ プロセスが失敗する可能性があることを示す警告メッセージが表示されます。

$ cd ~/nrfjprog/
$ ./nrfjprog -f nrf52 -s 683704924  --verify --chiperase --program \
       ~/src/ot-nrf528xx/build/bin/ot-rcp.hex --reset

成功すると、次の出力が生成されます。

Parsing hex file.
Erasing user available code and UICR flash areas.
Applying system reset.
Checking that the area to write is not protected.
Programing device.
Applying system reset.
Run.

ボードのロールを混同しないように、ボードに「RCP」というラベルを付けます。

ネイティブ USB に接続する

OpenThread RCP ビルドではシリアル トランスポートとしてネイティブ USB CDC ACM を使用できるため、nRF52840 ボードの nRF USB ポートを使用して RCP ホスト(Linux マシン)と通信する必要があります。

USB ケーブルのマイクロ USB 端子を書き込み済みの nRF52840 ボードのデバッグ ポートから外し、RESET ボタンの横にあるマイクロ USB nRF USB ポートに再び接続します。[nRF power source] スイッチを [USB] に設定します。

46e7b670d2464842.png

OpenThread デーモンを起動する

RCP 設計では、OpenThread Daemon を使用して Thread デバイスと通信し、管理します。-v 詳細フラグを指定して ot-daemon を起動し、ログ出力を確認して実行中であることを確認します。

$ cd ~/src/openthread
$ sudo ./build/posix/src/posix/ot-daemon -v \
    'spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800'

成功すると、詳細モードの ot-daemon は次のような出力を生成します。

ot-daemon[12463]: Running OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; POSIX; Aug 30 2022 10:55:05
ot-daemon[12463]: Thread version: 4
ot-daemon[12463]: Thread interface: wpan0
ot-daemon[12463]: RCP version: OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; SIMULATION; Aug 30 2022 10:54:10

ot-daemon のログを表示できるように、このターミナル ウィンドウを開いたままにします。

ot-ctl を使用して RCP ノードと通信します。ot-ctl は OpenThread CLI アプリと同じ CLI を使用します。そのため、他のシミュレートされた Thread デバイスと同じ方法で ot-daemon ノードを制御できます。

2 番目のターミナル ウィンドウで、ot-ctl を起動します。

$ sudo ./build/posix/src/posix/ot-ctl
>

ot-daemon で起動したノード 2(RCP ノード)の state を確認します。

> state
disabled
Done

5. FTD をセットアップする

この Codelab で使用する他の 2 つの Thread ノードは、標準のシステム オン チップ(SoC)設計のフル Thread デバイス(FTD)です。1 つのデバイスが Commissioner として機能し、そのネットワーク上のデバイスを安全に認証してコミッショニングします。もう一方のデバイスは、コミッショナーが Thread ネットワークに対して認証できるジョイナーとして機能します。

ビルドとフラッシュ

コミッショナーとジョイナーのロールを有効にして、nRF52840 プラットフォーム用の OpenThread FTD の例をビルドします。

$ cd ~/src/ot-nrf528xx
$ rm -rf build
$ script/build nrf52840 USB_trans -DOT_JOINER=ON -DOT_COMMISSIONER=ON

OpenThread Full Thread Device(FTD)CLI バイナリを含むディレクトリに移動し、16 進形式に変換します。

$ cd ~/src/ot-nrf528xx/build/bin
$ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex

nRF52840 ボードの外部電源ピンの横にあるマイクロ USB ポートに USB ケーブルを取り付け、Linux マシンに差し込みます。RCP が Linux マシンに接続されたままの場合、この新しいボードはシリアルポート /dev/ttyACM1 として表示されます(すべての nRF52840 ボードはシリアルポート識別子に ttyACM を使用します)。

$ ls /dev/ttyACM*
/dev/ttyACM0  /dev/ttyACM1

前と同様に、FTD に使用されている nRF52840 ボードのシリアル番号をメモします。

c00d519ebec7e5f0.jpeg

nRFx コマンドライン ツールの場所に移動し、ボードのシリアル番号を使用して、OpenThread CLI FTD の 16 進数ファイルを nRF52840 ボードに書き込みます。

$ cd ~/nrfjprog/
$ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \
       ~/src/ot-nrf528xx/build/bin/ot-cli-ftd.hex --reset

ボードに「Commissioner」というラベルを付けます。

ネイティブ USB に接続する

OpenThread FTD ビルドではシリアル トランスポートとしてネイティブ USB CDC ACM を使用できるため、nRF52840 ボードの nRF USB ポートを使用して RCP ホスト(Linux マシン)と通信する必要があります。

USB ケーブルのマイクロ USB 端子を書き込み済みの nRF52840 ボードのデバッグ ポートから外し、RESET ボタンの横にあるマイクロ USB nRF USB ポートに再び接続します。[nRF power source] スイッチを [USB] に設定します。

46e7b670d2464842.png

ビルドを確認する

ターミナル ウィンドウから GNU Screen を使用して OpenThread CLI にアクセスし、ビルドが成功したことを確認します。

$ screen /dev/ttyACM1

新しいウィンドウで、キーボードの Return キーを数回押して、OpenThread CLI の > プロンプトを表示します。IPv6 インターフェースを起動してアドレスを確認します。

> ifconfig up
Done
> ipaddr
fe80:0:0:0:1cd6:87a9:cb9d:4b1d
Done

Ctrl+A を使用 →

d FTD Commissioner CLI 画面から切り離して Linux ターミナルに戻る。これにより、次のボードをフラッシュできるようになります。CLI にいつでも戻るには、コマンドラインから screen -r を使用します。使用可能な画面のリストを表示するには、screen -ls を使用します。

$ screen -ls
There is a screen on:
        74182.ttys000.mylinuxmachine        (Detached)
1 Socket in /tmp/uscreens/S-username.

FTD Joiner を設定する

上記の手順を繰り返して、既存の ot-cli-ftd.hex ビルドを使用して 3 つ目の nRF52840 ボードをフラッシュします。完了したら、nRF USB ポートを使用してボードを PC に再接続し、nRF 電源スイッチを VDD に設定します。

この 3 枚目のボードが接続されたときに他の 2 つのノードが Linux マシンに接続されている場合、シリアルポート /dev/ttyACM2 として表示されます。

$ ls /dev/ttyACM*
/dev/ttyACM0  /dev/ttyACM1  /dev/ttyACM2

ボードに「Joiner」というラベルを付けます。

Screen を使用して検証する場合は、コマンドラインから Screen の新しいインスタンスを作成する代わりに、既存のインスタンスに再アタッチして、その中に新しいウィンドウを作成します(FTD Commissioner に使用したウィンドウ)。

$ screen -r

Ctrl+a → c を使用して、Screen 内に新しいウィンドウを作成します。

新しいコマンドライン プロンプトが表示されます。FTD Joiner の OpenThread CLI にアクセスします。

$ screen /dev/ttyACM2

この新しいウィンドウで、キーボードの Return キーを数回押して、OpenThread CLI の > プロンプトを表示します。IPv6 インターフェースを起動してアドレスを確認します。

> ifconfig up
Done
> ipaddr
fe80:0:0:0:6c1e:87a2:df05:c240
Done

FTD Joiner CLI が FTD Commissioner と同じ Screen インスタンスにあるため、Ctrl+a → n を使用して切り替えることができます。

Ctrl+A を使用 →

d を押すと、いつでも Screen を終了できます。

6. ターミナル ウィンドウのセットアップ

今後、Thread デバイスを頻繁に切り替えることになるため、すべてのデバイスが有効で、簡単にアクセスできることを確認してください。これまで、Screen を使用して 2 つの FTD にアクセスしてきましたが、このツールでは同じターミナル ウィンドウで分割画面を使用することもできます。これを使用して、別のノードで発行されたコマンドに対する 1 つのノードの反応を確認します。

理想的には、次の 4 つのウィンドウをすぐに使用できるようにしておく必要があります。

  1. ot-daemon サービス / ログ
  2. ot-ctl 経由の RCP Joiner
  3. OpenThread CLI を介した FTD Commissioner
  4. OpenThread CLI を介した FTD Joiner

独自のターミナル / シリアルポート構成またはツールを使用する場合は、次のステップに進んでください。すべてのデバイスのターミナル ウィンドウを、最適な方法で構成します。

画面の使用

使いやすさを考慮して、Screen セッションは 1 つだけ開始します。両方の FTD を設定したときに、すでに 1 つ作成されているはずです。

Screen 内のすべてのコマンドは Ctrl+a で始まります。

基本的な Screen コマンド:

Screen セッションに再アタッチする(コマンドラインから)

screen -r

Screen セッションを終了する

Ctrl+a → d

Screen セッション内に新しいウィンドウを作成する

Ctrl+a → c

同じ画面セッション内のウィンドウを切り替える

Ctrl+a → n(進む)Ctrl+a → p(戻る)

Screen セッションで現在のウィンドウを終了する

Ctrl+a → k

分割スクリーン

Screen を使用すると、ターミナルを複数のウィンドウに分割できます。

f1cbf1258cf0a5a.png

screen のコマンドには、Ctrl+a を使用してアクセスします。すべてのコマンドはこのアクセスキーの組み合わせで始まる必要があります。

この Codelab の手順に厳密に従うと、同じ Screen インスタンスに 2 つのウィンドウ(FTD Commissioner、FTD Joiner)が表示されるはずです。2 つの画面を分割するには、まず既存の Screen セッションに入ります。

$ screen -r

FTD デバイスのいずれかに接続している必要があります。Screen で次の手順を行います。

  1. Ctrl+a → S: ウィンドウを水平方向に分割する
  2. Ctrl+a → Tab で、カーソルを新しい空白のウィンドウに移動します。
  3. Ctrl+a → n で、新しいウィンドウを次のウィンドウに切り替えます。
  4. 最上部のウィンドウと同じ場合は、Ctrl+a → n をもう一度押して、別の FTD デバイスを表示します。

両方とも表示されるようになりました。Ctrl+a → Tab を使用して切り替えます。混乱を避けるため、Ctrl+a → A で各ウィンドウのタイトルを変更することをおすすめします。

高度な授業・利用向け

画面をさらに 4 分割して ot-daemon ログと RCP Joiner ot-ctl を表示するには、これらのサービスを同じ Screen インスタンス内で開始する必要があります。これを行うには、ot-daemon を停止して ot-ctl を終了し、新しい Screen ウィンドウ内で再起動します(Ctrl+a → c)。

この設定は必須ではなく、ユーザーが演習として行うことになっています。

次のコマンドを使用して、ウィンドウを分割して移動します。

新しいウィンドウを作成

Ctrl+a → c

ウィンドウを縦に分割する

Ctrl+a →

ウィンドウを横に分割する

Ctrl+a → S

表示されている次のウィンドウに移動

Ctrl+a → Tab

表示されているウィンドウを前後に切り替える

Ctrl+a → n または p

現在のウィンドウの名前を変更する

Ctrl+a → A

Ctrl+a → d でいつでも Screen を終了し、コマンドラインから screen -r で再接続します。

Screen の詳細については、GNU Screen クイック リファレンスをご覧ください。

7. Thread ネットワークを作成する

これで、すべてのターミナル ウィンドウと画面が構成されたので、Thread ネットワークを作成しましょう。FTD Commissioner で、新しい運用データセットを作成し、アクティブなデータセットとしてコミットします。オペレーショナル データセットは、作成する Thread ネットワークの構成です。

## FTD Commissioner ##
----------------------

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 11
Channel Mask: 07fff800
Ext PAN ID: c0de7ab5c0de7ab5
Mesh Local Prefix: fdc0:de7a:b5c0/64
Network Key: 1234c0de7ab51234c0de7ab51234c0de
Network Name: OpenThread-c0de
PAN ID: 0xc0de
PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4
Security Policy: 0, onrcb
Done

後で使用するネットワーク キー 1234c0de7ab51234c0de7ab51234c0de をメモしておきます。

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

> dataset commit active
Done

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

> ifconfig up
Done

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

> thread start
Done

しばらくしてから、デバイスの状態を確認します。リーダーである必要があります。今後の参照用に RLOC16 も取得します。

## FTD Commissioner ##
----------------------

> state
leader
Done
> rloc16
0c00
Done

デバイスの IPv6 アドレスを確認します。

## FTD Commissioner ##
----------------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00        # Leader Anycast Locator (ALOC)
fdc0:de7a:b5c0:0:0:ff:fe00:c00         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:6394:5a75:a1ad:e5a    # Mesh-Local EID (ML-EID)
fe80:0:0:0:1cd6:87a9:cb9d:4b1d         # Link-Local Address (LLA)

他の Thread デバイスからスキャンすると、「codelab」ネットワークが表示されるようになりました。

RCP Joinerot-ctl から:

## RCP Joiner ##
----------------

> scan
| PAN  | MAC Address      | Ch | dBm | LQI |
+------+------------------+----+-----+-----+
| c0de | 1ed687a9cb9d4b1d | 11 | -36 | 232 |

FTD Joiner の OpenThread CLI から:

## FTD Joiner ##
----------------

> scan
| PAN  | MAC Address      | Ch | dBm | LQI |
+------+------------------+----+-----+-----+
| c0de | 1ed687a9cb9d4b1d | 11 | -38 | 229 |

「codelab」ネットワークがリストに表示されない場合は、もう一度スキャンしてみてください。

8. RCP Joiner を追加します。

Thread コミッショニングはネットワーク上でアクティブではありません。つまり、帯域外コミッショニング プロセスを使用して、作成したばかりの Thread ネットワークに RCP Joiner を追加する必要があります。

FTD Commissioner で、ネットワーク キー(例: 1234c0de7ab51234c0de7ab51234c0de)をメモしました。ネットワーク キーを再度検索する必要がある場合は、FTD Commissioner で次のコマンドを実行します。

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

次に、RCP Joiner で、アクティブなデータセットのネットワーク キーを FTD Commissioner のネットワーク キーに設定します。

## RCP Joiner ##
----------------

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

データセットが正しく設定されていることを確認します。

## RCP Joiner ##
----------------

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

Thread を起動して、RCP Joiner が「codelab」ネットワークに参加するようにします。数秒待ってから、状態、RLOC16、その IPv6 アドレスを確認します。

## RCP Joiner ##
----------------

> ifconfig up
Done
> thread start
Done
> state
child
Done
> rloc16
0c01
Done
> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:0c01         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f    # Mesh-Local EID (ML-EID)
fe80:0:0:0:18e5:29b3:a638:943b          # Link-Local Address (LLA)
Done

後で使用するため、メッシュローカル IPv6 アドレス(ここでは fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f)をメモしておきます。

FTD Commissioner に戻り、ルーター テーブルと子テーブルを確認して、両方のデバイスが同じネットワークに属していることを確認します。RLOC16 を使用して RCP Joiner を識別します。

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  35 | 1ed687a9cb9d4b1d |

Done
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|VER| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+------------------+
|   1 | 0x0c01 |        240 |         25 |     3 |   89 |1|1|1|  2| 1ae529b3a638943b |
Done

RCP Joiner のメッシュローカル アドレス(RCP Joiner の ipaddr 出力から取得したメッシュローカル アドレス)に ping を送信して、接続を確認します。

## FTD Commissioner ##
----------------------

> ping fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f
> 8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=1 hlim=64 time=40ms

これで、次のトポロジ図に示すように、2 つのノードで構成される Thread ネットワークができました。

otcodelab_top01C_2nodes.png

トポロジ図

この Codelab の残りの部分では、ネットワークの状態が変化するたびに新しい Thread トポロジ図を表示します。ノードロールは次のように表記されます。

b75a527be4563215.png

ルーターは常に五角形、エンドデバイスは常に円形です。各ノードの数字は、その時点での各ノードの現在のロールと状態に応じて、CLI 出力に表示されるルーター ID または子 ID を表します。

9. FTD Joiner をコミッショニングする

次に、3 つ目の Thread デバイスを「codelab」ネットワークに追加します。今回は、より安全なインバンド コミッショニング プロセスを使用し、FTD Joiner のみが参加できるようにします。

FTD Joinereui64 を取得し、FTD Commissioner が識別できるようにします。

## FTD Joiner ##
----------------

> eui64
2f57d222545271f1
Done

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

## FTD Commissioner ##
----------------------

> commissioner start
Done
> commissioner joiner add 2f57d222545271f1 J01NME
Done

FTD Joiner に切り替えます。FTD Commissioner で設定した Joiner Credential を使用して、Joiner ロールを開始します。

## FTD Joiner ##
----------------

> ifconfig up
Done
> joiner start J01NME
Done

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

## FTD Joiner ##
----------------

>
Join success

Thread を起動して FTD Joiner を「codelab」ネットワークに参加させ、すぐに状態と RLOC16 を確認します。

## FTD Joiner ##
----------------

> thread start
Done
> state
child
Done
> rloc16
0c02
Done

デバイスの IPv6 アドレスを確認します。ALOC がないことに注意してください。これは、このデバイスがリーダーではなく、ALOC を必要とするエニーキャスト固有のロールも保持していないためです。

## FTD Joiner ##
----------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:c02         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd    # Mesh-Local EID (ML-EID)
fe80:0:0:0:e4cd:d2d9:3249:a243         # Link-Local Address (LLA)

すぐに FTD Commissioner に切り替え、ルーター テーブルと子テーブルを確認して、「codelab」ネットワークに 3 つのデバイスが存在することを確認します。

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         25 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
|   2 | 0x0c02 |        240 |         15 |     3 |   44 |1|1|1|1| e6cdd2d93249a243 |
Done

RLOC16 に基づいて、FTD Joiner はエンドデバイス(子)としてネットワークに接続されています。更新されたトポロジは次のとおりです。

otcodelab_top01C_ed01.png

10. スレッドの動作

この Codelab の Thread デバイスは、ルーター対応エンドデバイス(REED)と呼ばれる特定の種類のフル Thread デバイス(FTD)です。つまり、ルーターまたはエンドデバイスとして機能し、エンドデバイスからルーターに昇格できます。

Thread は最大 32 個のルーターをサポートできますが、ルーターの数を 16 ~ 23 個に保つようにします。REED がエンドデバイス(子)として接続され、ルーターの数が 16 未満の場合、2 分以内のランダムな期間の後に、自動的にルーターに昇格します。

FTD Joiner を追加した後、Thread ネットワークにお子様が 2 人いる場合は、少なくとも 2 分待ってから、FTD Commissioner でルーターと子テーブルを再確認します。

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       63 |         0 |     3 |      3 |   1 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         61 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
Done

FTD Joiner(拡張 MAC = e6cdd2d93249a243)がルーターに昇格しました。RLOC16 が異なる(0c02 ではなく b800)ことに注意してください。これは、RLOC16 がデバイスのルーター ID と子 ID に基づいているためです。エンド デバイスからルーターに移行すると、ルーター ID と子 ID の値が変更され、RLOC16 も変更されます。

otcodelab_top01C.png

FTD Joiner で新しい状態と RLOC16 を確認します。

## FTD Joiner ##
----------------

> state
router
Done
> rloc16
b800
Done

FTD Joiner をダウングレードする

この動作をテストするには、ルーターからエンドデバイスに FTD Joiner を手動でダウングレードします。状態を child に変更し、RLOC16 を確認します。

## FTD Joiner ##
----------------

> state child
Done
> rloc16
0c03
Done

otcodelab_top01C_ed02.png

FTD Commissioner に戻ると、FTD Joiner が子テーブル(ID = 3)に表示されます。移行中は両方に存在する可能性もあります。

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       63 |         0 |     3 |      3 |   1 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         61 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
|   3 | 0x0c03 |        240 |         16 |     3 |   94 |1|1|1|1| e6cdd2d93249a243 |
Done

しばらくすると、RLOC が b800 のルーターに切り替わります。

otcodelab_top01C.png

リーダーを削除する

リーダーは、すべての Thread Router の中から自動的に選出されます。つまり、現在のリーダーが Thread ネットワークから削除されると、他のルーターのいずれかが新しいリーダーになります。

FTD Commissioner で、Thread をシャットダウンして Thread ネットワークから削除します。

## FTD Commissioner ##
----------------------

> thread stop
Done
> ifconfig down
Done

2 分以内に、FTD Joiner が新しい Thread リーダーになります。FTD Joiner の状態と IPv6 アドレスを確認して、次のことを確認します。

## FTD Joiner ##
----------------

> state
leader
Done
> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00       # Now it has the Leader ALOC!
fdc0:de7a:b5c0:0:0:ff:fe00:b800
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd
fe80:0:0:0:e4cd:d2d9:3249:a243
Done

otcodelab_top02C_01.png

子テーブルを確認します。新しい RLOC16 があることに注意してください。これは RCP Joiner であり、ID と拡張 MAC で示されています。Thread ネットワークを維持するために、親ルーターを FTD Commissioner から FTD Joiner に切り替えています。これにより、RCP Joiner の新しい RLOC16 が生成されます(ルーター ID が 3 から 46 に変更されたため)。

## FTD Joiner ##
----------------

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0xb801 |        240 |         27 |     3 |  145 |1|1|1|1| 1ae529b3a638943b |
Done

RCP Joiner が FTD Joiner に子として接続されるまで数分かかることがあります。状態と RLOC16 を確認して、次のことを確認します。

## RCP Joiner ##
--------------

> state
child
> rloc16
b801

FTD Commissioner を再接続する

2 つのノードがある Thread ネットワークはあまり面白くありません。FTD Commissioner をオンラインに戻しましょう。

FTD Commissioner で、Thread を再起動します。

## FTD Commissioner ##
----------------------

> ifconfig up
Done
> thread start
Done

2 分以内に、エンド デバイスとして「codelab」ネットワークに自動的に再接続し、ルーターに昇格します。

## FTD Commissioner ##
----------------------

> state
router
Done

FTD Joiner でルーターと子テーブルを確認して、次のことを確認します。

## FTD Joiner ##
----------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |       63 |         0 |     3 |      3 |   0 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       46 |         0 |     0 |      0 |  15 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0xb801 |        240 |        184 |     3 |  145 |1|1|1|1| 1ae529b3a638943b |
Done

otcodelab_top02C_02.png

Thread ネットワークは再び 3 つのノードで構成されています。

11. トラブルシューティング

異なる端末や画面ウィンドウで複数のデバイスを使用して Thread ネットワークを管理するのは複雑になる可能性があります。問題が発生した場合は、これらのヒントを参考にネットワークまたはワークスペースの状態を「リセット」してください。

画面

構成が複雑になった場合(Screen ウィンドウが多すぎる、Screen 内に Screen があるなど)、Ctrl+a → k を押して Screen ウィンドウをすべて削除し、コマンドラインで screen -ls を実行して No Sockets found が出力されるまで、Screen ウィンドウを削除し続けます。次に、デバイスごとに Screen ウィンドウを再作成します。Screen が強制終了されても、デバイスの状態は保持されます。

Thread ノード

Thread ネットワーク トポロジがこの Codelab で説明したとおりでない場合や、ノードが何らかの理由で切断された場合(ノードを駆動する Linux マシンがスリープ状態になったなど)、Thread を停止し、ネットワーク認証情報をクリアして、Thread ネットワークを作成するの手順からやり直すことをおすすめします。

FTD をリセットするには:

## FTD Commissioner or FTD Joiner ##
------------------------------------

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

RCP は ot-ctl を介して同じ方法でリセットできます。

## RCP Joiner ##
----------------

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

12. マルチキャストの使用

マルチキャストは、デバイスのグループに情報を一度に送信するために使用されます。Thread ネットワークでは、スコープに応じて、異なるデバイス グループでマルチキャストに使用する特定のアドレスが予約されています。

IPv6 アドレス

スコープ

配達先

ff02::1

リンクローカル

すべての FTD と MED

ff02::2

リンクローカル

すべての FTD とボーダー ルーター

ff03::1

Mesh-Local

すべての FTD と MED

ff03::2

Mesh-Local

すべての FTD とボーダー ルーター

この Codelab では Border Router を使用しないため、2 つの FTD と MED のマルチキャスト アドレスに焦点を当てます。

リンクローカル スコープは、単一の無線伝送または単一の「ホップ」で到達可能なすべての Thread インターフェースで構成されます。ネットワーク トポロジによって、ff02::1 マルチキャスト アドレスへの ping に応答するデバイスが決まります。

FTD Commissioner から ff02::1 に ping を送信します。

## FTD Commissioner ##
----------------------

> ping ff02::1
> 8 bytes from fe80:0:0:0:e4cd:d2d9:3249:a243: icmp_seq=2 hlim=64 time=9ms

ネットワークには他の 2 つのデバイス(FTD Joiner と RCP Joiner)がありますが、FTD Commissioner は FTD Joiner のリンクローカル アドレス(LLA)からの 1 つのレスポンスしか受信していません。つまり、FTD Commissioner がシングルホップで到達できるのは FTD Joiner だけです。

otcodelab_top02C_02_LL.png

次に、FTD Joiner から ff02::1 に ping を送信します。

## FTD Joiner ##
----------------

> ping ff02::1
> 8 bytes from fe80:0:0:0:1cd6:87a9:cb9d:4b1d: icmp_seq=1 hlim=64 time=11ms
8 bytes from fe80:0:0:0:18e5:29b3:a638:943b: icmp_seq=1 hlim=64 time=24ms

2 つの回答が届きました。他のデバイスの IPv6 アドレスを確認すると、最初のデバイス(4b1d で終わる)は FTD Commissioner の LLA で、2 番目のデバイス(943b で終わる)は RCP Joiner の LLA であることがわかります。

otcodelab_top02C_02_LL02.png

これは、FTD Joiner が FTD Commissioner と RCP Joiner の両方に直接接続されていることを意味し、トポロジが確認されます。

Mesh-Local

メッシュローカル スコープは、同じ Thread ネットワーク内で到達可能なすべての Thread インターフェースで構成されます。ff03::1 マルチキャスト アドレスへの ping のレスポンスを見てみましょう。

FTD Commissioner から ff03::1 に ping を送信します。

## FTD Commissioner ##
----------------------

> ping ff03::1
> 8 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:b800: icmp_seq=3 hlim=64 time=9ms
8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=3 hlim=64 time=68ms

今回は、FTD コミッショナーが 2 つのレスポンスを受信しました。1 つは FTD ジョイナーのルーティング ロケータ(RLOC、b800 で終わる)、もう 1 つは RCP ジョイナーのメッシュローカル EID(ML-EID、d55f で終わる)です。これは、メッシュローカル スコープが Thread ネットワーク全体を構成しているためです。ネットワーク内のデバイスがどこにあっても、ff03::1 アドレスに登録されます。

otcodelab_top02C_02_ML.png

FTD Joiner から ff03::1 に ping を送信して、同じ動作を確認します。

## FTD Joiner ##
----------------

> ping ff03::1
> 8 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:c00: icmp_seq=2 hlim=64 time=11ms
8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=2 hlim=64 time=23ms

otcodelab_top02C_02_LL02.png

両方の ping 出力で RCP Joiner の応答時間をメモします。RCP Joiner が FTD Commissioner に到達するのにかかった時間(68 ミリ秒)は、FTD Joiner に到達するのにかかった時間(23 ミリ秒)よりもはるかに長くなっています。これは、FTD Joiner の場合は 1 ホップで済むのに対し、FTD Commissioner に到達するには 2 ホップが必要になるためです。

また、メッシュローカル マルチキャスト ping は、RCP Joiner ではなく、2 つの FTD に対してのみ RLOC で応答したことにもお気づきかもしれません。これは、FTD がネットワーク内のルーターであるのに対し、RCP はエンドデバイスであるためです。

RCP Joiner の状態を確認して、次のことを確認します。

## RCP Joiner ##
----------------

> state
child

13. UDP でメッセージを送信する

OpenThread が提供するアプリケーション サービスの 1 つに、トランスポート レイヤ プロトコルである User Datagram Protocol(UDP)があります。OpenThread 上に構築されたアプリケーションは、UDP API を使用して、Thread ネットワーク内のノード間、または外部ネットワーク内の他のデバイス(Thread ネットワークにボーダー ルーターがある場合はインターネットなど)間でメッセージを渡すことができます。

UDP ソケットは OpenThread CLI を介して公開されます。これを使用して、2 つの FTD 間でメッセージを渡します。

FTD Joiner の Mesh-Local EID アドレスを取得します。このアドレスは、Thread ネットワーク内のどこからでも到達できるため使用されています。

## FTD Joiner ##
----------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00        # Leader Anycast Locator (ALOC)
fdc0:de7a:b5c0:0:0:ff:fe00:b800        # Routing Locator (RLOC)
fe80:0:0:0:e4cd:d2d9:3249:a243         # Link-Local Address (LLA)
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd    # Mesh-Local EID (ML-EID)
Done

UDP を起動し、任意の IPv6 アドレスのソケットにバインドします。

## FTD Joiner ##
----------------

> udp open
Done
> udp bind :: 1212

FTD Commissioner に切り替え、UDP を開始して、FTD Joiner で設定したソケットに ML-EID を使用して接続します。

## FTD Commissioner ##
----------------------

> udp open
Done
> udp connect fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd 1212
Done

UDP 接続は 2 つのノード間でライブである必要があります。FTD 担当者からのメッセージを送信します。

## FTD Commissioner ##
----------------------

> udp send hellothere
Done

FTD Joiner で UDP メッセージが受信されました。

## FTD Joiner ##
----------------

> 10 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:c00 49153 hellothere

14. 完了

これで、物理的な Thread ネットワークが作成されました。

b915c433e7027cc7.png

これで、次のことがわかりました。

  • Thread デバイスのタイプ、ロール、スコープの違い
  • Thread デバイスがネットワーク内で状態を管理する方法
  • UDP を使用してノード間で簡単なメッセージを渡す方法

次のステップ

この Codelab で学んだことを活かして、以下の演習に挑戦してみましょう。

  • ot-cli-mtd バイナリを使用して FTD Joiner ボードを MTD として再フラッシュし、ルーターにアップグレードしたり、リーダーになろうとしたりしないことを確認します。
  • ネットワークにデバイスを追加し(別のプラットフォームも試してください)、ルーターと子テーブル、マルチキャスト アドレスへの ping を使用してトポロジをスケッチします。
  • pyspinel を使用して NCP を制御する
  • OpenThread Border Router を使用して NCP をボーダー ルーターに変換し、Thread ネットワークをインターネットに接続する

関連情報

openthread.ioGitHub で、次のようなさまざまな OpenThread リソースをご確認ください。

関連資料: