1. Giới thiệu
OpenThread do Google phát hành là một cách triển khai nguồn mở của giao thức mạng Thread®. Google Nest đã phát hành OpenThread để cung cấp rộng rãi công nghệ được dùng trong các sản phẩm của Nest cho nhà phát triển nhằm đẩy nhanh quá trình phát triển sản phẩm cho nhà thông minh.
Quy cách Thread xác định một giao thức giao tiếp không dây đáng tin cậy, an toàn và tiêu thụ ít điện năng giữa các thiết bị dựa trên IPv6 cho các ứng dụng gia đình. OpenThread triển khai tất cả các lớp mạng Thread, bao gồm IPv6, 6LoWPAN, IEEE 802.15.4 có tính năng bảo mật MAC, Thiết lập liên kết mạng và Định tuyến mạng.
Trong Lớp học lập trình này, bạn sẽ lập trình OpenThread trên phần cứng thực, tạo và quản lý một mạng Thread, đồng thời truyền thông báo giữa các nút.
Kiến thức bạn sẽ học được
- Tạo và flash các tệp nhị phân OpenThread CLI vào các bảng phát triển
- Xây dựng RCP bao gồm một máy Linux và một bảng phát triển
- Giao tiếp với RCP bằng cách sử dụng OpenThread Daemon và
ot-ctl
- Quản lý các nút Thread theo cách thủ công bằng GNU Screen và OpenThread CLI
- Thiết lập an toàn cho các thiết bị trên mạng Thread
- Cách hoạt động của truyền tin đa hướng IPv6
- Truyền thông báo giữa các nút Luồng bằng UDP
Bạn cần có
Phần cứng:
- 3 bảng phát triển Nordic Semiconductor nRF52840
- 3 cáp USB sang Micro-USB để kết nối các bảng
- Một máy Linux có ít nhất 3 cổng USB
Phần mềm:
- Chuỗi công cụ GNU
- Công cụ dòng lệnh Nordic nRF5x
- Phần mềm Segger J-Link
- OpenThread
- Git
2. Bắt đầu
Mô phỏng OpenThread
Trước khi bắt đầu, bạn có thể xem qua Lớp học lập trình mô phỏng OpenThread để làm quen với các khái niệm cơ bản về Thread và OpenThread CLI.
Thiết bị đầu cuối cổng nối tiếp
Bạn nên nắm rõ cách kết nối với một cổng nối tiếp thông qua một thiết bị đầu cuối. Lớp học lập trình này sử dụng GNU Screen và cung cấp thông tin tổng quan về cách sử dụng, nhưng bạn có thể dùng bất kỳ phần mềm thiết bị đầu cuối nào khác.
Máy Linux
Lớp học lập trình này được thiết kế để sử dụng máy Linux dựa trên i386 hoặc x86 làm máy chủ cho thiết bị Radio Co-Processor (RCP) Thread và để flash tất cả các bảng phát triển Thread. Tất cả các bước đều được kiểm thử trên Ubuntu 14.04.5 LTS (Trusty Tahr).
Bo mạch Nordic Semiconductor nRF52840
Lớp học lập trình này sử dụng 3 bo mạch PDK nRF52840.
Cài đặt SEGGER J-Link
Chúng tôi sử dụng SEGGER J-Link để lập trình các bo mạch nRF52840 có các mô-đun JTAG trên bo mạch. Cài đặt công cụ này trên máy Linux.
Tải gói phù hợp cho máy của bạn xuống rồi cài đặt ở vị trí thích hợp. Trên Linux, đây là /opt/SEGGER/JLink
.
Cài đặt Công cụ dòng lệnh nRF5x
Công cụ dòng lệnh nRF5x cho phép bạn flash các tệp nhị phân OpenThread vào các bo mạch nRF52840. Cài đặt bản dựng nRF5x-Command-Line-Tools-<OS> thích hợp trên máy Linux.
Đặt gói đã giải nén vào thư mục gốc ~/
Cài đặt ARM GNU Toolchain
ARM GNU Toolchain được dùng để tạo.
Bạn nên đặt tệp lưu trữ đã trích xuất vào /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/
trên máy Linux. Làm theo hướng dẫn trong tệp readme.txt
của kho lưu trữ để biết hướng dẫn cài đặt.
Màn hình cài đặt (không bắt buộc)
Screen là một công cụ đơn giản để truy cập vào các thiết bị được kết nối bằng cổng nối tiếp. Lớp học lập trình này sử dụng Screen, nhưng bạn có thể sử dụng bất kỳ ứng dụng đầu cuối cổng nối tiếp nào mà bạn muốn.
$ sudo apt-get install screen
3. Sao chép kho lưu trữ
OpenThread
Sao chép và cài đặt OpenThread. Các lệnh script/bootstrap
đảm bảo rằng chuỗi công cụ được cài đặt và môi trường được định cấu hình đúng cách:
$ mkdir -p ~/src $ cd ~/src $ git clone --recursive https://github.com/openthread/openthread.git $ cd openthread $ ./script/bootstrap
Tạo trình nền OpenThread:
$ script/cmake-build posix -DOT_DAEMON=ON
Giờ đây, bạn đã sẵn sàng tạo và flash OpenThread vào các bảng nRF52840.
4. Thiết lập RCP Joiner
Tạo và flash
Tạo ví dụ OpenThread nRF52840 bằng chức năng Joiner và USB gốc. Thiết bị sử dụng vai trò Joiner để được xác thực và thiết lập một cách an toàn trên mạng Thread. USB gốc cho phép sử dụng USB CDC ACM làm phương thức truyền dữ liệu nối tiếp giữa nRF52840 và máy chủ.
Luôn dọn dẹp kho lưu trữ của các bản dựng trước đó trước bằng cách chạy rm -rf build
.
$ cd ~/src $ git clone --recursive https://github.com/openthread/ot-nrf528xx.git $ cd ot-nrf528xx $ script/build nrf52840 USB_trans
Chuyển đến thư mục có tệp nhị phân RCP OpenThread rồi chuyển đổi tệp đó sang định dạng thập lục phân:
$ cd ~/src/ot-nrf528xx/build/bin $ arm-none-eabi-objcopy -O ihex ot-rcp ot-rcp.hex
Gắn cáp USB vào cổng gỡ lỗi Micro-USB bên cạnh chân nguồn bên ngoài trên bo mạch nRF52840, sau đó cắm cáp này vào máy Linux. Đặt công tắc nRF power source (nguồn điện nRF) trên bảng nRF52840 thành VDD. Khi được kết nối đúng cách, LED5 sẽ bật.
Nếu đây là bảng mạch đầu tiên được gắn vào máy Linux, thì bảng mạch này sẽ xuất hiện dưới dạng cổng nối tiếp /dev/ttyACM0
(tất cả bảng mạch nRF52840 đều sử dụng ttyACM
làm giá trị nhận dạng cổng nối tiếp).
$ ls /dev/ttyACM* /dev/ttyACM0
Ghi lại số sê-ri của bo mạch nRF52840 đang được dùng cho RCP:
Chuyển đến vị trí của Công cụ dòng lệnh nRFx và chuyển tệp hex RCP OpenThread vào bảng nRF52840 bằng số sê-ri của bảng. Xin lưu ý rằng nếu bỏ qua cờ --verify
, bạn sẽ thấy một thông báo cảnh báo cho biết quy trình flash có thể không thành công mà không có lỗi.
$ cd ~/nrfjprog/ $ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \ ~/src/ot-nrf528xx/build/bin/ot-rcp.hex --reset
Kết quả sau đây sẽ được tạo khi thành công:
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.
Gắn nhãn "RCP" cho bảng để sau này bạn không nhầm lẫn các vai trò của bảng.
Kết nối với USB gốc
Vì bản dựng RCP OpenThread cho phép sử dụng USB CDC ACM gốc làm phương thức truyền dữ liệu nối tiếp, nên bạn phải sử dụng cổng nRF USB trên bo mạch nRF52840 để giao tiếp với máy chủ RCP (máy Linux).
Tháo đầu Micro-USB của cáp USB khỏi cổng gỡ lỗi của bo mạch nRF52840 đã được flash, sau đó gắn lại vào cổng Micro-USB nRF USB bên cạnh nút RESET. Đặt công tắc nguồn nRF thành USB.
Khởi động trình nền OpenThread
Trong thiết kế RCP, hãy sử dụng OpenThread Daemon để giao tiếp và quản lý thiết bị Thread. Bắt đầu ot-daemon
bằng cờ -v
chi tiết để bạn có thể xem đầu ra nhật ký và xác nhận rằng nó đang chạy:
$ cd ~/src/openthread $ sudo ./build/posix/src/posix/ot-daemon -v \ 'spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800'
Khi thành công, ot-daemon
ở chế độ chi tiết sẽ tạo ra kết quả tương tự như sau:
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
Hãy để cửa sổ dòng lệnh này mở để bạn có thể xem nhật ký từ ot-daemon
.
Sử dụng ot-ctl
để giao tiếp với nút RCP. ot-ctl
sử dụng cùng một CLI như ứng dụng OpenThread CLI. Do đó, bạn có thể kiểm soát các nút ot-daemon
theo cách tương tự như các thiết bị Thread mô phỏng khác.
Trong cửa sổ dòng lệnh thứ hai, hãy bắt đầu ot-ctl
:
$ sudo ./build/posix/src/posix/ot-ctl >
Kiểm tra state
của Node 2 (nút RCP) mà bạn đã bắt đầu bằng ot-daemon
:
> state disabled Done
5. Thiết lập FTD
Hai nút Thread còn lại được dùng trong Lớp học lập trình này là Thiết bị Thread đầy đủ (FTD) theo thiết kế tiêu chuẩn của Hệ thống trên vi mạch (SoC). Một thiết bị sẽ đóng vai trò là Người uỷ quyền để xác thực và uỷ quyền các thiết bị vào mạng đó một cách an toàn. Thiết bị còn lại hoạt động như một Thiết bị tham gia mà Người uỷ quyền có thể xác thực với mạng Thread.
Tạo và flash
Tạo ví dụ FTD OpenThread cho nền tảng nRF52840, với vai trò Commissioner và Joiner được bật:
$ cd ~/src/ot-nrf528xx $ rm -rf build $ script/build nrf52840 USB_trans -DOT_JOINER=ON -DOT_COMMISSIONER=ON
Chuyển đến thư mục có tệp nhị phân CLI của Thiết bị OpenThread Full Thread (FTD) và chuyển đổi tệp đó sang định dạng thập lục phân:
$ cd ~/src/ot-nrf528xx/build/bin $ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex
Gắn cáp USB vào cổng Micro-USB bên cạnh chân nguồn bên ngoài trên bo mạch nRF52840, sau đó cắm cáp này vào máy Linux. Nếu RCP vẫn được gắn vào máy Linux, thì bo mạch mới này sẽ xuất hiện dưới dạng cổng nối tiếp /dev/ttyACM1
(tất cả các bo mạch nRF52840 đều sử dụng ttyACM
cho giá trị nhận dạng cổng nối tiếp).
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1
Như trước đây, hãy ghi lại số sê-ri của bo mạch nRF52840 đang được dùng cho FTD:
Chuyển đến vị trí của nRFx Command Line Tools (Công cụ dòng lệnh nRFx) rồi chuyển tệp hex OpenThread CLI FTD vào bo mạch nRF52840 bằng số sê-ri của bo mạch:
$ cd ~/nrfjprog/ $ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \ ~/src/ot-nrf528xx/build/bin/ot-cli-ftd.hex --reset
Đặt tên cho bảng là "Uỷ viên".
Kết nối với USB gốc
Vì bản dựng OpenThread FTD cho phép sử dụng USB CDC ACM gốc làm phương thức truyền dữ liệu nối tiếp, nên bạn phải sử dụng cổng nRF USB trên bo mạch nRF52840 để giao tiếp với máy chủ RCP (máy Linux).
Tháo đầu Micro-USB của cáp USB khỏi cổng gỡ lỗi của bo mạch nRF52840 đã được flash, sau đó gắn lại vào cổng Micro-USB nRF USB bên cạnh nút RESET. Đặt công tắc nguồn nRF thành USB.
Xác minh bản dựng
Xác minh bản dựng thành công bằng cách truy cập vào OpenThread CLI bằng GNU Screen từ cửa sổ dòng lệnh.
$ screen /dev/ttyACM1
Trong cửa sổ mới, hãy nhấn phím Return trên bàn phím vài lần để hiển thị lời nhắc OpenThread CLI >
. Đưa giao diện IPv6 lên và kiểm tra địa chỉ:
> ifconfig up Done > ipaddr fe80:0:0:0:1cd6:87a9:cb9d:4b1d Done
Sử dụng Ctrl+a →
d
để tách khỏi màn hình FTD Commissioner CLI và quay lại cửa sổ dòng lệnh Linux để có thể nạp chương trình cho bảng tiếp theo. Để nhập lại CLI bất cứ lúc nào, hãy dùng screen -r
qua dòng lệnh. Để xem danh sách các màn hình có sẵn, hãy dùng lệnh screen -ls
:
$ screen -ls There is a screen on: 74182.ttys000.mylinuxmachine (Detached) 1 Socket in /tmp/uscreens/S-username.
Thiết lập FTD Joiner
Lặp lại quy trình trên để nạp chương trình cho bo mạch nRF52840 thứ ba bằng bản dựng ot-cli-ftd.hex
hiện có. Khi hoàn tất, hãy nhớ kết nối lại bo mạch với máy tính bằng cổng USB nRF và đặt công tắc nguồn nRF thành VDD.
Nếu 2 nút còn lại được gắn vào máy Linux khi bảng thứ ba này được gắn, thì bảng này sẽ xuất hiện dưới dạng cổng nối tiếp /dev/ttyACM2
:
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1 /dev/ttyACM2
Đặt tên cho bảng là "Joiner".
Khi xác minh bằng Screen, thay vì tạo một phiên bản Screen mới từ dòng lệnh, hãy đính kèm lại vào phiên bản hiện có và tạo một cửa sổ mới trong đó (cửa sổ mà bạn đã dùng cho FTD Commissioner):
$ screen -r
Tạo cửa sổ mới trong Screen bằng tổ hợp phím Ctrl+a → c
.
Một dấu nhắc dòng lệnh mới sẽ xuất hiện. Truy cập vào OpenThread CLI cho FTD Joiner:
$ screen /dev/ttyACM2
Trong cửa sổ mới này, hãy nhấn phím Return trên bàn phím vài lần để hiển thị lời nhắc >
OpenThread CLI. Đưa giao diện IPv6 lên và kiểm tra địa chỉ:
> ifconfig up Done > ipaddr fe80:0:0:0:6c1e:87a2:df05:c240 Done
Giờ đây, vì FTD Joiner CLI nằm trong cùng một phiên bản Màn hình với FTD Commissioner, nên bạn có thể chuyển đổi giữa chúng bằng cách sử dụng Ctrl+a → n
.
Sử dụng Ctrl+a →
d
bất cứ lúc nào để thoát khỏi Screen.
6. Thiết lập cửa sổ dòng lệnh
Sau này, bạn sẽ thường xuyên chuyển đổi giữa các thiết bị Thread, vì vậy, hãy đảm bảo tất cả các thiết bị đều đang hoạt động và dễ dàng truy cập. Cho đến nay, chúng ta đã sử dụng Screen để truy cập vào hai FTD và công cụ này cũng cho phép chia đôi màn hình trên cùng một cửa sổ thiết bị đầu cuối. Sử dụng tính năng này để xem cách một nút phản ứng với các lệnh được đưa ra trên một nút khác.
Tốt nhất là bạn nên có sẵn 4 cửa sổ:
ot-daemon
dịch vụ / nhật ký- RCP Joiner qua
ot-ctl
- FTD Commissioner thông qua OpenThread CLI
- FTD Joiner thông qua OpenThread CLI
Nếu bạn muốn sử dụng cấu hình hoặc công cụ cổng nối tiếp / thiết bị đầu cuối của riêng mình, hãy chuyển sang bước tiếp theo. Định cấu hình cửa sổ thiết bị đầu cuối cho tất cả thiết bị theo cách phù hợp nhất với bạn.
Sử dụng màn hình
Để dễ sử dụng, bạn chỉ nên bắt đầu một phiên Screen. Bạn đã có một FTD khi thiết lập cả hai FTD.
Tất cả các lệnh trong Screen đều bắt đầu bằng Ctrl+a.
Các lệnh cơ bản trên màn hình:
Đính kèm lại vào phiên Screen (từ dòng lệnh) |
|
Rời khỏi phiên Screen | Ctrl+a → |
Tạo cửa sổ mới trong phiên Màn hình | Ctrl+a → |
Chuyển đổi giữa các cửa sổ trong cùng một phiên Chia sẻ màn hình | Ctrl+a → |
Đóng cửa sổ hiện tại trong phiên Screen | Ctrl+a → |
Chia đôi màn hình
Với Screen, bạn có thể chia thiết bị đầu cuối thành nhiều cửa sổ:
Bạn có thể truy cập các lệnh trong screen
bằng cách nhấn tổ hợp phím Ctrl+a. Mọi lệnh đều phải bắt đầu bằng tổ hợp phím truy cập này.
Nếu đã làm theo chính xác Lớp học lập trình này, bạn sẽ có 2 cửa sổ (FTD Commissioner, FTD Joiner) trên cùng một phiên bản Màn hình. Để chia đôi màn hình giữa hai phiên, trước tiên, hãy nhập phiên Screen hiện có:
$ screen -r
Bạn nên dùng một trong các thiết bị FTD. Làm theo các bước sau trong Screen:
- Ctrl+a →
S
để chia cửa sổ theo chiều ngang - Ctrl+a →
Tab
để di chuyển con trỏ đến cửa sổ trống mới - Ctrl+a →
n
để chuyển cửa sổ mới đó sang cửa sổ tiếp theo - Nếu đó là cửa sổ trên cùng, hãy nhấn Ctrl+a →
n
một lần nữa để xem thiết bị FTD khác
Cả hai đều xuất hiện. Chuyển đổi giữa các chế độ bằng cách nhấn Ctrl+a → Tab
. Bạn nên đổi tên từng cửa sổ bằng tổ hợp phím Ctrl+a → A
để tránh nhầm lẫn.
Cách sử dụng nâng cao
Để chia màn hình thành các phần tư và xem nhật ký ot-daemon
cũng như ot-ctl
RCP Joiner, bạn phải khởi động các dịch vụ đó trong cùng một phiên bản Màn hình này. Để làm như vậy, hãy dừng ot-daemon
và thoát ot-ctl
, rồi khởi động lại trong các cửa sổ Screen mới (Ctrl+a → c
).
Người dùng không bắt buộc phải thiết lập và có thể tự thực hiện.
Chia và di chuyển giữa các cửa sổ bằng các lệnh sau:
Tạo cửa sổ mới | Ctrl+a → |
Chia cửa sổ theo chiều dọc | Ctrl+a → |
Chia cửa sổ theo chiều ngang | Ctrl+a → |
Chuyển đến cửa sổ tiếp theo xuất hiện | Ctrl+a → |
Chuyển cửa sổ hiển thị về phía trước hoặc phía sau | Ctrl+a → |
Đổi tên cửa sổ hiện tại | Ctrl+a → |
Thoát khỏi Screen bất cứ lúc nào bằng tổ hợp phím Ctrl+a → d
và đính kèm lại bằng tổ hợp phím screen -r
từ dòng lệnh.
Để biết thêm thông tin về Screen, hãy xem tài liệu tham khảo nhanh về GNU Screen.
7. Tạo mạng Thread
Giờ đây, khi bạn đã định cấu hình tất cả các cửa sổ và màn hình của thiết bị đầu cuối, hãy tạo mạng Thread. Trên Uỷ viên FTD, hãy tạo một Tập dữ liệu hoạt động mới và xác nhận đó là tập dữ liệu đang hoạt động. Tập dữ liệu hoạt động là cấu hình cho mạng Thread mà bạn đang tạo.
## 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
Ghi lại Khoá mạng 1234c0de7ab51234c0de7ab51234c0de
mà bạn sẽ dùng sau này.
Xác nhận tập dữ liệu này là tập dữ liệu đang hoạt động:
> dataset commit active Done
Đưa giao diện IPv6 lên:
> ifconfig up Done
Bắt đầu thao tác giao thức Thread:
> thread start Done
Sau một lát, hãy kiểm tra trạng thái thiết bị. Đó phải là Nhà lãnh đạo. Ngoài ra, hãy lấy RLOC16 để tham khảo sau này.
## FTD Commissioner ## ---------------------- > state leader Done > rloc16 0c00 Done
Kiểm tra địa chỉ IPv6 của thiết bị:
## 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)
Mạng "codelab" hiện có thể thấy khi quét từ các thiết bị Thread khác.
Từ ot-ctl
trên RCP Joiner (Công cụ kết hợp RCP):
## RCP Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -36 | 232 |
Từ OpenThread CLI trên FTD Joiner:
## FTD Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -38 | 229 |
Nếu mạng "codelab" không xuất hiện trong danh sách, hãy thử quét lại.
8. Thêm RCP Joiner
Quy trình thiết lập Thread không hoạt động trên mạng. Điều này có nghĩa là chúng ta cần thêm RCP Joiner vào mạng Thread mà chúng ta vừa tạo bằng quy trình thiết lập ngoài băng tần.
Trên FTD Commissioner (Uỷ viên FTD), chúng ta ghi lại Network Key (Khoá mạng), ví dụ: 1234c0de7ab51234c0de7ab51234c0de
. Nếu bạn cần tra cứu lại Khoá mạng, hãy chạy lệnh sau trên FTD Commissioner:
## FTD Commissioner ## > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done
Tiếp theo, trên RCP Joiner, hãy đặt Khoá mạng tập dữ liệu đang hoạt động thành Khoá mạng của Uỷ viên FTD:
## RCP Joiner ## ---------------- > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done > dataset commit active Done
Kiểm tra tập dữ liệu để đảm bảo bạn đã đặt đúng.
## RCP Joiner ## ---------------- > dataset Network Key: 1234c0de7ab51234c0de7ab51234c0de
Đưa Thread lên để RCP Joiner tham gia mạng "codelab". Chờ vài giây, kiểm tra trạng thái, RLOC16 và địa chỉ IPv6 của nó:
## 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
Ghi lại Địa chỉ IPv6 cục bộ của mạng lưới (fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f
ở đây), bạn sẽ sử dụng địa chỉ này sau.
Trên FTD Commissioner, hãy kiểm tra bộ định tuyến và các bảng con để xác nhận rằng cả hai thiết bị đều thuộc cùng một mạng. Sử dụng RLOC16 để xác định 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 địa chỉ cục bộ của RCP Joiner (địa chỉ cục bộ của mạng lưới lấy từ đầu ra ipaddr
của RCP Joiner) để xác minh khả năng kết nối:
## 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
Giờ đây, chúng ta có một mạng Thread gồm 2 nút, được minh hoạ bằng sơ đồ cấu trúc liên kết này:
Sơ đồ cấu trúc liên kết
Khi bạn thực hiện phần còn lại của Lớp học lập trình, chúng tôi sẽ cho thấy một sơ đồ cấu trúc liên kết Thread mới bất cứ khi nào trạng thái của mạng thay đổi. Các vai trò của nút được biểu thị như sau:
Bộ định tuyến luôn là hình ngũ giác và Thiết bị đầu cuối luôn là hình tròn. Các con số trên mỗi nút đại diện cho Mã nhận dạng bộ định tuyến hoặc Mã nhận dạng con xuất hiện trong đầu ra CLI, tuỳ thuộc vào vai trò và trạng thái hiện tại của mỗi nút tại thời điểm đó.
9. Uỷ quyền cho FTD Joiner
Bây giờ, hãy thêm thiết bị Thread thứ ba vào mạng "codelab". Lần này, chúng ta sẽ sử dụng quy trình thiết lập an toàn hơn trong băng tần và chỉ cho phép FTD Joiner tham gia.
Trên FTD Joiner, hãy lấy eui64
để Uỷ viên FTD có thể xác định được:
## FTD Joiner ## ---------------- > eui64 2f57d222545271f1 Done
Trên FTD Commissioner, hãy khởi động commissioner và chỉ định eui64
của thiết bị có thể tham gia, cùng với Joiner Credential, ví dụ: J01NME
. Thông tin đăng nhập của thiết bị kết nối là một chuỗi gồm các ký tự chữ và số viết hoa (0-9 và A-Y, không bao gồm I, O, Q và Z để dễ đọc), có độ dài từ 6 đến 32 ký tự.
## FTD Commissioner ## ---------------------- > commissioner start Done > commissioner joiner add 2f57d222545271f1 J01NME Done
Chuyển sang FTD Joiner (Công cụ kết nối FTD). Bắt đầu vai trò của thiết bị kết nối bằng Thông tin xác thực của thiết bị kết nối mà bạn vừa thiết lập trên FTD Commissioner:
## FTD Joiner ## ---------------- > ifconfig up Done > joiner start J01NME Done
Trong vòng khoảng một phút, bạn sẽ nhận được thông báo xác nhận xác thực thành công:
## FTD Joiner ## ---------------- > Join success
Đưa Thread lên để FTD Joiner tham gia mạng "codelab", rồi kiểm tra ngay trạng thái và RLOC16:
## FTD Joiner ## ---------------- > thread start Done > state child Done > rloc16 0c02 Done
Kiểm tra địa chỉ IPv6 của thiết bị. Xin lưu ý rằng không có ALOC. Lý do là vì thiết bị này không phải là Thiết bị chính và cũng không giữ vai trò dành riêng cho Anycast yêu cầu 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)
Chuyển ngay sang FTD Commissioner (Uỷ viên FTD) rồi kiểm tra bộ định tuyến và các bảng con để xác nhận rằng có 3 thiết bị trong mạng "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
Dựa trên RLOC16, FTD Joiner đã kết nối với mạng dưới dạng Thiết bị đầu cuối (thiết bị con). Sau đây là cấu trúc liên kết mới của chúng tôi:
10. Chuỗi cuộc trò chuyện trong thực tế
Các thiết bị Thread trong Lớp học lập trình này là một loại Thiết bị Thread đầy đủ (FTD) cụ thể, được gọi là Thiết bị cuối đủ điều kiện làm bộ định tuyến (REED). Điều này có nghĩa là chúng có thể hoạt động như một Bộ định tuyến hoặc Thiết bị cuối và có thể tự nâng cấp từ Thiết bị cuối lên Bộ định tuyến.
Thread có thể hỗ trợ tối đa 32 Bộ định tuyến, nhưng cố gắng duy trì số lượng Bộ định tuyến trong khoảng từ 16 đến 23. Nếu REED kết nối với tư cách là Thiết bị đầu cuối (thiết bị con) và số lượng Bộ định tuyến dưới 16, thì sau một khoảng thời gian ngẫu nhiên trong vòng 2 phút, thiết bị này sẽ tự động nâng cấp lên Bộ định tuyến.
Nếu bạn có 2 thiết bị con trong mạng Thread sau khi thêm FTD Joiner, hãy đợi ít nhất 2 phút, sau đó kiểm tra lại bảng bộ định tuyến và bảng thiết bị con trên 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 mở rộng = e6cdd2d93249a243
) đã tự thăng cấp thành Bộ định tuyến. Xin lưu ý rằng RLOC16 khác (b800
thay vì 0c02
). Đó là vì RLOC16 dựa trên Router ID và Child ID của một thiết bị. Khi chuyển từ Thiết bị cuối sang Bộ định tuyến, giá trị Mã bộ định tuyến và Mã thiết bị con sẽ thay đổi, cũng như RLOC16.
Xác nhận trạng thái mới và RLOC16 trên FTD Joiner:
## FTD Joiner ## ---------------- > state router Done > rloc16 b800 Done
Hạ cấp FTD Joiner
Bạn có thể kiểm thử hành vi này bằng cách hạ cấp FTD Joiner theo cách thủ công từ Router xuống End Device. Thay đổi trạng thái thành trẻ em và kiểm tra RLOC16:
## FTD Joiner ## ---------------- > state child Done > rloc16 0c03 Done
Quay lại FTD Commissioner, FTD Joiner hiện sẽ xuất hiện trong bảng con (ID = 3). Thậm chí, có thể ảnh/video sẽ xuất hiện ở cả hai nơi trong quá trình chuyển:
## 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
Sau một thời gian, nó sẽ chuyển về Bộ định tuyến có RLOC là b800
.
Xoá người lãnh đạo
Leader được chọn trong số tất cả các Bộ định tuyến luồng. Điều này có nghĩa là nếu Bộ định tuyến chính hiện tại bị xoá khỏi mạng Thread, thì một trong các Bộ định tuyến khác sẽ trở thành Bộ định tuyến chính mới.
Trên FTD Commissioner, hãy tắt Thread để xoá Thread khỏi mạng Thread:
## FTD Commissioner ## ---------------------- > thread stop Done > ifconfig down Done
Trong vòng 2 phút, FTD Joiner sẽ trở thành thiết bị dẫn đầu Thread mới. Kiểm tra trạng thái và địa chỉ IPv6 của FTD Joiner để xác minh:
## 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
Kiểm tra bảng con. Lưu ý rằng có một RLOC16 mới. Đây là RCP Joiner, như được chỉ ra bằng mã nhận dạng và MAC mở rộng. Để giữ cho mạng Thread hoạt động cùng nhau, RCP Joiner đã chuyển đổi các Bộ định tuyến mẹ, từ FTD Commissioner sang FTD Joiner. Điều này dẫn đến một RLOC16 mới cho RCP Joiner (vì Router ID của nó đã thay đổi, từ 3 thành 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
Bạn có thể phải đợi vài phút để RCP Joiner gắn vào FTD Joiner dưới dạng một phần tử con. Kiểm tra trạng thái và RLOC16 để xác nhận rằng:
## RCP Joiner ## -------------- > state child > rloc16 b801
Đính kèm lại FTD Commissioner
Mạng Thread có 2 nút không thú vị lắm. Hãy đưa Uỷ viên FTD trở lại trực tuyến.
Trên FTD Commissioner, hãy khởi động lại Thread:
## FTD Commissioner ## ---------------------- > ifconfig up Done > thread start Done
Trong vòng 2 phút, thiết bị này sẽ tự động kết nối lại với mạng "codelab" dưới dạng một Thiết bị đầu cuối, sau đó tự nâng cấp lên Bộ định tuyến.
## FTD Commissioner ## ---------------------- > state router Done
Kiểm tra bộ định tuyến và các bảng con trên FTD Joiner để xác minh:
## 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
Mạng Thread của chúng tôi lại có 3 nút.
11. Khắc phục sự cố
Việc quản lý mạng Thread có nhiều thiết bị trên các cửa sổ màn hình hoặc thiết bị đầu cuối khác nhau có thể phức tạp. Hãy sử dụng các mẹo này để "đặt lại" trạng thái của mạng hoặc không gian làm việc nếu bạn gặp vấn đề.
Màn hình
Nếu bạn bị lạc trong cấu hình (quá nhiều cửa sổ Screen hoặc Screen trong Screen), hãy tiếp tục đóng các cửa sổ Screen bằng tổ hợp phím Ctrl+a → k cho đến khi không còn cửa sổ nào và screen -ls
trên dòng lệnh xuất ra No Sockets found
. Sau đó, tạo lại các cửa sổ Màn hình cho từng thiết bị. Trạng thái thiết bị được giữ nguyên ngay cả khi Màn hình bị tắt.
Nút Thread
Nếu cấu trúc liên kết mạng Thread không như mô tả trong Lớp học lập trình này hoặc các nút bị ngắt kết nối vì lý do nào đó (có thể là do máy Linux cung cấp năng lượng cho các nút chuyển sang chế độ ngủ), thì tốt nhất là bạn nên tắt Thread, xoá thông tin đăng nhập mạng và bắt đầu lại từ bước Tạo mạng Thread.
Cách đặt lại FTD:
## FTD Commissioner or FTD Joiner ## ------------------------------------ > thread stop Done > ifconfig down Done > factoryreset Done
Bạn có thể đặt lại RCP theo cách tương tự thông qua ot-ctl
:
## RCP Joiner ## ---------------- > thread stop Done > ifconfig down Done > factoryreset Done
12. Sử dụng truyền tin đa hướng
Truyền tin đa hướng được dùng để truyền thông tin đến một nhóm thiết bị cùng một lúc. Trong mạng Thread, các địa chỉ cụ thể được dành riêng cho việc sử dụng truyền tin đa hướng với các nhóm thiết bị khác nhau, tuỳ thuộc vào phạm vi.
Địa chỉ IPv6 | Phạm vi | Đã giao cho |
| Link-Local | Tất cả FTD và MED |
| Link-Local | Tất cả FTD và Bộ định tuyến biên |
| Mesh-Local | Tất cả FTD và MED |
| Mesh-Local | Tất cả FTD và Bộ định tuyến biên |
Vì chúng ta không sử dụng Bộ định tuyến biên trong Lớp học lập trình này, nên hãy tập trung vào 2 địa chỉ truyền tin đa hướng FTD và MED.
Link-Local
Phạm vi Liên kết cục bộ bao gồm tất cả các giao diện Thread mà một lần truyền vô tuyến hoặc một "bước nhảy" có thể tiếp cận được. Cấu trúc liên kết mạng quy định những thiết bị nào phản hồi lệnh ping đến địa chỉ đa hướng ff02::1
.
Ping ff02::1
của Uỷ viên FTD:
## FTD Commissioner ## ---------------------- > ping ff02::1 > 8 bytes from fe80:0:0:0:e4cd:d2d9:3249:a243: icmp_seq=2 hlim=64 time=9ms
Có 2 thiết bị khác trong mạng (FTD Joiner và RCP Joiner), nhưng FTD Commissioner chỉ nhận được một phản hồi, từ Địa chỉ cục bộ liên kết (LLA) của FTD Joiner. Điều này có nghĩa là FTD Joiner là thiết bị duy nhất mà FTD Commissioner có thể tiếp cận bằng một bước nhảy.
Giờ đây, hãy ping ff02::1
từ FTD Joiner:
## 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
Hai câu trả lời! Khi kiểm tra địa chỉ IPv6 của các thiết bị khác, chúng ta có thể thấy địa chỉ đầu tiên (kết thúc bằng 4b1d
) là LLA của FTD Commissioner và địa chỉ thứ hai (kết thúc bằng 943b
) là LLA của RCP Joiner.
Điều này có nghĩa là FTD Joiner được kết nối trực tiếp với cả FTD Commissioner và RCP Joiner, giúp xác nhận cấu trúc liên kết của chúng ta.
Mesh-Local
Phạm vi Mesh-Local bao gồm tất cả các giao diện Thread có thể truy cập trong cùng một mạng Thread. Hãy xem các phản hồi cho một lệnh ping đến địa chỉ truyền tin ff03::1
.
Ping ff03::1
của Uỷ viên FTD:
## 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
Lần này, Uỷ viên FTD nhận được hai phản hồi, một từ Bộ định vị tuyến đường (RLOC, kết thúc bằng b800
) của FTD Joiner và một từ EID cục bộ theo mạng lưới (ML-EID, kết thúc bằng d55f
) của RCP Joiner. Đó là do phạm vi cục bộ theo mạng lưới bao gồm toàn bộ mạng Thread. Dù ở đâu trong mạng, thiết bị sẽ được đăng ký địa chỉ ff03::1
.
Ping ff03::1
từ FTD Joiner để xác nhận hành vi tương tự:
## 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
Lưu ý thời gian phản hồi của RCP Joiner trong cả hai đầu ra ping. RCP Joiner mất nhiều thời gian hơn để kết nối với FTD Commissioner (68 mili giây) so với FTD Joiner (23 mili giây). Đó là vì nó phải thực hiện 2 bước để tiếp cận Uỷ viên FTD, so với 1 bước đối với FTD Joiner.
Bạn cũng có thể nhận thấy rằng lệnh ping truyền tin đa hướng cục bộ trong mạng lưới chỉ phản hồi bằng RLOC cho 2 FTD, chứ không phải RCP Joiner. Điều này là do FTD là Bộ định tuyến trong mạng, trong khi RCP là Thiết bị đầu cuối.
Kiểm tra trạng thái của RCP Joiner để xác nhận:
## RCP Joiner ## ---------------- > state child
13. Gửi thông báo bằng UDP
Một trong các dịch vụ ứng dụng mà OpenThread cung cấp là Giao thức dữ liệu người dùng (UDP), một giao thức Tầng truyền tải. Một ứng dụng được xây dựng trên OpenThread có thể sử dụng UDP API để truyền thông báo giữa các nút trong mạng Thread hoặc đến các thiết bị khác trong mạng bên ngoài (chẳng hạn như Internet, nếu mạng Thread có Bộ định tuyến biên).
Các socket UDP được hiển thị thông qua OpenThread CLI. Hãy dùng nó để truyền thông báo giữa hai FTD.
Lấy địa chỉ EID Mesh-Local cho FTD Joiner. Chúng tôi sử dụng địa chỉ này vì có thể truy cập từ mọi nơi trong mạng 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
Khởi động UDP và liên kết UDP với một ổ cắm cho mọi địa chỉ IPv6:
## FTD Joiner ## ---------------- > udp open Done > udp bind :: 1212
Chuyển sang FTD Commissioner, khởi động UDP và kết nối với ổ cắm mà bạn thiết lập trên FTD Joiner bằng ML-EID của ổ cắm đó:
## FTD Commissioner ## ---------------------- > udp open Done > udp connect fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd 1212 Done
Kết nối UDP phải hoạt động giữa hai nút. Gửi thông điệp của Uỷ viên FTD:
## FTD Commissioner ## ---------------------- > udp send hellothere Done
Trên FTD Joiner, thông báo UDP đã được nhận!
## FTD Joiner ## ---------------- > 10 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:c00 49153 hellothere
14. Xin chúc mừng!
Bạn đã tạo một mạng Thread thực!
Giờ thì bạn đã biết:
- sự khác biệt giữa các loại, vai trò và phạm vi thiết bị Thread
- cách các thiết bị Thread quản lý trạng thái của chúng trong mạng
- cách truyền các thông báo đơn giản giữa các nút bằng UDP
Các bước tiếp theo
Dựa trên Lớp học lập trình này, hãy thử các bài tập sau:
- Nạp lại chương trình trên bo mạch FTD Joiner dưới dạng MTD bằng tệp nhị phân
ot-cli-mtd
và quan sát thấy bo mạch này không bao giờ tự nâng cấp lên Bộ định tuyến hoặc cố gắng trở thành Trưởng nhóm - Thêm nhiều thiết bị hơn (thử một nền tảng khác!) vào mạng và phác thảo cấu trúc liên kết bằng cách sử dụng các bảng bộ định tuyến và bảng con, cùng với các lệnh ping đến địa chỉ truyền tin đa hướng
- Sử dụng pyspinel để điều khiển NCP
- Chuyển đổi NCP thành Bộ định tuyến biên bằng Bộ định tuyến biên OpenThread và kết nối mạng Thread với Internet
Tài liệu đọc thêm
Hãy xem openthread.io và GitHub để biết nhiều tài nguyên về OpenThread, bao gồm:
- Nền tảng được hỗ trợ – khám phá tất cả các nền tảng hỗ trợ OpenThread
- Tạo OpenThread – thông tin chi tiết hơn về cách tạo và định cấu hình OpenThread
- Thread Primer – bao gồm tất cả các khái niệm về Thread có trong Lớp học lập trình này
Tài liệu tham khảo: