1. 簡介
Google 發布的 OpenThread 是 Thread® 網路通訊協定的開放原始碼實作項目。Google Nest 已發布 OpenThread,讓開發人員廣泛使用 Nest 產品採用的技術,加速開發智慧聯網家庭產品。
Thread 規格定義了以 IPv6 為基礎的可靠、安全且低功耗的無線裝置對裝置通訊協定,適用於居家應用。OpenThread 會實作所有 Thread 網路層,包括 IPv6、6LoWPAN、IEEE 802.15.4 (含 MAC 安全性)、網狀連結建立和網狀路徑。
在本程式碼研究室中,您將在實際硬體上編寫 OpenThread 程式、建立及管理 Thread 網路,並在節點之間傳遞訊息。
課程內容
- 將 OpenThread CLI 二進位檔建構並刷入開發板
- 建構由 Linux 電腦和開發板組成的 RCP
- 使用 OpenThread Daemon 和
ot-ctl
與 RCP 通訊 - 使用 GNU Screen 和 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 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 程式設計 nRF52840 開發板,這些開發板內建 JTAG 模組。在 Linux 電腦上安裝這個程式。
為電腦下載適當的套件,並安裝在正確位置。在 Linux 上,這是 /opt/SEGGER/JLink
。
安裝 nRF5x 指令列工具
您可以使用 nRF5x 指令列工具,將 OpenThread 二進位檔刷入 nRF52840 開發板。在 Linux 電腦上安裝適當的 nRF5x-Command-Line-Tools-<OS> 建構版本。
將解壓縮的套件放入根資料夾 ~/
安裝 ARM GNU Toolchain
建構時會使用 ARM GNU Toolchain。
建議您將解壓縮的封存檔放在 Linux 電腦的 /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/
中。按照封存檔 readme.txt
檔案中的操作說明安裝。
安裝 Screen (選用)
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
建構及刷機
使用 Joiner 和原生 USB 功能建構 OpenThread nRF52840 範例。裝置會使用 Joiner 角色安全地通過驗證,並委派至 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 power source」(nRF 電源) 切換開關設為「VDD」。正確連接後,LED5 會亮起。
如果這是連結至 Linux 機器的第一個開發板,則會顯示為序列埠 /dev/ttyACM0
(所有 nRF52840 開發板都使用 ttyACM
做為序列埠 ID)。
$ ls /dev/ttyACM* /dev/ttyACM0
請記下用於 RCP 的 nRF52840 開發板序號:
前往 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 機器) 通訊。
從已刷寫 nRF52840 板的偵錯埠拔除 USB 傳輸線的 Micro-USB 端,然後重新連接至 RESET 按鈕旁邊的 Micro-USB nRF USB 連接埠。將「nRF power source」(nRF 電源) 切換鈕設為「USB」。
啟動 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=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
使用的 CLI 與 OpenThread 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)。其中一部裝置會做為 Commissioner,負責安全地驗證裝置,並將裝置委派給該網路。另一部裝置則做為加入者,可供管理員驗證加入 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 十六進位檔案刷到 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 機器) 通訊。
從已刷寫 nRF52840 板的偵錯埠拔除 USB 傳輸線的 Micro-USB 端,然後重新連接至 RESET 按鈕旁邊的 Micro-USB nRF USB 連接埠。將「nRF power source」(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 Commissioner CLI 畫面中分離,然後返回 Linux 終端機,以便刷寫下一個開發板。如要隨時重新進入 CLI,請從指令列使用 screen -r
。如要查看可用螢幕清單,請使用 screen -ls
:
$ screen -ls There is a screen on: 74182.ttys000.mylinuxmachine (Detached) 1 Socket in /tmp/uscreens/S-username.
設定 FTD Joiner
重複上述程序,使用現有的 ot-cli-ftd.hex
建構版本,刷寫第三個 nRF52840 開發板。完成後,請務必使用 nRF USB 連接埠將開發板重新連接至電腦,並將 nRF 電源開關設為 VDD。
如果其他兩個節點在連接第三個開發板時已附加至 Linux 電腦,則應會顯示為序列埠 /dev/ttyACM2
:
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1 /dev/ttyACM2
將看板標示為「Joiner」。
使用 Screen 進行驗證時,請勿從指令列建立新的 Screen 執行個體,而是重新附加至現有執行個體,並在其中建立新視窗 (您用於 FTD 專員的視窗):
$ screen -r
在 Screen 中建立新視窗:按下 Ctrl+a → c
。
畫面上會顯示新的命令列提示。存取 FTD Joiner 的 OpenThread CLI:
$ screen /dev/ttyACM2
在新視窗中,按幾次鍵盤上的 Return 鍵,叫出 OpenThread CLI >
提示。啟動 IPv6 介面並檢查位址:
> ifconfig up Done > ipaddr fe80:0:0:0:6c1e:87a2:df05:c240 Done
現在 FTD Joiner CLI 與 FTD Commissioner 位於同一個 Screen 執行個體,因此可以使用 Ctrl+a → n
在兩者之間切換。
使用 Ctrl+a →
d
隨時退出「螢幕」模式。
6. 設定終端機視窗
日後你將經常切換 Thread 裝置,因此請確保所有裝置都已上線且容易存取。到目前為止,我們都是使用 Screen 存取這兩個 FTD,而這個工具也允許在同一個終端機視窗中分割畫面。您可以使用這項功能,查看一個節點對另一個節點發出的指令有何反應。
理想情況下,您應該有四個可用的視窗:
ot-daemon
服務 / 記錄- 透過
ot-ctl
RCP Joiner - 透過 OpenThread CLI FTD 專員
- 透過 OpenThread CLI FTD Joiner
如要使用自己的終端機 / 序列埠設定或工具,請跳到下一個步驟。以最適合自己的方式設定所有裝置的終端機視窗。
使用螢幕
為方便使用,請只啟動一個螢幕共用工作階段。設定兩個 FTD 時,您應該已經有一個。
Screen 中的所有指令都以 Ctrl+a 開頭。
基本螢幕指令:
重新附加至 Screen 工作階段 (透過指令列) |
|
離開 Screen 工作階段 | Ctrl+a → |
在 Screen 工作階段中建立新視窗 | Ctrl+a → |
在同一 Screen 工作階段中切換視窗 | Ctrl+a → |
終止 Screen 工作階段中的目前視窗 | Ctrl+a → |
分割畫面
使用 Screen 時,你可以將終端機分割為多個視窗:
使用 Ctrl + a 鍵即可存取 screen
中的指令。所有指令都應以這個快速鍵組合開頭。
如果您確實遵循本程式碼研究室的操作說明,應該會在同一個 Screen 執行個體上看到兩個視窗 (FTD Commissioner、FTD Joiner)。如要在兩個畫面之間分割畫面,請先輸入現有的 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 Joiner ot-ctl
,必須在這個相同的畫面執行個體中啟動這些服務。如要這麼做,請停止 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 專員上建立新的作業資料集,並將其提交為有效資料集。作業資料集是您要建立的 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
稍候片刻,然後檢查裝置狀態。應該是 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」網路。
從 ot-ctl
上的 RCP Joiner:
## RCP Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -36 | 232 |
在 FTD Joiner 上,透過 OpenThread CLI 執行下列操作:
## FTD Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -38 | 229 |
如果清單中未顯示「codelab」網路,請再次掃描。
8. 新增 RCP Joiner
網路上的 Thread 委派作業未啟用,因此我們需要使用頻外委派程序,將 RCP Joiner 新增至剛建立的 Thread 網路。
在 FTD 專員上,我們記下網路金鑰,例如 1234c0de7ab51234c0de7ab51234c0de
。如需再次查詢網路金鑰,請在 FTD 專員上執行下列指令:
## FTD Commissioner ## > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done
接著,在 RCP Joiner 上,將其有效資料集網路金鑰設為 FTD Commissioner 網路金鑰:
## RCP Joiner ## ---------------- > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done > dataset commit active Done
檢查資料集,確認設定正確無誤。
## RCP Joiner ## ---------------- > dataset Network Key: 1234c0de7ab51234c0de7ab51234c0de
啟動 Thread,讓 RCP Joiner 加入「codelab」網路。等待幾秒鐘,檢查狀態、RLOC16 和 IPv6 位址:
## RCP Joiner ## ---------------- > ifconfig up Done > thread start Done > state child Done > rloc16 0c01 Done > ipaddr fdc0:de7a:b5c0:0:0:ff:fe00:0c01 # Routing Locator (RLOC) fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f # Mesh-Local EID (ML-EID) fe80:0:0:0:18e5:29b3:a638:943b # Link-Local Address (LLA) Done
記下網狀網路本機 IPv6 位址 (fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f
),稍後會用到。
返回 FTD Commissioner,檢查路由器和子項表格,確認兩部裝置都屬於同一個網路。使用 RLOC16 識別 RCP Joiner。
## FTD Commissioner ## ---------------------- > router table | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+-------+--------+-----+------------------+ | 3 | 0x0c00 | 3 | 0 | 0 | 0 | 35 | 1ed687a9cb9d4b1d | Done > child table | ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|S|D|VER| Extended MAC | +-----+--------+------------+------------+-------+------+-+-+-+---+------------------+ | 1 | 0x0c01 | 240 | 25 | 3 | 89 |1|1|1| 2| 1ae529b3a638943b | Done
連線偵測 (ping) RCP Joiner 的網狀網路本機位址 (從 RCP Joiner 的 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 網路,拓撲圖如下所示:
拓撲圖
在完成其餘程式碼研究室的過程中,每當網路狀態變更時,我們都會顯示新的 Thread 拓撲圖。節點角色標示如下:
路由器一律為五邊形,終端裝置一律為圓形。每個節點上的數字代表 CLI 輸出中顯示的路由器 ID 或子項 ID,視每個節點當時的角色和狀態而定。
9. 委派 FTD Joiner
現在,讓我們將第三個 Thread 裝置新增至「codelab」網路。這次我們將使用更安全的頻內委派程序,且只允許 FTD Joiner 加入。
在 FTD Joiner 上取得 eui64
,以便 FTD Commissioner 識別:
## FTD Joiner ## ---------------- > eui64 2f57d222545271f1 Done
在 FTD Commissioner 上啟動 Commissioner,並指定可加入的裝置 eui64
,以及 Joiner Credential,例如 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 Commissioner 上設定的 Joiner Credential,啟動 Joiner 角色:
## FTD Joiner ## ---------------- > ifconfig up Done > joiner start J01NME Done
驗證成功後,您會在幾分鐘內收到確認訊息:
## FTD Joiner ## ---------------- > Join success
啟動 Thread,讓 FTD Joiner 加入「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 Joiner 已以終端裝置 (子項) 的身分連上網路。以下是更新後的拓撲:
10. 執行中的執行緒
本程式碼研究室中的 Thread 裝置是特定類型的完整 Thread 裝置 (FTD),稱為「符合路由器資格的終端裝置」(REED)。這表示裝置可做為路由器或終端裝置,並可從終端裝置升級為路由器。
Thread 最多可支援 32 個路由器,但會盡量將路由器數量維持在 16 到 23 個之間。如果 REED 以終端裝置 (子項) 形式附加,且路由器數量少於 16 個,REED 會在兩分鐘內的隨機時間段後,自動升級為路由器。
如果在新增 FTD Joiner 後,Thread 網路中有兩個子項,請等待至少兩分鐘,然後在 FTD Commissioner 上重新檢查路由器和子項表格:
## FTD Commissioner ## ---------------------- > router table | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+-------+--------+-----+------------------+ | 3 | 0x0c00 | 3 | 0 | 0 | 0 | 50 | 1ed687a9cb9d4b1d | | 46 | 0xb800 | 63 | 0 | 3 | 3 | 1 | e6cdd2d93249a243 | > child table | ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|S|D|N| Extended MAC | +-----+--------+------------+------------+-------+------+-+-+-+-+------------------+ | 1 | 0x0c01 | 240 | 61 | 3 | 89 |1|1|1|1| 1ae529b3a638943b | Done
FTD Joiner (擴充 MAC = e6cdd2d93249a243
) 已將自己升級為路由器。請注意,RLOC16 不同 (b800
而非 0c02
),這是因為 RLOC16 是以裝置的路由器 ID 和子項 ID 為準。當裝置從終端裝置轉換為路由器時,路由器 ID 和子項 ID 值會變更,RLOC16 也會變更。
在 FTD Joiner 上確認新狀態和 RLOC16:
## FTD Joiner ## ---------------- > state router Done > rloc16 b800 Done
降級 FTD Joiner
您可以手動將 FTD Joiner 從路由器降級為終端裝置,測試這項行為。將狀態變更為子項,並檢查 RLOC16:
## FTD Joiner ## ---------------- > state child Done > rloc16 0c03 Done
返回 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
的路由器。
移除領導者
領導者是從所有執行緒路由器中選出。也就是說,如果目前的領導者從 Thread 網路中移除,其他路由器就會成為新的領導者。
在 FTD Commissioner 上關閉 Thread,從 Thread 網路中移除:
## FTD Commissioner ## ---------------------- > thread stop Done > ifconfig down Done
兩分鐘內,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
檢查子資料表。請注意,現在有新的 RLOC16。這是 RCP Joiner,如其 ID 和擴充 MAC 所示。為維持 Thread 網路的完整性,它已從 FTD Commissioner 切換至 FTD Joiner,這會導致 RCP Joiner 的 RLOC16 變更 (因為路由器 ID 從 3 變更為 46)。
## FTD Joiner ## ---------------- > child table | ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|S|D|N| Extended MAC | +-----+--------+------------+------------+-------+------+-+-+-+-+------------------+ | 1 | 0xb801 | 240 | 27 | 3 | 145 |1|1|1|1| 1ae529b3a638943b | Done
RCP Joiner 可能需要幾分鐘才能以子項形式附加至 FTD Joiner。檢查狀態和 RLOC16,確認:
## RCP Joiner ## -------------- > state child > rloc16 b801
重新附加 FTD 專員
只有兩個節點的 Thread 網路並不有趣。讓我們讓 FTD 專員恢復連線。
在 FTD 專員上,重新啟動 Thread:
## 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. 疑難排解
在不同終端或螢幕視窗上管理多部裝置的 Thread 網路可能很複雜。如果遇到問題,請使用這些訣竅「重設」網路或工作區的狀態。
螢幕
如果設定過於複雜 (太多 Screen 視窗,或 Screen 視窗內有 Screen 視窗),請使用 Ctrl+a → k 鍵持續終止 Screen 視窗,直到沒有任何視窗為止,且指令列上的 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 位址 | 範圍 | 已送達 |
| 本機連結 | 所有 FTD 和 MED |
| 本機連結 | 所有 FTD 和邊界路由器 |
| 網格本機 | 所有 FTD 和 MED |
| 網格本機 | 所有 FTD 和邊界路由器 |
由於我們在本程式碼研究室中未使用邊界路由器,因此請著重於兩個 FTD 和 MED 多點傳播位址。
本機連結
單一無線電傳輸或單一「躍點」可觸及的所有 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 Joiner 和 RCP Joiner),但 FTD Commissioner 只收到一個回應,來自 FTD Joiner 的 Link-Local Address (LLA)。也就是說,FTD 連結器是 FTD 專員可透過單一躍點連線的唯一裝置。
現在從 FTD Joiner 偵測 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 Joiner 的 LLA。
這表示 FTD Joiner 直接連線至 FTD Commissioner 和 RCP Joiner,確認拓撲。
網格本機
網狀網路本機範圍包含同一 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 Joiner 的路由定位器 (RLOC,結尾為 b800
),另一則來自 RCP Joiner 的網狀區域 EID (ML-EID,結尾為 d55f
)。這是因為網狀區域範圍涵蓋整個 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 Joiner 的回應時間。RCP Joiner 抵達 FTD Commissioner 的時間 (68 毫秒) 比抵達 FTD Joiner 的時間 (23 毫秒) 長得多。這是因為 FTD Commissioner 需要兩次躍點才能連線,FTD Joiner 則只需要一次。
您可能也注意到,網狀網路本機多點傳播連線偵測只會回應兩個 FTD 的 RLOC,不會回應 RCP Joiner。這是因為 FTD 是網路中的路由器,而 RCP 是終端裝置。
檢查 RCP Joiner 的狀態,確認:
## RCP Joiner ## ---------------- > state child
13. 使用 UDP 傳送訊息
OpenThread 提供的一項應用程式服務是使用者資料包通訊協定 (UDP),這是一種傳輸層通訊協定。以 OpenThread 建構的應用程式可以使用 UDP API,在 Thread 網路中的節點之間傳遞訊息,或傳遞至外部網路中的其他裝置 (例如網際網路,前提是 Thread 網路具備邊界路由器)。
UDP 通訊端會透過 OpenThread CLI 公開。我們將使用此介面在兩個 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 Commissioner,啟動 UDP,然後使用 ML-EID 連線至您在 FTD Joiner 上設定的通訊端:
## 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 裝置類型、角色和範圍之間的差異
- Thread 裝置如何管理網路中的狀態
- 如何使用 UDP 在節點之間傳遞簡單訊息
後續步驟
以本程式碼研究室為基礎,嘗試下列練習:
- 使用
ot-cli-mtd
二進位檔將 FTD Joiner 板重新刷為 MTD,並觀察該板是否從未升級為路由器,或嘗試成為領導者 - 在網路上新增更多裝置 (嘗試使用其他平台!),並使用路由器和子項表格,以及對多播位址的 Ping,繪製拓撲圖
- 使用 pyspinel 控制 NCP
- 使用 OpenThread 邊界路由器將 NCP 轉換為邊界路由器,並將 Thread 網路連上網際網路
延伸閱讀
如需各種 OpenThread 資源,請前往 openthread.io 和 GitHub,包括:
- 支援的平台:瞭解支援 OpenThread 的所有平台
- 建構 OpenThread:建構及設定 OpenThread 的詳細資訊
- Thread 基礎知識:涵蓋本程式碼研究室中所有 Thread 概念
參考資料: