使用 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 和 ot-ctl 與 RCP 通訊
  • 使用 GNU 畫面和 OpenThread CLI 手動管理 Thread 節點
  • 安全調控裝置到 Thread 網路
  • IPv6 多點傳送的運作方式
  • 使用 UDP 在 Thread 節點之間傳遞訊息

軟硬體需求

硬體:

  • 3 北歐半導體 nRF52840 開發板
  • 使用 3 條 USB 轉 Micro-USB 傳輸線連接鍵盤
  • 擁有至少 3 個 USB 連接埠的 Linux 電腦

軟體:

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

2. 開始使用

OpenThread 模擬

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

序列埠終端

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

Linux 機器

本程式碼研究室是設計為使用 i386 或 x86 型 Linux 電腦做為無線電合作處理器 (RCP) Thread 裝置的主機,並且刷新所有 Thread 開發板。所有步驟皆已在 Ubuntu 14.04.5 LTS (Trusty Tahr) 上測試。

北歐半導體 nRF52840 主機

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

a6693da3ce213856.png

我們使用 SEGGER J-Link 來編寫具有 JTAG 模組的 nRF52840 主機板。請在 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 檔案中的操作說明安裝操作說明。

安裝畫面 (選用)

螢幕是一項簡單的工具,用於存取透過序列埠連線的裝置。本程式碼研究室會使用 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 Daemon:

$ script/cmake-build posix -DOT_DAEMON=ON

您現在可以建構 OpenThread,將 OpenThread 刷新到 nRF52840 主機板。

4. 設定 RCP 彙整器

建構及刷新

建構具備彙整器和原生 USB 功能的 OpenThread nRF52840 範例。裝置會使用「彙整者」角色,安全地在 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 指令列工具的位置,使用主機板序號將 OpenThread RCP 十六進位檔案刷新到 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 傳輸線的 Micro-USB 端從閃爍的 nRF52840 電路板的偵錯連接埠中卸除,然後將 USB 傳輸線重新插入「重設」按鈕旁邊的 micro-USB nRF USB 連接埠。將「nRF 電源」開關設為「USB」

46e7b670d2464842.png

啟動 OpenThread Daemon

在 RCP 設計中,使用 OpenThread Daemon 與 Thread 裝置進行通訊及管理 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) 設計的 Full Thread 裝置 (FTD)。在實際工作環境中,您可以使用 wpantund 這個正式環境等級的網路介面驅動程式來控制 OpenThread NCP 執行個體。但在本程式碼研究室中,我們會使用 OpenThread CLI ot-ctl

其中一項裝置會作為執行委員會,安全地驗證裝置並透過該網路執行佣金。另一部裝置會做為彙整器使用,方便委員會向 Thread 網路進行驗證。

建構及刷新

建立 nRF52840 平台的 OpenThread FTD 範例,同時啟用「Commissioner」和「Joiner」角色:

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

前往含有 OpenThread 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 電腦連接,這個新主機板應顯示為序列埠 /dev/ttyACM1 (所有 nRF52840 主機板,均使用 ttyACM 做為序列埠 ID)。

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

和先前一樣,記下 FTD 使用的 nRF52840 主機板序號:

c00d519ebec7e5f0.jpeg

前往 nRFx 指令列工具的位置,使用主機板序號將 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 電腦) 通訊。

將 USB 傳輸線的 Micro-USB 端從閃爍的 nRF52840 電路板的偵錯連接埠中卸除,然後將 USB 傳輸線重新插入「重設」按鈕旁邊的 micro-USB nRF USB 連接埠。將「nRF 電源」開關設為「USB」

46e7b670d2464842.png

驗證版本

透過終端機視窗使用 GNU 畫面存取 OpenThread CLI,驗證建構作業是否成功。nRF52840 主機板採用 115200 的欺詐率。

$ screen /dev/ttyACM1 115200

在新視窗中,按下鍵盤上的 Return 鍵數次,即可顯示 OpenThread CLI > 提示。開啟 IPv6 介面並檢查位址:

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

請按下 Ctrl + A 鍵 →

d 從 FTD Commissioner CLI 畫面卸離並返回 Linux 終端機,以便刷新的下一個 Jamboard。您隨時可以在指令列中使用 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」

連接這個第三板連接時,如果另外兩個節點連接至 Linux 電腦,它應顯示為序列埠 /dev/ttyACM2

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

將討論板加上「Joiner」標籤。

使用 Screen 進行驗證時,請重新附加至現有畫面,並在該執行個體中建立新視窗 (您用於 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 Commissioner 使用相同的螢幕執行個體,您可以使用 Ctrl +a → n 在兩者間切換。

請按下 Ctrl + A 鍵 →

d 隨時退出螢幕。

6. 終端機視窗設定

日後,你將會經常切換 Thread 裝置,因此請確認所有裝置皆已上線且易於存取。到目前為止,我們一直使用 Screen 存取這兩個 FTD,這項工具也允許同一個終端機視窗分割畫面。使用此項目可查看節點如何回應其他節點發出的指令。

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

  1. ot-daemon 服務 / 記錄檔
  2. 透過 ot-ctlRCP 彙整器
  3. 透過 OpenThread CLI 使用 FTD Commissioner
  4. 透過 OpenThread CLI 使用 FTD 彙整器

如要使用自己的終端機 / 序列埠設定或工具,請跳至下一個步驟。根據你的需求,為所有裝置設定終端機視窗。

使用螢幕

為方便使用,請只啟動一個畫面工作階段。您在設定兩項 FTD 時,應該已備妥這組 ID。

畫面中的所有指令開頭皆為 Ctrl +a。

基本螢幕指令:

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

screen -r

離開螢幕工作階段

Ctrl + A → d

在畫面工作階段內建立新視窗

Ctrl + A → c

在同一個畫面工作階段中切換視窗

Ctrl + A → n (轉寄) Ctrl + A → p (返回)

終止目前的畫面工作階段

Ctrl + A → k

分割畫面

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

f1cbf1258cf0a5a.png

如要存取 screen 中的指令,請按下 Ctrl + A 鍵。每個指令都應該以這個存取金鑰的組合為開頭。

如果你確實按照程式碼研究室的指示操作,則同一個畫面執行個體應會顯示兩個視窗 (FTD Commissioner、FTD Joiner)。如要在兩者間分割畫面,請先進入現有的畫面工作階段:

$ 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 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 裝置掃描到網路時,畫面上就會顯示網路。

透過 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 |

如果「程式碼研究室」清單中未顯示這個網路,請再掃描一次。

8. 新增 RCP 彙整器

網路上未啟用 Thread 調校功能,我們需要將 RCP 聯結程式新增至剛剛透過頻外調控程序建立的 Thread 網路。

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

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

接著,在「RCP 彙整器」中,將使用中的資料集網路金鑰設為 FTD Commissioner 網路金鑰:

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

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

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

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

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

啟動 Thread,以便 RCP 聯結器加入「程式碼研究室」更是如此稍候片刻,然後檢查狀態、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 輸出內容取得的 Mesh-Local 位址) 連線偵測 (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

我們現在擁有由兩個節點組成的 Thread 網路,如以下拓撲圖所示:

otcodelab_top01C_2nodes.png

拓撲圖

當您在程式碼研究室的其他部分,每當網路狀態改變,我們就會顯示新的 Thread 拓撲圖表。節點角色的定義如下:

b75a527be4563215.png

路由器一律為十字形,且最終裝置一律為圓形。每個節點的數字代表 CLI 輸出內容中顯示的路由器 ID 或子項 ID,視每個節點當時的角色和狀態而定。

9. 調試 FTD 聯名家

現在將第三個 Thread 裝置新增至「程式碼研究室」更是如此這次我們會使用更安全的頻內調控程序,只允許 FTD 聯結器加入。

FTD Joiner 上取得 eui64,以便 FTD 委員會識別:

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

> eui64
2f57d222545271f1
Done

FTD Commissioner 中啟動 FTD Commissioner,並指定可加入的裝置 eui64,以及彙整者憑證,例如 J01NME。彙整憑證是裝置專屬字串,由所有大寫英數字元 (0 至 9 和 A-Y 組成,但不包括 I、O、Q 和 Z),長度介於 6 至 32 個字元。

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

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

切換到 FTD 彙整器。使用剛剛在 FTD 委員會設定的彙整者憑證建立彙整角色:

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

> ifconfig up
Done
> joiner start J01NME
Done

大約一分鐘內,您會收到驗證成功的確認訊息:

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

>
Join success

開啟 Thread,讓 FTD 聯結器加入「程式碼研究室」並立即檢查狀態和 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 委員會,檢查路由器和子資料表,確認「程式碼研究室」中有這 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. 討論串應用實例

本程式碼研究室中的 Thread 裝置是一種特定類型的完整 Thread 裝置 (FTD),稱為路由器符合資格的終端裝置 (REED)。也就是說,這類裝置可以做為路由器或終端裝置使用,也可將自身從終端裝置升級為路由器。

Thread 最多可支援 32 個路由器,但會試著將路由器數量保持在 16 和 23 之間。如果 REED 以終端裝置 (子) 連接,而路由器數量低於 16,則系統會在隨機時間後兩分鐘內,自動將自身推送至路由器。

如果在新增 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 Commissioner 後,子資料表 (ID = 3) 應會顯示 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 |
|   3 | 0x0c03 |        240 |         16 |     3 |   94 |1|1|1|1| e6cdd2d93249a243 |
Done

一段時間後,裝置會切換回 RLOC 為 b800 的路由器。

otcodelab_top01C.png

移除主管

所有 Thread 路由器都會自行選擇主要路由器。也就是說,如果將目前的領導者從 Thread 網路中移除,另一部路由器就會成為新的領導者。

FTD Commissioner 上關閉 Thread,將其從 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 Commissioner 改為 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

請稍候幾分鐘,等待 RCP 加入者以孩童身分附加至 FTD 加入器。請查看狀態和 RLOC16 以確認下列事項:

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

> state
child
> rloc16
b801

重新附加 FTD 委員會

有兩個節點的 Thread 網路沒什麼好玩的。讓我們重新上線 FTD 委員會。

FTD Commissioner 上重新啟動 Thread:

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

> ifconfig up
Done
> thread start
Done

兩分鐘內,指令碼會自動重新附加至「程式碼研究室」並升級為路由器。

## 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 網路拓撲並未如本程式碼研究室所述,或是節點因故中斷連線 (可能是因為提供這些 Thread 的 Linux 裝置進入休眠狀態),建議你關閉 Thread 並清除網路憑證,然後重新執行「建立 Thread 網路」步驟。

重設 FTD:

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

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

可以透過 ot-ctl 以相同的方式重設 RCP:

## 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 多點傳播位址進行連線偵測 (ping)。

來自 FTD 委員會的連線偵測 (ping) 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 彙整者和 RCP 彙整者),但 FTD 委員會只收到 FTD 彙整者的連結本機位址 (LLA) 傳送的一次回應。也就是說,FTD 彙整器是唯一可透過單一躍點到達的裝置。

otcodelab_top02C_02_LL.png

正在從 FTD 彙整器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

有兩則回應!檢查其他裝置的 IPv6 位址時,我們可以發現第一個 (結尾為 4b1d) 是 FTD 委員會的 LLA,第二個 (結尾為 943b) 則是 RCP 彙整器的 LLA。

otcodelab_top02C_02_LL02.png

這表示 FTD 彙整者會直接與 FTD 委員會和代表本拓撲的 RCP 彙整者聯繫。

網格本機

Mesh-Local 範圍包含同一個 Thread 網路內可連線的所有 Thread 介面。我們來看看對 ff03::1 多點傳播位址進行連線偵測 (ping) 的回應。

來自 FTD 委員會的連線偵測 (ping) 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),另一份來自 RCP 彙整者的網狀本機 EID (ML-EID,結尾為 d55f)。這是因為「網狀本機」範圍涵蓋整個 Thread 網路。無論裝置位於何處,該裝置都會訂閱 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 委員會 (FTD 委員會) 所需的時間,比達成 FTD 彙整器的時間高出許多 (23 毫秒)。這是因為相較於 FTD 加入者,必須完成兩個躍點才能觸及 FTD 委員會。

您可能也會發現,網狀本機多點傳播連線偵測僅針對兩個 FTD 回應,而非 RCP 彙整器。這是因為 FTD 是網路中的路由器,而 RCP 則是終端裝置。

請查看 RCP 彙整器的狀態,確認下列事項:

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

> state
child

13. 透過 UDP 傳送訊息

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

UDP 通訊端會透過 OpenThread CLI 公開。現在來在兩個 FTD 之間傳遞訊息。

取得 FTD 彙整器的 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,然後使用 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 Joiner 中收到 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 資源,包括:

參考資料: