使用 nRF52840 板和 OpenThread 建構 Thread 網路

1. 簡介

26b7f4f6b3ea0700.png

Google 發布的 OpenThreadThread® 網路通訊協定的開放原始碼實作項目。Google Nest 已推出 OpenThread,讓開發人員能夠更廣泛地運用 Nest 產品所用的技術,加速為智慧聯網家庭開發產品。

Thread 規格定義了用於家用應用程式的 IPv6 穩定、安全和低功率無線裝置對通訊通訊協定。OpenThread 實作所有 Thread 網路層,包括 IPv6、6LoWPAN、IEEE 802.15.4 以及 MAC 安全性、網格連結建立和網格轉送。

在本程式碼研究室中,您將在實際的硬體上編寫 OpenThread、建立及管理 Thread 網路,以及在節點之間傳遞訊息。

4806d16a8c137c6d.jpeg

課程內容

  • 建構 OpenThread CLI 二進位檔並儲存至開發板
  • 建構包括 Linux 機器和開發板的 RCP
  • 使用 OpenThread Daemon 和 RCP 與 ot-ctl 進行通訊
  • 使用 GNU 螢幕和 OpenThread CLI 手動管理 Thread 節點
  • 將裝置安全地發布至 Thread 網路
  • IPv6 多播的運作方式
  • 使用 UDP 在 Thread 節點之間傳送訊息

軟硬體需求

硬體:

  • 3 Nordic Semiconductor nRF52840 開發人員專區
  • 3 條 USB 轉 micro-USB 傳輸線
  • 具備至少 3 個 USB 連接埠的 Linux 機器

軟體業:

  • GNU 工具鍊
  • Nordic nRF5x 指令列工具
  • Segger J-Link 軟體
  • OpenThread
  • Git

2. 開始使用

OpenThread 模擬

在開始之前,建議您先熟悉 OpenThread 模擬程式碼研究室,瞭解 Thread 的基本概念和 OpenThread CLI。

序列埠終端機

您應該熟悉如何透過終端機連線至序列埠。本程式碼研究室使用 GNU 螢幕並提供使用總覽,但您可使用其他終端機軟體。

Linux 機器

本程式碼研究室的設計宗旨是使用 i386 或 x86 的 Linux 機器,來當做 Radio Co-Processor (RCP) Thread 主機的主機,並重新整理所有 Thread 開發板。所有步驟均在 Ubuntu 14.04.5 LTS (Trusty Tahr) 上完成測試。

北歐半導體 nRF52840 白板

本程式碼研究室使用三個 nRF52840 PDK 主機

a6693da3ce213856.png

我們使用 SEGGER J-Link 來並加入 JTAG 模組。在 Linux 電腦上安裝這個套件。

為您的電腦下載適當的套件,並在適當位置安裝。在 Linux 上則為 /opt/SEGGER/JLink

安裝 nRF5x 指令列工具

nRF5x 指令列工具可讓您將 OpenThread 二進位檔刷新至 nRF52840 白板。在 Linux 電腦上安裝適當的 nRF5x-Command-Line-Tools-<OS> 版本。

將擷取的套件放入根資料夾 ~/

安裝 ARM GNU Toolchain

ARM GNU 工具鍊用於建構。

建議你將擷取的封存檔案放在 Linux 電腦的 /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/ 中。請按照封存檔案的 readme.txt 檔案的說明操作。

安裝畫面 (選用)

螢幕是一項簡單的工具,可讓您存取序列埠連線的裝置。本程式碼研究室使用螢幕,但您可以使用任何序列埠終端機應用程式。

$ 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 Daemon:

$ script/cmake-build posix -DOT_DAEMON=ON

現在,您已經可以建構 OpenThread 並推送至 nRF52840 白板。

4. 設定 RCP 彙整器

建構和快閃

使用 Shareder 和原生 USB 功能建構 OpenThread nRF52840 範例。裝置會使用「JOIN」角色以安全驗證並轉換至 Thread 網路。原生 USB 可使用 USB CDC ACM 做為 nRF52840 和主機之間的序列傳輸。

務必先執行 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 二進位檔的目錄,並將其轉換為十六進位格式:

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

將 USB 傳輸線接上 nRF52840 白板外部電源接頭旁的 Micro-USB 偵錯連接埠,然後插入 Linux 機器。將 nRF52840 白板的「nRF 電源來源」開關設為「VDD」。正確連線後,LED5 已開啟。

20a3b4b480356447.png

如果這是與 Linux 機器共用的第一個面板,就會顯示為序列埠 /dev/ttyACM0 (所有 nRF52840 主機都會使用 ttyACM 做為序列埠 ID)。

$ ls /dev/ttyACM*
/dev/ttyACM0

請注意,RCP 使用的 nRF52840 主機序號:

c00d519ebec7e5f0.jpeg

前往 nRFx 指令列工具的位置,並使用 Jamboard 的序號,將 OpenThread RCP 十六進位檔案刷至 nRF52840 白板。請注意,如果離開 --verify 旗標,系統會顯示警告訊息,說明 Flash 程序可能會發生錯誤而失敗。

$ 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 連接埠,然後將傳輸線重新插入「MiSET」按鈕旁邊的 Micro-USB nRF USB 連接埠。將「nRF 電源來源」開關切換至「USB」

46e7b670d2464842.png

開啟 OpenThread Daemon

在 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=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 節點。

在第二個終端機視窗中,啟動 ot-ctl

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

檢查您用 ot-daemon 啟動的節點 2 (RCP 節點) state

> state
disabled
Done

5. 設定 FTD

這個程式碼研究室使用的兩個 Thread 節點還屬於標準系統晶片 (SoC) 設計的全執行緒裝置 (FTD)。在「正式版」設定中,使用者可能會使用 wpantund (實際工作環境等級的網路介面驅動程式) 控管 OpenThread NCP 執行個體,但在本程式碼研究室中,我們將使用 ot-ctl:OpenThread CLI。

一部裝置是委託人員,負責確保裝置安全地通過網路註冊程序。其他裝置可以作為彙整器,讓委員會能夠驗證 Thread 網路。

建構和快閃

為 nRF52840 平台建立 OpenThread FTD 範例,並啟用 Commissioner 和 JOINer 角色:

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

前往使用 Thread Open Full Thread Device (FTD) CLI 二進位檔的目錄,並將其轉換為十六進位格式:

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

將 USB 傳輸線接上 nRF52840 白板外部電源接頭旁的 Micro-USB 連接埠,然後插入 Linux 機器。如果 RCP 仍連接至 Linux 電腦,這個新的 Jamboard 應該會顯示為序列埠 /dev/ttyACM1 (所有 nRF52840 主機板都會使用 ttyACM 做為序列埠 ID)。

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

和先前一樣,請注意 FTD 使用的 nRF52840 序號:

c00d519ebec7e5f0.jpeg

前往 nRFx 指令列工具的位置,並使用 Jamboard 的序號,將 OpenThread CLI FTD 十六進位檔案閃爍至 nRF52840 白板:

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

將白板標示為「佣金」。

連線至原生 USB

由於 OpenThread FTD 版本允許使用原生 USB CDC ACM 做為序列傳輸,因此您必須使用 nRF52840 主機的 nRF USB 連接埠與 RCP 主機 (Linux 機器) 進行通訊。

從刷新的 nRF52840 白板的偵錯通訊埠卸離 USB 傳輸線的 Micro-USB 連接埠,然後將傳輸線重新插入「MiSET」按鈕旁邊的 Micro-USB nRF USB 連接埠。將「nRF 電源來源」開關切換至「USB」

46e7b670d2464842.png

驗證版本

在終端機視窗中使用 GNU 螢幕存取 OpenThread CLI,即可驗證建構作業是否成功。nRF52840 主機的跳出率為 115200。

$ screen /dev/ttyACM1 115200

在新視窗中按下鍵盤上的返回鍵,開啟 OpenThread CLI > 提示。開啟 IPv6 介面並檢查位址:

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

使用 Ctrl + A →

d 從 FTD 佣金 C 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 版本,重複上述程序以刷出第三個 nRF52840 白板。完成後,請務必使用 nRF USB 連接埠將主機板重新連接電腦,並將 nRF 電源來源開關設為 VDD

如果連接了其他 Dboard 的兩個節點,連接至 Linux 機器,則應顯示為序列埠 /dev/ttyACM2

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

將白板標示為「加入會議」。

使用螢幕驗證時,請勿透過指令列建立新的螢幕執行個體,而是重新附加至現有的執行個體,並在該視窗中建立新的視窗 (用於 FTD 執行人員):

$ screen -r

使用 Ctrl + a → 在畫面中開啟新視窗 → c

系統會顯示新的指令列提示。存取 FTD 彙整器的 OpenThread CLI:

$ screen /dev/ttyACM2 115200

在新視窗中點選鍵盤上的「Return」鍵,藉此開啟 OpenThread CLI > 提示。開啟 IPv6 介面並檢查位址:

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

現在 FTD 彙整器 CLI 和 FTD 執行人員相同,現在可以使用 Ctrl+a → n 來切換。

使用 Ctrl + A →

d 即可隨時退出畫面。

6. 終端機視窗設定

日後,你將經常在 Thread 裝置間切換,所以請確認這些裝置都處於直播狀態,而且易於存取。到目前為止,我們一直使用螢幕存取兩個 FTD,且這項工具也允許在同一終端機視窗中分割畫面。使用此功能可瞭解一個節點如何回應透過其他節點發出的指令。

理想情況下,您應該有四個可用的視窗:

  1. ot-daemon 服務 / 記錄檔
  2. RCP 彙整者 (透過 ot-ctl)
  3. 透過 OpenThread CLI 建立 FTD 執行者
  4. 透過 OpenThread CLI 進行 FTD 彙整工具

如要使用自己的終端機 / 序列埠設定或工具,請跳到下一個步驟。以最適合自己的方式設定所有裝置的終端機視窗。

使用螢幕

為了方便起見,只要啟動一個畫面工作階段即可。設定兩種 FTD 時,您應該已經擁有。

螢幕畫面中的所有指令都是以 Ctrl+a 鍵開始。

基本螢幕指令:

透過指令列重新附加至螢幕工作階段

screen -r

離開螢幕工作階段

Ctrl + A → d

在螢幕工作階段中建立新視窗

Ctrl + A → c

在同一個螢幕工作階段中切換視窗

Ctrl + a → n (前進) Ctrl+a → p (返回)

在畫面工作階段中關閉目前的視窗

Ctrl + A → k

分割畫面

您可以使用螢幕將終端機分割為多個視窗:

f1cbf1258cf0a5a.png

按下 Ctrl+a 鍵可存取 screen 中的指令。每個指令開頭都應該是這個存取金鑰組合。

如果你已確實按照程式碼研究室的說明操作,相同畫面執行個體應該會顯示兩個視窗 (FTD 執行人員、FTD 彙整工具)。如要將畫面分成兩個畫面,請先進入現有的「螢幕」工作階段:

$ 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 彙整器 ot-ctl,這些服務必須在同一個螢幕執行個體中啟動。方法是停止 ot-daemon 並退出 ot-ctl,然後在新的「畫面」視窗中重新啟動 (Ctrl+a → c)。

使用者無須進行這項設定,因此可留待運動。

使用下列指令分割及瀏覽視窗:

開啟新視窗

Ctrl + A → c

垂直分割視窗

Ctrl + A →

水平分割視窗

Ctrl + A → S

跳到下一個顯示的視窗

Ctrl + A → Tab

將顯示的視窗向前或後移

Ctrl + A → np

將目前的視窗重新命名

Ctrl + A → A

你隨時可以按下 Ctrl + A 鍵 → d,然後使用指令列重新附加 screen -r

如要進一步瞭解螢幕畫面,請參閱 GNU 螢幕快速參考指引

7. 建立 Thread 網路

您已設定所有終端機視窗和螢幕,讓我們建立 Thread 網路。在 FTD 委員會上建立新的作業資料集,然後將其提交為使用中的資料集。作業資料集為您建立的 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 彙整工具ot-ctl

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

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

透過 FTD 彙整器的 OpenThread CLI:

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

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

如果在清單中找不到「Codelab」網路,請嘗試重新掃描。

8. 新增 RCP 彙整器

網路交集功能並未啟用,也就是說,我們必須將 RCP 彙整工具新增至我們透過頻外傳輸佣金剛建立的 Thread 網路。

我們在 FTD 委員會 (網路金鑰) 記下了網路金鑰,例如 1234c0de7ab51234c0de7ab51234c0de。如果需要再次查詢網路金鑰,請在 FTD 委員會執行下列指令:

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

接著,在 RCP 彙整者上,將執行中的資料集網路金鑰設為 FTD 佣金網路金鑰:

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

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

請檢查資料集,確認設定正確無誤。

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

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

啟動 Thread,讓 RCP 彙整器加入「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 委員會,檢查路由器和子項表格,確認兩個裝置都屬於同一個網路。使用 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 彙整器的網格本機位址 (從 RCP 彙整工具的 ipaddr 輸出取得的網格位址),藉此驗證連線能力:

## 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

我們現在擁有包含兩個節點的 Thread 網路,如這張拓撲圖所示:

otcodelab_top01C_2nodes.png

拓撲圖

在程式碼研究室的其餘部分中,只要網路狀態有所變更,我們就會顯示新的執行緒拓撲圖表。節點角色如下:

b75a527be4563215.png

路由器一律為五十年,而終端裝置一律為圓形。每個節點上的數字代表了 CLI 輸出內容中顯示的路由器 ID 或子項 ID,視每個節點目前的角色和狀態而定。

9. 獲得 FTD 彙整者

現在,讓我們將第三個 Thread 裝置加入「Codelab」網路。這次,我們會採用更安全的頻段佣金協定,並只允許 FTD 彙整工具加入。

在「FTD 彙整器」上取得 eui64,讓 FTD 執行人員能夠識別:

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

> eui64
2f57d222545271f1
Done

FTD 委員會上啟動佣金器,並指定可加入裝置的 eui64 以及聯合憑證,例如 J01NME。JOIN Credential 是裝置專屬字串,所有大寫英數字元 (0-9 和 A-Y,不包括 I、O、Q 和 Z),且長度必須介於 6 至 32 個字元之間。

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

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

切換至 FTD 彙整器。使用剛在 FTD 委員會上設定的「JOINer Credential」角色開始加入計畫:

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

> ifconfig up
Done
> joiner start J01NME
Done

您會在一分鐘內收到驗證成功的確認通知:

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

>
Join success

啟動 Thread,讓 FTD 彙整成為「Codelab」網路,並立即檢查狀態和 RLOC16:

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

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

請檢查裝置的 IPv6 位址。請注意,沒有 ALOC。這是因為此裝置並非領導者,也不是任何需要 ALOC 的 Anycast 專屬角色。

## 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 委員會,檢查路由器和子項表格,確認「程式碼研究室」網路中是否包含三個裝置:

## 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. 執行緒實際使用

這個程式碼研究室的 Thread 裝置是一種稱為「符合資格的路由器」(REED) 的完整執行緒裝置 (FTD)。這代表他們能夠做為路由器或裝置使用,也可從端對端裝置升級為路由器。

Thread 最多可支援 32 個路由器,但嘗試將路由器數量維持在 16 至 23 個之間。如果 REED 是做為結束裝置 (子項) 連接,且路由器數量低於 16 個,則經過 2 分鐘的隨機時間範圍後,系統就會自動將本身升級為路由器。

如果在 FTD 彙整器中新增 Thread 中的兩個子項後,請等待至少兩分鐘,然後再次檢查 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) 已自行升級至路由器。請注意,RLOC16 並不相同 (b800 而非 0c02)。這是因為 RLOC16 是根據裝置的路由器 ID 和子項 ID 建立。從最終裝置改用路由器時,路由器 ID 和子項 ID 的值都會變更,因此 RLOC16 也會改變。

otcodelab_top01C.png

FTD 彙整器確認新狀態和 RLOC16:

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

> state
router
Done
> rloc16
b800
Done

降級 FTD 彙整器

您可以手動將 FTD 彙整器從路由器降級至端對端裝置,藉此測試這個行為。將狀態變更為子項並查看 RLOC16:

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

> state child
Done
> rloc16
0c03
Done

otcodelab_top01C_ed02.png

返回 FTD 執行人員之後,FTD 彙整器應該會顯示在子項表格中 (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 路由器上都受到影響。也就是說,如果目前的執行緒從 Thread 網路中移除後,另一個路由器會成為新的領導者。

FTD 委員會上,關閉執行緒即可將其從 Thread 網路中移除:

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

> thread stop
Done
> ifconfig down
Done

FTD 彙整器會在兩分鐘內成為新的執行緒領導者。檢查 FTD 彙整器的狀態和 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 彙整器,如「ID 和延伸 MAC」所表示。為了保持 Thread 網路運作,已將父項路由器從 FTD 委員會切換為 FTD 彙整器。這會導致 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

您可能必須稍候幾分鐘,讓 FCP 彙整器以子項的形式附加至 FTD 合併器。請檢查狀態和 RLOC16 以確認下列事項:

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

> state
child
> rloc16
b801

重新附加 FTD 佣金

含有兩個節點的 Thread 網路並不有趣。讓我們將 FTD 委員會重新上線。

在「FTD Commissioner」中重新啟動執行緒:

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

> ifconfig up
Done
> thread start
Done

系統會在兩分鐘內自動重新連接至「Codelab」網路做為結束裝置,然後將其升級為路由器。

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

> state
router
Done

請檢查 FTD 彙整器中的路由器和子項資料表,以確認以下項目:

## 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 網路再次包含三個節點。

11. 疑難排解

管理含有不同裝置不同終端機或螢幕視窗的 Thread 網路可能並不容易。如果遇到問題,請使用以下提示「重設」網路狀態或工作區。

螢幕

如果您遇到設定中遺失的問題 (或是許多畫面視窗或畫面中的「畫面」),請持續使用 Ctrl+a → k 鍵來終止螢幕視窗,直到指令列中沒有名稱,screen -ls 輸出輸出內容時 No Sockets found。然後重新建立每部裝置的螢幕視窗。即使裝置終止,系統仍會保留裝置狀態。

執行緒節點

如果這個程式碼研究室未說明 Thread 網路拓撲,或者節點因故中斷 (可能原因可能是 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

網格網格

所有 FTD 和 MED

ff03::2

網格網格

所有 FTD 和邊界路由器

由於我們並不會在本程式碼研究室中使用邊界路由器,因此會將重點放在兩個 FTD 和 MED 多傳播位址。

Link-Local 範圍包含可透過單一無線電傳輸功能,或是單一「躍點」存取的所有 Thread 介面。網路拓撲會決定哪些裝置會回應 ff02::1 多播位址。

FTD 委員會連線偵測 ff02::1

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

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

網路中還有兩部其他裝置 (FTD JOIN 連線和 RCP 彙整器),但 FTD 委員會只收到一個回應,其來源為 FTD 聯盟的連結位址 (LLA)。因此 FTD 彙整工具是唯一可以在單一躍點上觸及的裝置。

otcodelab_top02C_02_LL.png

現在,從 FTD 彙整工具中呼叫 ff02::1

## 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

有兩個回應!檢查其他裝置的 IPv6 位址時,可以看到第一個位址 (結尾為 4b1d) 是 FTD 執行人員的 LLA,而第二個位址 (結尾為 943b) 是 RCP 聯合員工的 LLA。

otcodelab_top02C_02_LL02.png

這表示 FTD 總結人員同時與 FTD 委員會和 RCP 聯合成員聯繫,證實我們的拓撲。

網格網格

網狀連線範圍涵蓋同一個 Thread 網路中所有可連線的 Thread 介面。我們可以看到對 ff03::1 多播位址的連線偵測 (ping) 的回應。

FTD 委員會連線偵測 ff03::1

## 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 寄接器的定位器 (RLOC,結尾為 b800) 和 RCPJOINer's Tier-Local EID (ML-EID),結尾為 d55f。這是因為網狀網路範圍由整個執行緒網路組成。無論裝置在哪個網路中,系統都會訂閱 ff03::1 位址。

otcodelab_top02C_02_ML.png

FTD 彙整器連線偵測 ff03::1,確認相同的行為:

## 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 彙整回應回應時間。因為 FTD 成員 (68 毫秒) 的 RCP 彙整程序比 FTD 彙整更久 (23 毫秒),這是因為相較於 FTD 彙整器的 FTD 連線,必須分別進行兩項躍點。

您可能也會注意到,網格的多點多點連線偵測 (ping) 會透過 RLOC 針對兩個 FTD 做出回應,而不是 RCP 彙整。這是因為 FTD 是網路內的路由器,RCP 則是終端裝置。

檢查 RCP 彙整器的狀態,確認以下事項:

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

> state
child

13. 透過 UDP 傳送訊息

OpenThread 提供的一種應用程式服務是 Usergramgram Protocol (UDP),也就是傳輸層通訊協定。在 OpenThread 上建構的應用程式可以使用 UDP API,在 Thread 網路中的節點或外部網路中的其他裝置 (例如網際網路皆有邊界路由器) 之間傳送訊息。

UDP 通訊端是透過 OpenThread CLI 公開。讓我們使用 FTD 傳遞訊息。

取得 FTD 彙整者的網格-本機 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,並使用 MLF 聯合網路套件的 ML-EID 連線至您設定的通訊端 (FTD)。

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

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

UDP 連線應在兩個節點之間運作。從 FTD 委員會傳送訊息:

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

> udp send hellothere
Done

FTD 彙整器已收到 UDP 訊息!

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

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

14. 恭喜!

你已建立實體 Thread 網路!

b915c433e7027cc7.png

你現在知道:

  • Thread 裝置類型、角色和範圍之間的差異
  • Thread 裝置如何在網路中管理狀態
  • 如何使用 UDP 在節點之間傳遞簡單的訊息

後續步驟

以本程式碼研究室為基礎,嘗試使用以下練習:

  • 使用 ot-cli-mtd 二進位檔,將 FTD 彙整板重新刷新為 MTD
  • 將更多裝置 (可改用其他平台!) 新增至網路,然後使用路由器和子項資料表,搭配連線偵測 (ping) 多個位址,即可勾勒拓撲
  • 使用 pyspinel 來控制 NCP
  • 使用 OpenThread 邊界路由器將 NCP 轉換為邊界路由器,並將 Thread 網路連線至網際網路

其他資訊

請參考 openthread.ioGitHub,瞭解各種 OpenThread 資源,包括:

參考資料: