1. 簡介
Google 發布的 OpenThread 是 Thread® 網路通訊協定的開放原始碼實作項目。Google Nest 發布了 OpenThread,讓開發人員廣泛使用 Nest 產品中的技術,加快開發智慧聯網家庭產品的速度。
Thread 規格定義了以 IPv6 為基礎的無線裝置間通訊協定,可用於家用應用程式,提供可靠、安全且耗電量低的通訊機制。OpenThread 實作所有 Thread 網路層,包括 IPv6、6LoWPAN、IEEE 802.15.4 (含 MAC 安全性)、Mesh Link 建立和 Mesh 路由。
在本程式碼研究室中,您將在實際硬體上編寫 OpenThread 程式碼、建立及管理 Thread 網路,並在節點之間傳遞訊息。
課程內容
- 建構並將 OpenThread CLI 二進位檔閃過開發板
- 建構由 Linux 電腦和開發板組成的 RCP
- 使用 OpenThread Daemon 和
ot-ctl
與 RCP 通訊 - 使用 GNU Screen 和 OpenThread CLI 手動管理執行緒節點
- 在 Thread 網路上安全地啟用裝置
- IPv6 多播的運作方式
- 使用 UDP 在執行緒節點之間傳遞訊息
軟硬體需求
硬體:
- 3 個 Nordic Semiconductor nRF52840 開發板
- 3 條 USB 轉 Micro-USB 傳輸線,用於連接電路板
- 至少有 3 個 USB 連接埠的 Linux 電腦
軟體:
- GNU 工具鍊
- Nordic nRF5x 指令列工具
- Segger J-Link 軟體
- OpenThread
- Git
2. 開始使用
OpenThread 模擬
在開始之前,建議您先完成 OpenThread 模擬程式碼研究室,熟悉基本執行緒概念和 OpenThread CLI。
序列埠終端機
您應該熟悉如何透過終端機連線至序列埠。本程式碼研究室使用 GNU Screen,並提供使用概況,但您也可以使用任何其他終端機軟體。
Linux 機器
本程式碼研究室的設計目的是使用 i386 或 x86 架構的 Linux 機器,做為無線電共用處理器 (RCP) Thread 裝置的主機,並對所有 Thread 開發板進行閃燈作業。所有步驟均已在 Ubuntu 14.04.5 LTS (Trusty Tahr) 上測試。
Nordic Semiconductor nRF52840 板卡
本程式碼研究室使用三個 nRF52840 PDK 板。
安裝 SEGGER J-Link
我們使用 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,但您可以使用任何想要的序列埠終端機應用程式。
$ 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 彙整器
建構及閃現
使用 Joiner 和原生 USB 功能建構 OpenThread nRF52840 範例。裝置會使用加入者角色,以安全的方式進行驗證,並在 Thread 網路上啟用。原生 USB 可讓您將 USB CDC ACM 用於 nRF52840 和主機之間的序列傳輸。
請務必先執行 rm -rf build
,清理先前建構作業的 repo。
$ 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 會亮起。
如果這是連接至 Linux 機器的第一個板子,則會顯示為序列埠 /dev/ttyACM0
(所有 nRF52840 板子都會使用 ttyACM
做為序列埠 ID)。
$ ls /dev/ttyACM* /dev/ttyACM0
請注意,用於 RCP 的 nRF52840 板序號:
前往 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 傳輸線的 Micro-USB 端從已刷新韌體的 nRF52840 板的偵錯埠上拔除,然後重新連接至 RESET 按鈕旁的 Micro-USB nRF USB 連接埠。將 nRF 電源切換鈕設為 USB。
啟動 OpenThread Daemon
在 RCP 設計中,請使用 OpenThread Daemon 與 Thread 裝置通訊及管理該裝置。請使用 -v
詳細標記啟動 ot-daemon
,以便查看記錄輸出內容,並確認 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
節點。
在第二個終端機視窗中啟動 ot-ctl
:
$ sudo ./build/posix/src/posix/ot-ctl >
請檢查您使用 ot-daemon
啟動的節點 2 (RCP 節點) 的 state
:
> state disabled Done
5. 設定 FTD
本程式碼研究室中使用的其他兩個 Thread 節點,是標準單晶片系統 (SoC) 設計中的全 Thread 裝置 (FTD)。在實際工作環境中,您可以使用 wpantund
(實際工作環境等級的網路介面驅動程式) 控制 OpenThread NCP 例項,但在本程式碼研究室中,我們會使用 OpenThread 指令列介面 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 板的序號:
前往 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 傳輸線的 Micro-USB 端從已刷新內容的 nRF52840 板的偵錯連接埠上拔除,然後重新連接至 RESET 按鈕旁的 Micro-USB nRF USB 連接埠。將 nRF 電源切換鈕設為 USB。
驗證建構作業
透過從終端機視窗使用 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 總監 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
版本刷新第三個 nRF52840 電路板。完成後,請務必使用 nRF USB 連接埠將電路板重新連接至電腦,並將 nRF 電源切換至 VDD。
如果其他兩個節點在連接這第三個板子時已連接到 Linux 機器,則應顯示為序列埠 /dev/ttyACM2
:
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1 /dev/ttyACM2
將板子標示為「Joiner」。
使用 Screen 進行驗證時,請勿透過指令列建立新的 Screen 例項,而是重新連結至現有的例項,並在其中建立新的視窗 (您用於 FTD 管理員):
$ screen -r
使用 Ctrl + a → c
在 Screen 中建立新視窗。
畫面上會顯示新的命令提示字元。存取 FTD 彙整器的 OpenThread CLI:
$ screen /dev/ttyACM2
在這個新視窗中,按幾下鍵盤上的「Return」鍵,即可顯示 OpenThread CLI >
提示。啟動 IPv6 介面並檢查位址:
> ifconfig up Done > ipaddr fe80:0:0:0:6c1e:87a2:df05:c240 Done
由於 FTD 彙整器 CLI 與 FTD 管理員位於同一個 Screen 例項中,您可以使用 Ctrl+a → n
切換這兩個工具。
使用 Ctrl + A →
d
隨時可以退出 Screen。
6. 設定終端機視窗
往後你會經常切換 Thread 裝置,因此請確認所有裝置都已啟用且可輕鬆存取。到目前為止,我們一直使用 Screen 存取這兩個 FTD,而且這個工具也允許在同一個終端機視窗中分割畫面。這項功能可讓您查看一個節點如何回應另一個節點所發出的指令。
理想情況下,您應該準備好四個視窗:
ot-daemon
服務 / 記錄- 透過
ot-ctl
彙整 RCP - 透過 OpenThread CLI 執行 FTD 委派作業
- 透過 OpenThread CLI 執行 FTD 彙整器
如果您想使用自己的終端機 / 序列埠設定或工具,請直接跳到下一個步驟。根據您的需求,為所有裝置設定最適合的終端機視窗。
使用螢幕
為方便使用,請只啟動一個 Screen 工作階段。您應該在設定兩個 FTD 時就已建立一個。
Screen 中的所有指令都以 Ctrl+a 開頭。
基本螢幕指令:
重新連結至 Screen 工作階段 (透過指令列) |
|
離開螢幕工作階段 | Ctrl + A → |
在螢幕工作階段中建立新視窗 | Ctrl + A → |
在同一個螢幕工作階段中切換視窗 | Ctrl + a → |
在 Screen 工作階段中終止目前的視窗 | Ctrl + A → |
分割畫面
您可以使用 Screen 將終端機分割成多個視窗:
您可以使用 Ctrl + a 存取 screen
中的指令。每個指令都應以此存取鍵組合開頭。
如果您確實遵循程式碼研究室的操作說明,應該會在同一個 Screen 例項上看到兩個視窗 (FTD 委派者、FTD 參與者)。如要將畫面分割成兩個畫面,請先進入現有的 Screen 工作階段:
$ screen -r
您應使用 FTD 裝置。請按照下列步驟操作:
- Ctrl + A →
S
,將視窗水平分割 - Ctrl + a →
Tab
,將游標移至新的空白視窗 - Ctrl + a →
n
,將新視窗切換至下一個 - 如果與頂端視窗相同,請再次按下 Ctrl + a →
n
查看其他 FTD 裝置
兩者現在都會顯示。使用 Ctrl + a → Tab
切換兩者。建議您使用 Ctrl+a → A
重新命名每個視窗,以免造成混淆。
進階用途
如要進一步將畫面分割成四分之一,並查看 ot-daemon
記錄和 RCP 彙集器 ot-ctl
,必須在同一個 Screen 例項中啟動這些服務。如要這樣做,請停止 ot-daemon
並退出 ot-ctl
,然後在新 Screen 視窗中重新啟動 (Ctrl+a → c
)。
這項設定並非必要,可由使用者自行設定。
使用下列指令分割及瀏覽視窗:
建立新視窗 | Ctrl + A → |
垂直分割視窗 | Ctrl+a → |
水平分割視窗 | Ctrl + A → |
跳到下一個顯示的視窗 | Ctrl + A → |
切換顯示的視窗 (向前或向後) | Ctrl + A → |
重新命名目前的視窗 | Ctrl + 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 start Done
過一會兒,請檢查裝置狀態。應為 Leader。另外,請取得 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 彙整工具
Thread 委派作業並未在網路上啟用,因此我們必須使用輔助委派程序,將 RCP 彙集器新增至剛剛建立的 Thread 網路。
在 FTD 專員中,我們會記下網路金鑰,例如 1234c0de7ab51234c0de7ab51234c0de
。如果需要再次查詢網路金鑰,請在 FTD Commissioner 上執行下列指令:
## FTD Commissioner ## > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done
接著,在 RCP 彙整器中,將其有效資料集 Network Key 設為 FTD 管理員 Network Key:
## RCP Joiner ## ---------------- > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done > dataset commit active Done
檢查資料集,確認設定正確無誤。
## RCP Joiner ## ---------------- > dataset Network Key: 1234c0de7ab51234c0de7ab51234c0de
開啟執行緒,讓 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
請記下 Mesh-Local IPv6 位址 (此處為 fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f
),稍後會用到。
回到 FTD Commissioner,檢查路由器和子表格,確認兩部裝置都已連上同一個網路。使用 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 彙整器的 Mesh-Local 位址 (從 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 網路,如這個拓撲圖所示:
拓撲圖
在您完成程式碼研究室的其餘部分時,我們會在網路狀態變更時顯示新的執行緒拓樸圖。節點角色的表示方式如下:
路由器一律為五角形,終端裝置一律為圓形。每個節點上的數字代表 CLI 輸出內容中的 Router ID 或 Child ID,這取決於各節點當時的角色和狀態。
9. 向 FTD 加入者收取佣金
現在,我們要將第三個 Thread 裝置新增至「codelab」網路。這次我們會使用更安全的頻內調試程序,並只允許 FTD 加入者加入。
在 FTD 彙整器上取得 eui64
,讓 FTD 管理員能夠辨識:
## FTD Joiner ## ---------------- > eui64 2f57d222545271f1 Done
在 FTD Commissioner 上啟動 Commissioner,並指定可加入的裝置 eui64
和 Joiner 憑證 (例如 J01NME
)。加入者憑證是特定裝置的字串,包含所有大寫英數字元 (0 到 9 和 A 到 Y,不含 I、O、Q 和 Z,以便閱讀),長度介於 6 到 32 個半形字元之間。
## 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
請啟動執行緒,讓 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 Commissioner,並檢查路由器和子表格,確認「codelab」網路中存在三部裝置:
## 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 彙整器已以終端裝置 (子項) 的形式連結至網路。以下是更新後的拓撲圖:
10. 執行中的執行緒
本程式碼研究室中的 Thread 裝置是特定類型的 Full Thread Device (FTD),稱為 Router Eligible End Device (REED)。這表示這些裝置可做為路由器或終端裝置,並可將自己從終端裝置升級為路由器。
執行緒最多可支援 32 個 Router,但會嘗試將 Router 的數量維持在 16 到 23 之間。如果 REED 以終端裝置 (子項) 的形式連線,且路由器數量低於 16,REED 會在兩分鐘內的隨機時間後,自動升級為路由器。
如果在加入 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 彙整器 (Extended MAC = e6cdd2d93249a243
) 已將自身升級為路由器。請注意,RLOC16 不同 (b800
而非 0c02
),這是因為 RLOC16 是根據裝置的 Router ID 和 Child ID 計算。從終端裝置轉換為路由器時,其路由器 ID 和子 ID 值會變更,RLOC16 也會隨之變更。
在 FTD 彙集器上確認新狀態和 RLOC16:
## FTD Joiner ## ---------------- > state router Done > rloc16 b800 Done
降級 FTD 彙整器
您可以手動將 FTD 彙集器 從路由器降級為終端裝置,藉此測試這項行為。將狀態變更為子項,並檢查 RLOC16:
## FTD Joiner ## ---------------- > state child Done > rloc16 0c03 Done
回到 FTD 委派者,現在子表格 (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
的 Router。
移除主管
領導者會在所有執行緒路由器中自行選出。也就是說,如果目前的領導裝置從 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
請檢查子資料表。請注意,這裡有一個新的 RLOC16。這是 RCP 彙集器,如其 ID 和 Extended MAC 所示。為了讓 Thread 網路保持連線,它已將父項 Router 從 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 Joiner 以子項的形式附加至 FTD Joiner。請檢查狀態和 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 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
我們的 Thread 網路同樣由三個節點組成。
11. 疑難排解
在不同的終端機或 Screen 視窗上,管理具有多個裝置的 Thread 網路可能會很複雜。如果遇到問題,請參考下列訣竅「重設」網路或工作區的狀態。
螢幕
如果您在設定時迷失方向 (例如 Screen 視窗太多,或 Screen 內有太多 Screen),請持續使用 Ctrl+a → k 關閉 Screen 視窗,直到沒有任何視窗,且命令列上的 screen -ls
輸出 No Sockets found
為止。然後為每部裝置重新建立螢幕視窗。即使螢幕已終止,裝置狀態仍會保留。
執行緒節點
如果 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 位址 | 範圍 | 已送達 |
| Link-Local | 所有 FTD 和 MED |
| Link-Local | 所有 FTD 和邊界路由器 |
| 網格-本機 | 所有 FTD 和 MED |
| 網格-本機 | 所有 FTD 和邊界路由器 |
由於本程式碼研究室未使用邊界路由器,因此我們將著重於兩個 FTD 和 MED 多點傳送位址。
Link-Local
連結區域範圍包含單一無線電傳輸或單一「跳躍」可到達的所有 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
網路中還有其他兩部裝置 (FTD 彙整器和 RCP 彙整器),但 FTD 總管只收到一個回應,來自 FTD 彙整器的連結本機位址 (LLA)。也就是說,FTD 彙整器是 FTD 調度器可在單一跳躍中觸及的唯一裝置。
接著從 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
兩個回覆!查看其他裝置的 IPv6 位址,我們可以看到第一個 (結尾為 4b1d
) 是 FTD 管理員的 LLA,第二個 (結尾為 943b
) 是 RCP 彙整器的 LLA。
這表示 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 加入者的路由定位器 (RLOC,結尾為 b800
),另一個來自 RCP 加入者的 Mesh-Local EID (ML-EID,結尾為 d55f
)。這是因為 Mesh-Local 範圍包含整個 Thread 網路。無論裝置位於網路中的何處,都會訂閱 ff03::1
位址。
從 FTD Joiner 連線偵測 (ping) 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
請注意,在兩個 ping 輸出內容中,RCP 彙整器的回應時間為 RCP 彙整工具到達 FTD 調度器的時間 (68 毫秒) 比到達 FTD 彙整工具的時間 (23 毫秒) 長得多。這是因為 FTD 彙整器必須進行兩次跳躍才能到達 FTD 管理員,而 FTD 彙整器只需進行一次跳躍。
您可能也注意到,網狀區域多點 ping 只會針對兩個 FTD 回應 RLOC,而不會回應 RCP 彙集器。這是因為 FTD 是網路中的路由器,而 RCP 是終端裝置。
檢查 RCP 彙集器的狀態,確認以下事項:
## RCP Joiner ## ---------------- > state child
13. 使用 UDP 傳送訊息
OpenThread 提供的應用程式服務之一是傳輸層通訊協定 (UDP)。以 OpenThread 建構的應用程式可使用 UDP API,在 Thread 網路中的節點之間傳遞訊息,或傳送至外部網路中的其他裝置 (如果 Thread 網路設有邊界路由器,則可傳送至網際網路)。
透過 OpenThread CLI 公開 UDP 通訊端。讓我們使用它在兩個 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 位址的 Socket:
## FTD Joiner ## ---------------- > udp open Done > udp bind :: 1212
切換至 FTD Commissioner、啟動 UDP,並使用 ML-EID 連線至在 FTD Joiner 上設定的 Socket:
## 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 網路!
您現在知道:
- 執行緒裝置類型、角色和範圍的差異
- Thread 裝置如何管理網路中的狀態
- 如何使用 UDP 在節點之間傳遞簡單訊息
後續步驟
請根據本程式碼研究室的內容,嘗試下列練習:
- 使用
ot-cli-mtd
二進位檔,將 FTD 彙整板重新刷新為 MTD,並觀察是否會自行升級為 Router,或嘗試成為 Leader - 在網路中新增更多裝置 (試試其他平台!),並使用路由器和子項資料表,以及對多點傳送位址執行 ping 作業,勾勒出拓樸圖
- 使用 pyspinel 控制 NCP
- 使用 OpenThread 邊界路由器將 NCP 轉換為邊界路由器,並將 Thread 網路連上網際網路
延伸閱讀
請造訪 openthread.io 和 GitHub,取得各種 OpenThread 資源,包括:
- 支援的平台:查看支援 OpenThread 的所有平台
- 建構 OpenThread:進一步瞭解如何建構及設定 OpenThread
- 執行緒入門:涵蓋本程式碼研究室中所有執行緒概念
參考資料: