使用 B91 开发板和 OpenThread 构建 Thread 网络

1. 简介

26b7f4f6b3ea0700.png

OpenThreadThread® 网络协议的开源实现,该协议是一种可靠且安全的无线网状网络协议,专为物联网 (IoT) 设备而设计。OpenThread 由 Google 的 Nest 团队开发,并以开源项目的形式免费提供给开发者社区。

Thread 规范为智能家居和商业建筑中常见的资源受限设备建立了一种可靠、安全且节能的无线通信协议。OpenThread 包含 Thread 中的完整网络层范围,例如 IPv6、6LoWPAN、具有 MAC 安全性的 IEEE 802.15.4、网状链路建立和网状路由。

Telink 已将 OpenThread 实现集成到 Zephyr RTOS 中,从而实现与 Telink 硬件的无缝兼容。您可以在 GitHub 上轻松获取此集成的源代码,该源代码还以软件开发套件 (SDK) 的形式提供。

在此 Codelab 中,您将在实际硬件上对 OpenThread 进行编程,创建和管理 Thread 网络,并在节点之间交换消息。下图展示了实验中的硬件设置,包括一个 OT 边界路由器 (OTBR) 和一个 Thread 设备。

codelab_overview.png

学习内容

  • 使用 Telink Zephyr 开发环境设置 OpenThread 实现。
  • 构建 OpenThread CLI 示例(ot-cli-ftdot-rcp)并将其刷写到 Telink B91 开发板上。
  • 在 Raspberry Pi 3B+ 或更高版本上使用 Docker 设置 OpenThread 边界路由器 (OTBR)。
  • 在 OTBR 上创建 Thread 网络。
  • 使用带外调试将设备添加到 Thread 网络。
  • 使用 CLI 验证 Thread 网络中节点之间的连接。

所需条件

硬件:

  • 两块 B91 开发板。
  • 一台 Raspberry Pi 3B+ 或更高版本,并安装 Raspbian 操作系统映像。
  • 一台具有至少两个 USB 端口的 Linux 机器。
  • 已连接到互联网的交换机(或路由器)和多根以太网网线。

软件:

  • Telink 烧写和调试工具 —— LinuxBDT。
  • 串行端口终端工具,例如 PuTTY。
  • 其他工具,例如 Git 和 West。

2. 前提条件

Thread 概念和 OpenThread CLI

在学习本 Codelab 之前,建议您先学习 OpenThread 模拟 Codelab,以便熟悉基本的 Thread 概念和 OpenThread CLI。

Linux 机器

Linux 机器(Ubuntu v20.04 LTS 或更高版本)充当 build 机器,用于设置 Telink Zephyr 开发环境并刷写所有 Thread 开发板。若要完成这些任务,Linux 机器需要有两个可用的 USB 端口并连接到互联网。

串行端口连接和终端

您可以将设备直接插入 Linux 机器的 USB 端口。此外,您还需要一个串行端口终端工具来访问设备。

在此 Codelab 中,终端工具 PuTTY 用于控制 FTD Joiner 和 Raspberry Pi。它提供了使用情况概览,但您也可以使用其他终端软件。

此 Codelab 需要两套 B91 开发套件。下图显示了一组必需的最少组件。

overview.png

其中一个套件将用作 RCP(无线电协处理器),而另一个将用作 FTD(完整 Thread 设备)。如果您尚未获得该套件,可以访问 Telink 官方网站了解更多详情。以下是一些要使用的组件:

索引

名称

1

Telink B91 开发板

2

Telink 烧写板

3

2.4Ghz 天线

4

USB 线(USB A 转 mini USB)

Raspberry Pi 3B+ 或更高版本,并使用 Raspbian 操作系统映像

在此 Codelab 中,您需要使用 Raspberry Pi 3B+ 或更高版本,并安装 Raspbian Bullseye Lite 操作系统映像Raspbian Bullseye with Desktop。它通过以太网连接到互联网,并将配置为 OpenThread 边界路由器 (OTBR) 的主机。

网络连接

已连接到互联网的交换机(或路由器)和多根以太网网线。它们用于将 Raspberry Pi 连接到 Linux 机器,从而方便用户通过主机配置 Raspberry Pi。

LinuxBDT

Telink Burning and Debugging Tool (BDT) 适用于所有 Telink 芯片系列,可让您将 OpenThread 固件擦除并刷写到 Telink B91 开发板上。在 Linux 机器上安装基于 X86 的 Linux 版本 linuxBDT

其他

  • Git,用于设置 Telink Zephyr 开发环境。
  • West,用于管理 Zephyr 项目和构建 OpenThread 二进制文件。

3. 设置固件

在 Linux 计算机上,打开 CLI 终端,然后先执行以下命令,确保 APT 是最新版本。

$ sudo apt update
$ sudo apt upgrade

完成后,继续执行以下步骤。

  1. 安装依赖项。
    $ wget https://apt.kitware.com/kitware-archive.sh
    $ sudo bash kitware-archive.sh
    $ sudo apt install --no-install-recommends git cmake ninja-build \
    gperf ccache dfu-util device-tree-compiler python3-dev python3-pip \
    python3-setuptools python3-tk python3-wheel xz-utils file make gcc \
    gcc-multilib g++-multilib libsdl2-dev
    
    Zephyr 目前要求主要依赖项(例如 CMake [3.20.0]、Python3 [3.6] 和 Devicetree 编译器 [1.4.6])的最低版本。
    $ cmake --version
    $ python3 --version
    $ dtc --version
    
    在继续执行后续步骤之前,请验证系统上安装的版本。如果版本不正确,请将 APT 镜像切换为稳定且最新的镜像,或手动更新这些依赖项。
  2. 安装 west。
    $ pip3 install --user -U west
    $ echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
    $ source ~/.bashrc
    
    确保 ~/.local/bin 位于 $PATH 环境变量中。
  3. 获取 Zephyr 项目源代码。
    $ west init ~/zephyrproject
    $ cd ~/zephyrproject
    $ west update
    $ west blobs fetch hal_telink
    $ west zephyr-export
    
  4. 为 Zephyr 安装其他 Python 依赖项。
    $ pip3 install --user -r ~/zephyrproject/zephyr/scripts/requirements.txt
    
  5. 设置 Zephyr 工具链。将 Zephyr 工具链(约 1~2 GB)下载到本地目录,以便您刷写大多数板。
    $ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    $ wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing
    
    下载 Zephyr SDK 并将其放置在建议的路径中,如下所示。
    $HOME/zephyr-sdk[-x.y.z]
    $HOME/.local/zephyr-sdk[-x.y.z]
    $HOME/.local/opt/zephyr-sdk[-x.y.z]
    $HOME/bin/zephyr-sdk[-x.y.z]
    /opt/zephyr-sdk[-x.y.z]
    /usr/zephyr-sdk[-x.y.z]
    /usr/local/zephyr-sdk[-x.y.z]
    
    其中,[-x.y.z] 是可选文本,可以是任何文本,例如 -0.16.1。安装 SDK 后,该目录便无法移动。然后安装 Zephyr 工具链。
    $ tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    $ cd zephyr-sdk-0.16.1
    $ ./setup.sh -t riscv64-zephyr-elf -h -c
    
  6. 构建 Hello World 示例。首先,使用 Hello World 示例验证官方 Zephyr 项目配置是否正确,然后继续设置自定义项目。
    $ cd ~/zephyrproject/zephyr
    $ west build -p auto -b tlsr9518adk80d samples/hello_world
    
    使用 West build 命令从 Zephyr 代码库的根目录构建 hello_world 示例。您可以在 build/zephyr directory 下找到名为 zephyr.bin 的固件。
  7. 将 Zephyr 环境脚本添加到 ~/.bashrc。执行以下命令。
    $ echo "source ~/zephyrproject/zephyr/zephyr-env.sh" >> ~/.bashrc
    $ source ~/.bashrc
    
  8. 添加 Telink Zephyr 远程代码库。将 Telink 代码库作为开发分支下载到本地并进行更新。
    $ cd ~/zephyrproject/zephyr
    $ git remote add telink-semi https://github.com/telink-semi/zephyr
    $ git fetch telink develop
    $ git checkout develop
    $ west update
    $ west blobs fetch hal_telink
    

如需了解详情,请参阅 Zephyr 文档 - 入门指南

下载 Telink LinuxBDT 工具并将其解压缩到 Linux 机器上的本地目录(例如主目录 ~),以便将固件刷写到 B91 开发板上。

$ cd ~
$ wget http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/LinuxBDT.tar.bz2
$ tar -vxf LinuxBDT.tar.bz2 

通过 USB 接口将 Burning Board 连接到 Linux 机器,然后输入以下命令。

$ cd LinuxBDT
$ sudo ./bdt lsusb -v
Bus 002 Device 001: ID 1d6b:0003 xHCI Host Controller
Bus 001 Device 003: ID 0bda:565a Integrated_Webcam_HD
Bus 001 Device 023: ID 413c:301a Dell MS116 USB Optical Mouse
Bus 001 Device 037: ID 248a:826a Telink Web Debugger v3.6
Bus 001 Device 001: ID 1d6b:0002 xHCI Host Controller

如果您看到“Telink Web Debugger v3.6”消息,则表示 BDT 编程器已成功连接到 Linux 机器。

固件编译

在此 Codelab 中,您将构建两种类型的 OpenThread 固件:

  • ot-cli-ftd
  • ot-rcp

编译方法如下:

  1. 无线电协处理器 (ot-rcp)
    $ cd ~/zephyrproject
    $ rm -rf build_ot_coprocessor
    $ west build -b tlsr9518adk80d -d build_ot_coprocessor zephyr/samples/net/openthread/coprocessor -- -DDTC_OVERLAY_FILE="usb.overlay" -DOVERLAY_CONFIG=overlay-rcp-usb-telink.conf
    
  2. 具有交互式命令行的全功能 Thread 设备 (ot-cli-ftd)
    $ cd ~/zephyrproject
    $ rm -rf build_ot_cli_ftd
    $ west build -b tlsr9518adk80d -d build_ot_cli_ftd zephyr/samples/net/openthread/cli -- -DOVERLAY_CONFIG=overlay-telink-fixed-mac.conf -DCONFIG_OPENTHREAD_FTD=y
    

固件刷写

使用 USB 线缆将 B91 开发板连接到烧写板,如下图所示。

connection_overview.png

在命令行中,执行以下命令以执行固件烧录(以刷写 ot-cli-ftd 固件为例)。

$ cd ~/zephyrproject/build_ot_cli_ftd/zephyr
$ cp zephyr.bin ~/LinuxBDT/bin/ot-cli-ftd.bin
$ cd ~/LinuxBDT
$ sudo ./bdt 9518 ac
 Activate OK!
$ sudo ./bdt 9518 wf 0 -i bin/ot-cli-ftd.bin
 EraseSectorsize...
 Total Time: 2181 ms
 Flash writing...
 [100%][-] [##################################################]
 File Download to Flash at address 0x000000: 491700 bytes
 Total Time: 30087 ms

ot-rcp 的刷写方法与 ot-cli-ftd 的刷写方法基本相同。不过,固件路径和名称有所不同。

刷写完成后,通过相应标记区分两个 B91 开发板。将刷写了 ot-cli-ftd 的板标记为“FTD Joiner”,将刷写了 ot-rcp 的板标记为“RCP”。

4. 为 FTD Joiner 设备配置串行控制台

如图所示,将 FTD Joiner 直接插入 Linux 机器的 USB 端口。

usb_connection.png

将 FTD Joiner 设备连接到 Linux 机器后,打开 PuTTY。然后,创建一个新终端,设置串行端口信息,并打开串行端口。

uart_console.png

OpenThread 命令行参考文档位于此处:OpenThread CLI 参考文档。请务必在所有命令前添加 ot

示例:

> ot state
disabled
Done
> ot channel
11
Done
>

5. 将 Raspberry Pi 设置为 OpenThread 边界路由器

OpenThread 边界路由器是一种包含两个主要部分的设备:

  • Raspberry Pi 包含充当边界路由器 (BR) 所需的所有服务和固件。
  • RCP 负责 Thread 通信。

无线电协处理器 (RCP)

如需刷写 ot-rcp 固件,请按照与 ot-cli-ftd 固件刷写过程相同的步骤操作。将 B91 开发板连接到 Raspberry Pi 上的 USB 端口,如下图所示。

OTBR_overview.png

Raspberry Pi

  1. 确保 Raspbian Bullseye Lite 操作系统映像Raspbian Bullseye with Desktop 已正确写入 SD 卡。
  2. 您可以选择通过 SSH 连接到 Raspberry Pi,也可以直接使用 Raspbian 桌面。此 Codelab 将使用 SSH。
  3. 在继续执行下一步以安装 OTBR Docker 之前,请务必先更新本地代码库和软件包管理器。
    $ sudo apt-get update
    $ sudp apt-get upgrade
    

安装 Docker

如果您在上一步中仅更新了本地代码库和软件包管理器 APT,请重新启动 Raspberry Pi,然后打开 SSH 终端窗口。

  1. 安装 Docker:
    $ curl -sSL https://get.docker.com | sh
    
  2. 将当前账号放入 Docker 群组以授予权限,这样就不需要在每个命令前添加 sudo
    $ sudo usermod -aG docker $USER
    
    您需要重启 Raspberry Pi 才能使更改生效。
  3. 如果 Docker 尚未启动,请启动它:
    $ sudo dockerd
    
  4. OTBR 防火墙脚本会在 Docker 容器内生成规则。在此之前,请执行 modprobe 以加载 iptables 的内核模块。
    $ sudo modprobe ip6table_filter
    

配置并运行 Docker

此 Codelab 直接从 OpenThread Docker Hub 拉取 OTBR Docker 映像。此映像已通过 OpenThread 团队的测试和验证。

  1. 拉取最新映像:
    $ docker pull openthread/otbr:latest
    
  2. 检查 Docker 容器中的映像列表:
    $ docker images
    REPOSITORY        TAG       IMAGE ID       CREATED      SIZE
    openthread/otbr   latest    db081f4de15f   6 days ago   766MB
    
  3. 通过检查 /dev 确定 RCP 设备的串行端口名称,ttyACM0 表示 RCP 已正确连接。
    $ ls /dev/tty*
    ...
    /dev/ttyACM0
    ... 
    
  4. 首次运行 OTBR Docker,并引用 RCP 的串行端口 (ttyACM0)。如果您想继续使用此 OTBR Docker,请使用命令 docker start otbr
    $ docker run --name "otbr" --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" -p 8080:80 --dns=127.0.0.1 -it --volume /dev/ttyACM0:/dev/ttyACM0 --privileged openthread/otbr --radio-url spinel+hdlc+uart:///dev/ttyACM0
    
  5. 打开新的 SSH 终端窗口,以测试 Raspberry Pi 与 RCP 之间的连接。
    $ docker exec -ti otbr sh -c "sudo ot-ctl"
    > state 
    disabled
    Done
    

可选的 Docker 命令:

  • 获取有关正在运行的 Docker 容器的信息:
    $ docker ps -aq
    
  • 停止 OTBR Docker:
    $ docker stop otbr
    
  • 移除 OTBR Docker:
    $ docker rm otbr
    
  • 重新加载 OTBR Docker:
    $ docker restart otbr
    

此时,FTD Joiner 设备和 OTBR 已准备就绪,您可以继续执行下一步来构建 Thread 网络。

6. 创建 Thread 网络

在 RCP 上创建 Thread 网络

我们在 OTBR 上使用 ot-ctl shell 来建立 Thread 网络。如果您在上一部分中退出了 shell,请在 SSH 终端中输入以下命令以重新启动它:

$ docker exec -ti otbr sh -c "sudo ot-ctl"

接下来,按照表格中指定的顺序输入命令,并确保每个步骤都达到预期结果,然后再继续执行下一步。

索引

命令

简介

预期响应

1

dataset init new

创建新的随机网络数据集。

完成

2

dataset commit active

将新数据集提交到非易失性存储空间中的有效运营数据集。

完成

3

ifconfig up

启动 IPv6 接口。

完成

4

thread start

启用 Thread 协议操作并连接到 Thread 网络。

完成

等待 10 秒,直到线程接口启动。

5

state

检查设备状态。此命令可以多次调用,直到设备成为领导者并进入下一步。

leader
完成

6

dataset active

检查完整的有效运行数据集并记录网络密钥。

有效时间戳:1
渠道:13
渠道掩码:0x07fff800
扩展 PAN ID:b07476e168eda4fc
网状本地前缀:fd8c:60bc:a98:c7ba::/64
网络密钥:c312485187484ceb5992d2343baaf93d
网络名称:OpenThread-599c
PAN ID:0x599c
PSKc:04f79ad752e8401a1933486c95299f60
安全政策:672 onrc 0
完成

ot-cli-ftd 设备加入此 Thread 网络时,系统将使用 OTBR 在网络创建期间随机生成的网络密钥。

通过带外调试将 FTD Joiner 添加到 Thread

带外调试是指通过非无线方法(例如,在 OpenThread CLI 中手动输入)将网络凭据传输到等待加入网络的设备。在串行控制台中,按顺序向 FTD Joiner 输入以下命令。

索引

命令

简介

预期回答

1

ot dataset networkkey c312485187484ceb5992d2343baaf93d

设备只需使用网络密钥即可连接到 Thread 网络。

完成

2

ot dataset commit active

将新数据集提交到非易失性存储空间中的有效运营数据集。

完成

3

ot ifconfig up

启动 IPv6 接口。

完成

4

ot thread start

启用 Thread 协议操作并连接到 Thread 网络。

完成

等待 20 秒,让设备加入并自行配置。

5

ot state

检查设备状态。

子/路由器
完成

拓扑

在 SSH 终端中输入 ipaddrchild tablerouter table 等命令,以获取如下代码段所示的响应。

> ipaddr rloc
fd8c:60bc:a98:c7ba:0:ff:fe00:b000
Done
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt|Suprvsn| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+-------+------------------+
|   1 | 0xb001 |        240 |         23 |     3 |   51 |1|1|1|  3| 0 |     0 |   129 | 82bc12fbe783468e |

Done
> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     | Link |
+----+--------+----------+-----------+-------+--------+-----+------------------+------+
| 44 | 0xb000 |       63 |         0 |     0 |      0 |   0 | 7ae354109d611f7e |    0 |

Done
...
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt|Suprvsn| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+-------+------------------+

Done
> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     | Link |
+----+--------+----------+-----------+-------+--------+-----+------------------+------+
| 33 | 0x8400 |       63 |         0 |     3 |      3 |  13 | e61487c1cda940a6 |    1 |
| 44 | 0xb000 |       63 |         0 |     0 |      0 |   0 | 7ae354109d611f7e |    0 |

Done

OTBR 的 RLOC160xb000,FTD Joiner 的 RLOC16 最初为 0xb001。然后,FTD Joiner 的 RLOC16 在获取路由器 ID 后变为 0x8400。可以看出,FTD Joiner 已从子设备升级为路由器。

当前的 Thread 网络包含两个节点,拓扑结构如下图所示。

topology.png

7. Thread 设备之间的通信

ICMPv6 通信

我们使用 ping 命令来检查同一网络中的 Thread 设备是否可以相互通信。首先,使用 ipaddr 命令获取设备的 RLOC。

> ipaddr
fd8c:60bc:a98:c7ba:0:ff:fe00:fc11
fdbd:7274:649c:1:1d19:9613:f705:a5af
fd8c:60bc:a98:c7ba:0:ff:fe00:fc10
fd8c:60bc:a98:c7ba:0:ff:fe00:fc38
fd8c:60bc:a98:c7ba:0:ff:fe00:fc00
fd8c:60bc:a98:c7ba:0:ff:fe00:b000       # Routing Locator (RLOC)
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
fe80:0:0:0:78e3:5410:9d61:1f7e
Done

在 FTD Joiner 的串行控制台中输入以下命令,以执行 ping 操作。

> ot ping fd8c:60bc:a98:c7ba:0:ff:fe00:b000
16 bytes from fd8c:60bc:a98:c7ba:0:ff:fe00:b000: icmp_seq=1 hlim=64 time=19ms
1 packets transmitted, 1 packets received. Packet loss = 0.0%. Round-trip min/avg/max = 19/19.0/19 ms.
Done

串行端口的输出响应表明 OTBR 端已收到 ping 请求,FTD Joiner 已收到 OTBR 返回的 ping 响应。两个设备之间的通信成功。

UDP 通信

OpenThread 提供的应用服务还包括 UDP。您可以使用 UDP API 在 Thread 网络中的节点之间传递信息,也可以通过边界路由器将信息传递到外部网络。有关 OpenThread 的 UDP API 的详细介绍,请参阅 OpenThread CLI - UDP 示例。此 Codelab 将使用其中的一些 API 在 OTBR 和 FTD Joiner 之间传输信息。

首先,获取 OTBR 的网状本地 EID。此地址也是 Thread 设备的 IPv6 地址之一,可用于访问同一 Thread 网络分区中的 Thread 设备。

> ipaddr mleid
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
Done

在 SSH 终端中输入以下命令,以启用 OTBR UDP 并绑定设备的 1022 端口。

> udp open
Done
> udp bind :: 1022
Done

在串行控制台中输入以下命令,并启用 FTD Joiner 的 UDP。绑定设备的 1022 端口,然后向 OTBR 发送 5 字节的 hello 消息。

> ot udp open 
Done
> ot udp bind :: 1022
Done
> ot udp send fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6 1022 hello
Done

SSH 终端会输出以下信息。OTBR 从 FTD Joiner 接收到 hello 消息,这意味着 UDP 通信成功。

> 5 bytes from fd8c:60bc:a98:c7ba:9386:63cf:19d7:5a61 1022 hello

8. 恭喜

您已创建一个简单的 Thread 网络,并验证了该网络内的通信。

您现在已了解:

  • 如何构建和使用 Telink Zephyr 开发环境。
  • 如何构建 ot-cli-ftdot-rcp 二进制文件,以及如何将它们刷写到 Telink B91 开发板上。
  • 如何使用 Docker 将 Raspberry Pi 3B+ 或更高版本设置为 OpenThread 边界路由器 (OTBR)。
  • 如何在 OTBR 上创建 Thread 网络。
  • 如何通过带外调试将设备添加到 Thread 网络。
  • 如何验证 Thread 网络中节点之间的连接。

延伸阅读

访问 openthread.ioGitHub,了解各种 OpenThread 资源,包括:

参考文件: