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

1. 简介

26b7f4f6b3ea0700.png

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

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

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

在此 Codelab 中,您将在实际硬件上为 OpenThread 编程,创建和管理 Thread 网络,并在节点之间交换消息。下图显示了硬件设置,其中包含此 Codelab 中的 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 网络。
  • 使用 CLI 验证 Thread 网络节点之间的连接情况。

所需条件

硬件:

  • 两个 B91 开发板。
  • 一个搭载 Raspberry Pi 3B 或更高型号的 Raspbian OS 映像。
  • 具有至少两个 USB 端口的 Linux 机器。
  • 互联网连接(或路由器)和几根以太网线缆。

软件:

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

2. 前提条件

线程概念和 OpenThread CLI

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

Linux 机器

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

串行端口连接和终端

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

在此 Codelab 中,终端工具 PuTTY 用于控制 FTD 联接和 Raspberry Pi。它可以提供使用概览,也可以采用其他终端软件。

此 Codelab 需要两套 B91 开发套件。下面的照片在一个集中显示了所需的最基本的组件。

overview.png

其中一个套件将用作 RCP(无线协处理器),而另一个套件将用作 FTD(全线程设备)。如果您还没有该套件,可以从 Telink 官方网站获取更多详细信息。需要使用的部分组件如下:

索引

名称

1

Telink B91 开发板

2

Telink 燃烧板

3

2.4Ghz 天线

4

USB 线(USB A 转迷你 USB)

使用 Raspbian OS 映像的 Raspberry Pi 3B 及更高版本

在本 Codelab 中,我们需要一个 Raspberry Pi 3B 及更高版本,其中包含Raspbian Bullseye Lite OS 映像带 Rasbian Bullseye 的桌面平台。它通过以太网连接到互联网,并配置为 OpenThread 边界路由器 (OTBR) 的主机。

网络连接类型

可连接到互联网的开关(或路由器)以及多根以太网线缆。它们用于将 Raspberry Pi 连接到 Linux 机器,从而通过主机简化 Raspberry Pi 的用户配置。

LinuxBDT

Telink 错误和调试工具 (BDT) 适用于所有 Telink 芯片组,可用于清空 OpenThread 固件并将其刷写到 Telink B91 开发板。在 Linux 计算机上安装基于 X86 的 Linux 版本 linuxBDT

其他

  • Git,用于设置 Telink Zephyr 开发环境。
  • 西部,用于管理 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 Compiler (1.4.6)。
    $ cmake --version
    $ python3 --version
    $ dtc --version
    
    请先验证您的系统中已安装的版本,然后再继续后续步骤。如果版本不正确,请将 APT 镜像切换到稳定且最新的镜像,或手动更新这些依赖项。
  2. 向西安装。
    $ 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 接口将燃烧板连接到 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. 功能齐全且带有交互式命令行的线程设备 (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 的 Flash 方法基本相同。不过,固件路径和名称存在差异。

刷写后,通过将两个 B91 开发板进行相应标记加以区分。将刷入了 ot-cli-ftd 的板标记为“FTD Joiner”(带有 FTD 连接符),并将包含 ot-rcp 的板标记为“RCP”。

4. 为 FTD 联接设备配置配置控制台

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

usb_connection.png

将 FTD 联接设备连接到 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 概览

覆盆子 Pi

  1. 确保Raspbian Bullseye Lite OS 映像桌面版 Rasbian Bullseye 电脑版已正确写入 SD 卡。
  2. 您可以选择通过 SSH 连接到 Raspberry Pi,或者直接使用 Raspbian Desktop。此 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 联接设备和 OTBR 已准备就绪,您可以继续执行下一步以构建 Thread 网络。

6. 创建线程网络

在 RCP 上创建线程网络

我们使用 OTBR 上的 ot-ctl shell 建立线程网络。如果您在上一部分中退出了 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

检查设备状态。可以多次调用此命令,直到它成为主要副本,然后继续执行下一步。

领导者
完成

6

dataset active

检查完整的活跃操作数据集并记录网络键。











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

通过带外调试将 FTD 联接器添加到 Thread

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

索引

命令

简介

预期响应

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 联接器的 RLOC16 最初为 0xb001。然后,FTD 联接方的 RLOC16 将在获得路由器 ID 后变为 0x8400。您可以看到,FTD 联接已从儿童升级为路由器。

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

Topology.png

7. 线程设备之间的通信

ICMPv6 通信

我们使用 ping 命令来检查同一网络中的线程设备是否可以相互通信。首先,使用 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 联接器的串行控制台中输入以下命令,以执行 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 联接器已收到 OTBR 返回的 ping 响应。两台设备之间的通信已成功完成。

UDP 通信

OpenThread 提供的应用服务也包括 UDP。您可以使用 UDP API 在 Thread 网络中的节点之间传递信息,也可以通过边界路由器向外部网络传递信息。如需详细了解 OpenThread 的 UDP API,请参阅 OpenThread CLI - UDP 示例。此 Codelab 将使用它中的某些 API 在 OTBR 和 FTD 联接器之间传输信息。

首先,获取 OTBR 的 Mesh-Local 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 联接器的 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 联接器接收 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 网络中的节点之间的连接。

延伸阅读

查看 openthread.ioGitHub,了解各种 OpenThread 资源,包括:

参考文档: