nRF52840 ボードと OpenThread を使用して Thread ネットワークを構築する

1. はじめに

26b7f4f6b3ea0700.png

Google がリリースした OpenThread は、Thread® ネットワーキング プロトコルのオープンソース実装です。Google Nest は、Google Nest 製品で使用されている技術を広くデベロッパーに提供し、スマートホーム製品の開発を加速させるために、OpenThread をリリースしました。

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

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

4806d16a8c137c6d.jpeg

学習内容

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

必要なもの

ハードウェア:

  • Nordic Semiconductor nRF52840 開発ボード x 3
  • 3 つの USB - マイクロ USB ケーブル(ボードを接続する)
  • USB ポートが 3 つ以上ある Linux マシン

ソフトウェア:

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

2. 開始するには

OpenThread シミュレーション

始める前に、OpenThread Simulation Codelab を確認し、Thread の基本的なコンセプトと OpenThread CLI を理解しておくことをおすすめします。

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

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

Linux マシン

この Codelab は、i386 ベースまたは x86 ベースの Linux マシンを使用して、Radio Co-Processor(RCP)Thread デバイスのホストとして機能し、すべての Thread 開発ボードをフラッシュするように設計されています。すべての手順は Ubuntu 14.04.5 LTS(Trusty Tahr)でテストしました。

Nordic Semiconductor nRF52840 ボード

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

a6693da3ce213856.png

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

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

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

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

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

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

ビルドには ARM GNU ツールチェーンを使用します。

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

インストール画面(省略可)

画面は、シリアルポートで接続されたデバイスにアクセスするためのシンプルなツールです。この 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

これで、OpenThread をビルドして nRF52840 ボードに書き込む準備ができました。

4. RCP ジョイナーを設定する

ビルドしてフラッシュする

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 電源スイッチを 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 マシン)と通信する必要があります。

フラッシュした nRF52840 ボードのデバッグポートから USB ケーブルの Micro-USB 端子を取り外し、[RESET] ボタンの横にある Micro-USB nRF USB ポートに再度接続します。[nRF 電源] スイッチを [USB] に設定します。

46e7b670d2464842.png

OpenThread デーモンを開始

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

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

成功すると、詳細モードの 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 つのスレッドノードは、標準のシステム オン チップ(SoC)設計のフルスレッド デバイス(FTD)です。本番環境の設定では、本番環境グレードのネットワーク インターフェース ドライバである wpantund を使用して OpenThread NCP インスタンスを制御しますが、この Codelab では ot-ctl(OpenThread CLI)を使用します。

1 つのデバイスはコミッショナーとして機能し、そのネットワーク上でデバイスを安全に認証してコミッショニングします。もう 1 つのデバイスは、コミッショナーが Thread ネットワークに対して認証できるジョイナーとして機能します。

ビルドしてフラッシュする

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

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

OpenThread フルスレッド デバイス(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 をシリアル トランスポートとして使用できることから、RCP ホスト(Linux マシン)と通信するには、nRF52840 ボードの nRF USB ポートを使用する必要があります。

フラッシュした nRF52840 ボードのデバッグポートから USB ケーブルの Micro-USB 端子を取り外し、[RESET] ボタンの横にある Micro-USB nRF USB ポートに再度接続します。[nRF 電源] スイッチを [USB] に設定します。

46e7b670d2464842.png

ビルドを検証する

ターミナル ウィンドウから GNU Screen を使用して OpenThread CLI にアクセスし、ビルドが成功したことを確認します。nRF52840 ボードのボーレートは 115,200 です。

$ screen /dev/ttyACM1 115200

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

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

Ctrl+A → を使用する

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

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

FTD ジョイナーを設定する

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

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

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

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

Screen を使用して確認する場合は、コマンドラインから Screen の新しいインスタンスを作成する代わりに、FTD コミッショナーに使用した既存のインスタンスに再接続し、新しいウィンドウを作成します。

$ screen -r

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

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

$ screen /dev/ttyACM2 115200

新しいウィンドウで Enter キーを押すと、OpenThread CLI の > プロンプトが表示されます。IPv6 インターフェースを表示し、アドレスを確認します。

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

FTD Joiner CLI は FTD コミッショナーの画面と同じインスタンスに表示されるため、Ctrl+A → n を使用して切り替えられます。

Ctrl+A → を使用する

d をクリックすれば、いつでも画面を終了できます。

6. ターミナル ウィンドウの設定

今後、Thread デバイスは頻繁に切り替わるので、すべてのデバイスがライブでアクセスしやすいものにしてください。これまではスクリーンを使用して 2 つの FTD にアクセスしてきましたが、このツールでは、同じターミナル ウィンドウで画面を分割することもできます。これを使用して、あるノードが別のノードで発行されたコマンドにどう反応するかを確認します。

4 つのウィンドウをすぐに利用できる状態にすることをおすすめします。

  1. ot-daemon サービス / ログ
  2. RCP ジョイナーot-ctl 経由)
  3. FTD コミッショナー(OpenThread CLI を使用)
  4. FTD Joiner(OpenThread CLI を使用)

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

画面の使用

スクリーン セッションを 1 つだけ開始することをおすすめします。両方の FTD を設定するときにすでに用意されています。

画面内のすべてのコマンドは Ctrl+A で始まります。

基本画面コマンド:

(コマンドラインから)Screen セッションに再接続する

screen -r

スクリーン セッションを終了する

Ctrl+A → d

スクリーン セッション内に新しいウィンドウを作成する

Ctrl+A → c

同じスクリーン セッションでウィンドウを切り替える

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

スクリーン セッションの現在のウィンドウを強制終了する

Ctrl+A → k

分割スクリーン

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

f1cbf1258cf0a5a.png

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

Codelab を正確に実行している場合は、同じ Screen インスタンス上に 2 つのウィンドウ(FTD コミッショナー、FTD Joiner)が必要です。画面を 2 つに分けるには、まず既存の Screen セッションに入ります。

$ screen -r

いずれかの FTD デバイスを使用している。画面上の手順は以下のとおりです。

  1. Ctrl+A → Sウィンドウを水平方向に分割
  2. Ctrl+A → Tab 新しい空白ウィンドウにカーソルを移動
  3. Ctrl+A → n 新しいウィンドウに切り替える
  4. トップ ウィンドウと同じ場合は、Ctrl+A → n を再度押すと、他の FTD デバイスが表示されます

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

上級者向け

画面をさらにクワドラントに分割して ot-daemon ログと RCP Joiner ot-ctl を表示するには、これらのサービスを同じ Screen インスタンス内で起動する必要があります。そのためには、ot-daemon を停止して ot-ctl を終了し、新しい画面ウィンドウ内で再起動します(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 -r で再接続できます。

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

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

ターミナル ウィンドウと画面をすべて構成したので、Thread ネットワークを作成しましょう。FTD コミッショナーで、新しい運用データセットを作成し、それを有効なデータセットとして commit します。オペレーショナル データセットは、作成する 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 をメモします。

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

> 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 ジョイナーを追加する

ネットワークでコミッショニング サービスがアクティブでない。つまり、帯域外コミッショニング プロセスを使用して作成した Thread ネットワークに RCP ジョイナーを追加する必要があります。

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

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

次に、RCP Joiner で、有効なデータセットのネットワーク キーを FTD コミッショナー ネットワーク キーに設定します。

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

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

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

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

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

RCP Joiner が Codelab ネットワークに接続するように Thread を起動します。数秒待ってから、状態、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 コミッショナーに戻り、ルーターと子テーブルを確認して、両方のデバイスが同じネットワークの一部であることを確認します。RLOC16 を使用して RCP ジョイナーを識別します。

## 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 ジョイナーにコミッション

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

FTD Joinereui64 を取得して、FTD コミッショナーが識別できるようにします。

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

> eui64
2f57d222545271f1
Done

FTD コミッショナーで、コミッショナーを起動し、参加できるデバイスの eui64 と、Joiner の認証情報(J01NME など)を指定します。ジョイナー認証情報は 6 ~ 32 文字のデバイス固有の文字列(大文字の英数字(0 ~ 9 と A ~ Y、読みやすいように I、O、Q、Z を除く))です。

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

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

FTD Joiner に切り替えます。FTD コミッショナーに設定したジョイナー認証情報を使用して、ジョイナーのロールを開始します。

## 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 コミッショナーに切り替え、Router と子テーブルを確認して、「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 ジョイナーはエンドデバイス(子)としてネットワークに接続しています。最新のトポロジは次のとおりです。

otcodelab_top01C_ed01.png

10. スレッドの動作

この Codelab の Thread デバイスは、Router Eligible End Device(REED)と呼ばれる特定の種類の Full Thread Device(FTD)です。つまり、お客様は Router またはエンドデバイスのいずれかとして機能し、エンドデバイスから Router に昇格させることができます。

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

FTD Joiner を追加した後に Thread ネットワークに 2 つの子がある場合は、2 分以上待ってから、FTD コミッショナーでルーターと子テーブルを再度確認します。

## 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 ジョイナー(拡張 MAC = e6cdd2d93249a243)が Router に昇格しました。RLOC16 は(0c02 ではなく b800)異なることに注意してください。これは、RLOC16 がデバイスのルーター ID と子 ID に基づくためです。終了デバイスから Router に移行すると、Router ID と Child ID の値が変わり、RLOC16 も変更されます。

otcodelab_top01C.png

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

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

> state
router
Done
> rloc16
b800
Done

FTD ジョイナーをダウングレードする

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

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

> state child
Done
> rloc16
0c03
Done

otcodelab_top01C_ed02.png

FTD コミッショナーに戻ると、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 の Router に戻ります。

otcodelab_top01C.png

リーダーを削除

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

FTD コミッショナーで、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 があることに注意してください。これは、ID と拡張 MAC によって示される RCP Joiner です。Thread ネットワークをつなぎ合わせるため、親 Router を FTD コミッショナーから FTD Joiner に切り替えました。これにより、RCP ジョイナーの新しい 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 コミッショナーを再接続する

2 つのノードを持つ Thread ネットワークはそれほど楽しくありません。FTD コミッショナーをオンラインに戻しましょう。

FTD コミッショナーで Thread を再起動します。

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

> ifconfig up
Done
> thread start
Done

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

## 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 ネットワークを管理するのは複雑な場合があります。問題が発生した場合は、これらのヒントを参考にしてネットワークやワークスペースの状態を「リセット」してください。

画面

構成の見落とし(画面ウィンドウが多すぎる、または画面内の画面)が見つからなくなった場合は、Ctrl+a → k キーでなくなるまで画面ウィンドウを強制終了し、コマンドラインの screen -lsNo Sockets found を出力してください。次に、デバイスごとにスクリーン ウィンドウを再作成します。画面が強制終了されてもデバイスの状態は保持されます。

スレッドノード

Thread ネットワーク トポロジがこの Codelab の説明と異なる場合、またはなんらかの理由でノードが切断される場合は(Linux マシンがスリープ状態になったなどの理由で)、Threads を停止し、ネットワーク認証情報を消去してから、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

メッシュ ローカル

すべての FTD と MED

ff03::2

メッシュ ローカル

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

この Codelab ではボーダー ルーターを使用しないため、2 つの FTD および MED マルチキャスト アドレスに注目します。

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

FTD コミッショナーから 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 コミッショナーは FTD Joiner のリンクローカル アドレス(LLA)から 1 つの回答しか受けていません。つまり、FTD のコミッショナーが 1 回のホップでアクセスできる唯一のデバイスです。

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 コミッショナーの LLA、2 番目のアドレス(943b で終わるもの)が RCP Joiner の LLA です。

otcodelab_top02C_02_LL02.png

つまり、FTD ジョイナーは FTD コミッショナーと RCP ジョイナーの両方に直接接続されます。これにより、トポロジが確認されます。

メッシュ ローカル

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

FTD コミッショナーから 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 コミッショナーに、FTD Joiner のルーティング ロケーター(RLOC、末尾が b800)と RCP Joiner の Mesh-Local EID(ML-EID、末尾が d55f)の 2 つのレスポンスがありました。これは、メッシュのローカル スコープが 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 ジョイナーの応答時間をメモします。RT ジョイナーは FTD コミッショナーに届くまでの時間(68 ミリ秒)よりはるかに長い(23 ミリ秒)これは、FTD コミッショナーへのホップが 1 回かかるのに対し、FTD コミッショナーに到達するには 2 回ホップする必要があるからです。

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

RCP Joiner の状態を確認して、以下の点を確認します。

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

> state
child

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

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

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

FTD Joiner のメッシュローカル 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 コミッショナーに切り替えて UDP を起動し、ML-EID を使用して FTD Joiner で設定したソケットに接続します。

## 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 で学んだことを活かして、以下の演習に挑戦しましょう。

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

関連情報

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

関連資料: