1. 简介

Google 发布的 OpenThread 是 Thread 网络协议的开源实现。Google Nest 发布了 OpenThread,以便开发者广泛使用 Nest 产品中使用的技术,从而加快智能互联家居产品的开发速度。
Thread 规范定义了一种基于 IPv6 的可靠、安全且低功耗的无线设备到设备通信协议,适用于家庭应用。OpenThread 实现所有 Thread 网络层,包括 IPv6、6LoWPAN、具有 MAC 安全性的 IEEE 802.15.4、网状链路建立和网状路由。
此 Codelab 将引导您在模拟设备上模拟 Thread 网络。
学习内容
- 如何设置 OpenThread build 工具链
- 如何模拟 Thread 网络
- 如何对 Thread 节点进行身份验证
- 如何使用 OpenThread Daemon 管理 Thread 网络
所需条件
- git
- Linux、网络路由基础知识
2. 设置构建系统
Git
您必须拥有 Git,才能完成本 Codelab。请先下载并安装该工具,然后再继续。
安装完成后,请按照适用于您特定操作系统的说明下载并构建 OpenThread。
适用于 Mac OS X 的 Xcode
您需要在 Mac OS X 上安装并构建 OpenThread。为此,您需要安装 XCode。
安装 Xcode 后,请安装 Xcode 命令行工具:
$ xcode-select --install
在 Linux / Mac OS X 上构建
这些安装说明已在 Ubuntu Server 14.04 LTS 和 Mac OS X Sierra 10.12.6 上进行了测试。
安装 OpenThread。bootstrap 命令可确保已安装工具链并且环境已正确配置:
$ mkdir -p ~/src $ cd ~/src $ git clone --recursive https://github.com/openthread/openthread.git $ cd openthread $ ./script/bootstrap
使用 Windows
如果您偏好使用 Windows,建议您尝试此 Codelab 的 Docker 版本。
3. 构建 OpenThread 应用
安装完成后,构建示例 OpenThread 应用。在此 Codelab 中,我们使用的是模拟示例。
$ cd ~/src/openthread $ ./script/cmake-build simulation
现在构建 OpenThread Daemon:
$ ./script/cmake-build posix -DOT_DAEMON=ON
4. 模拟 Thread 网络
您将在本 Codelab 中使用的示例应用展示了一个最简单的 OpenThread 应用,该应用通过基本的命令行界面 (CLI) 公开 OpenThread 配置和管理接口。
此练习将引导您完成从一个模拟 Thread 设备向另一个模拟 Thread 设备发送 ping 所需的最低限度的步骤。
下图描述了一个基本的 Thread 网络拓扑。在此练习中,我们将模拟绿色圆圈内的两个节点:Thread Leader 和 Thread Router,它们之间只有一个连接。

对节点执行 ping 操作
1. 启动节点 1
前往 openthread 目录,然后使用 ot-cli-ftd 二进制文件为模拟的 Thread 设备生成 CLI 进程。
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
注意:如果您在运行此命令后没有看到 > 提示,请按 enter。
此二进制文件实现了在 POSIX 之上模拟的 OpenThread 设备。IEEE 802.15.4 无线电驱动程序是在 UDP 之上实现的(IEEE 802.15.4 帧在 UDP 载荷内传递)。
1 的实参是一个文件描述符,表示模拟设备的“出厂分配”IEEE EUI-64 的最低有效位。此值还用于绑定到 UDP 端口以进行 IEEE 802.15.4 无线电仿真(端口 = 9000 + 文件描述符)。在此 Codelab 中,每个模拟的 Thread 设备实例都将使用不同的文件描述符。
注意:在为模拟设备生成进程时,请仅使用此 Codelab 中所述的 1 或更大的文件描述符。文件描述符 0 已预留给其他用途。
创建新的运营数据集并将其提交为有效数据集。运行数据集是您要创建的 Thread 网络的配置。
> dataset init new Done > dataset Active Timestamp: 1 Channel: 20 Channel Mask: 07fff800 Ext PAN ID: d6263b6d857647da Mesh Local Prefix: fd61:2344:9a52:ede0/64 Network Key: e4344ca17d1dca2a33f064992f31f786 Network Name: OpenThread-c169 PAN ID: 0xc169 PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4 Security Policy: 0, onrcb Done
将此数据集提交为有效数据集:
> dataset commit active Done
启动 IPv6 接口:
> ifconfig up Done
启动 Thread 协议操作:
> thread start Done
等待几秒钟,然后验证设备是否已成为 Thread Leader。领导者是负责管理路由器 ID 分配的设备。
> state leader Done
查看分配给节点 1 的 Thread 接口的 IPv6 地址(您的输出会有所不同):
> ipaddr fd61:2344:9a52:ede0:0:ff:fe00:fc00 fd61:2344:9a52:ede0:0:ff:fe00:5000 fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6 fe80:0:0:0:94da:92ea:1353:4f3b Done
请注意以下特定 IPv6 地址类型:
- 以
fd开头 = 网状本地 - 以
fe80开头 = 链路本地
网状本地地址类型进一步细分为:
- 包含
ff:fe00= 路由器定位器 (RLOC) - 不包含
ff:fe00= 端点标识符 (EID)
在控制台输出中找到 EID,并记下以供日后使用。在上面的示例输出中,EID 为:
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
2. 启动节点 2
打开新终端,然后导航到 openthread 目录并生成 CLI 进程。这是您的第二个模拟 Thread 设备:
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 2
注意:如果您在运行此命令后没有看到 > 提示,请按 enter。
配置 Thread 网络密钥和 PAN ID,使用与节点 1 的运行数据集相同的值:
> dataset networkkey e4344ca17d1dca2a33f064992f31f786 Done > dataset panid 0xc169 Done
将此数据集提交为有效数据集:
> dataset commit active Done
启动 IPv6 接口:
> ifconfig up Done
启动 Thread 协议操作:
> thread start Done
设备将自行初始化为子设备。Thread 子设备相当于终端设备,是一种仅与父设备传输和接收单播流量的 Thread 设备。
> state child Done
在 2 分钟内,您应该会看到状态从 child 变为 router。Thread 路由器能够在 Thread 设备之间路由流量。也称为父级。
> state router Done
验证网络
验证网状网络是否正常运行的简单方法是查看路由器表。
1. 检查连接情况
在节点 2 上,获取 RLOC16。RLOC16 是设备 RLOC IPv6 地址的最后 16 位。
> rloc16 5800 Done
在节点 1 上,检查节点 2 的 RLOC16 的路由表。确保节点 2 先切换到路由器状态。
> router table | ID | RLOC16 | Next Hop | Path Cost | LQI In | LQI Out | Age | Extended MAC | +----+--------+----------+----------+-------+---------+-----+------------------+ | 20 | 0x5000 | 63 | 0 | 0 | 0 | 0 | 96da92ea13534f3b | | 22 | 0x5800 | 63 | 0 | 3 | 3 | 23 | 5a4eb647eb6bc66c |
在表中找到了节点 1 的 RLOC 0xa800,确认它已连接到网状网络。
2. 从节点 2 对节点 1 执行 Ping 操作
验证两个模拟 Thread 设备之间的连接。在节点 2 中,ping 分配给节点 1 的 EID:
> ping fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6 > 16 bytes from fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6: icmp_seq=1 hlim=64 time=12ms
按 enter 即可返回到 > CLI 提示。
测试网络
现在,您已可以成功在两个模拟 Thread 设备之间执行 ping 操作,接下来请通过将一个节点设为离线来测试网状网络。
返回到节点 1 并停止线程:
> thread stop Done
切换到节点 2 并检查状态。在两分钟内,节点 2 检测到领导者(节点 1)已离线,您应该会看到节点 2 转换为网络的 leader:
> state router Done ... > state leader Done
确认后,停止 Thread 并将节点 2 恢复出厂设置,然后再退出。执行恢复出厂设置是为了确保我们在本练习中使用的 Thread 网络凭据不会沿用到下一个练习中。
> thread stop Done > factoryreset > > exit
同时恢复出厂设置并退出节点 1:
> factoryreset > > exit
如需探索所有可用的 CLI 命令,请参阅 OpenThread CLI 参考文档。
5. 使用调试对节点进行身份验证
在上一个练习中,您设置了一个包含两个模拟设备的 Thread 网络,并验证了连接。不过,这仅允许未经身份验证的 IPv6 链路本地流量在设备之间传递。为了在它们之间(以及通过 Thread 边界路由器与互联网之间)路由全局 IPv6 流量,节点必须经过身份验证。
为了进行身份验证,一个设备必须充当调试器。专员是当前为新 Thread 设备选定的身份验证服务器,也是提供设备加入网络所需的网络凭据的授权者。
在此练习中,我们将使用与之前相同的双节点拓扑。对于身份验证,Thread Leader 将充当调试器,Thread 路由器将充当加入者。

1. 创建网络
如果您要继续完成上一个练习,则应已打开两个终端窗口。如果不是,请确保打开两个窗口并做好使用准备。一个将用作节点 1,另一个将用作节点 2。
在节点 1 中,生成 CLI 进程:
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
注意:如果您在运行此命令后没有看到 > 提示,请按 enter。
创建新的运行数据集,将其提交为有效数据集,然后启动 Thread:
> dataset init new Done > dataset Active Timestamp: 1 Channel: 12 Channel Mask: 07fff800 Ext PAN ID: e68d05794bf13052 Mesh Local Prefix: fd7d:ddf7:877b:8756/64 Network Key: a77fe1d03b0e8028a4e13213de38080e Network Name: OpenThread-8f37 PAN ID: 0x8f37 PSKc: f9debbc1532487984b17f92cd55b21fc Security Policy: 0, onrcb Done
将此数据集提交为有效数据集:
> dataset commit active Done
启动 IPv6 接口:
> ifconfig up Done
启动 Thread 协议操作:
> thread start Done
等待几秒钟,然后验证设备是否已成为 Thread Leader:
> state leader Done
2. 开始担任专员角色
在节点 1 上,启动 Commissioner 角色:
> commissioner start Done
允许任何具有 J01NME 加入者凭据的加入者(通过使用 * 通配符)委托加入网络。加入者是指由人类管理员添加到已调试的 Thread 网络中的设备。
> commissioner joiner add * J01NME Done
3. 启动加入者角色
在第二个终端窗口中,生成一个新的 CLI 进程。这是节点 2。
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 2
在节点 2 上,使用 J01NME 加入者凭据启用加入者角色。
> ifconfig up Done > joiner start J01NME Done
... 等待几秒钟以进行确认 ...
Join success
作为加入者,设备(节点 2)已成功向专员(节点 1)验证自身身份,并已收到 Thread 网络凭据。
现在,节点 2 已通过身份验证,请启动 Thread:
> thread start Done
4. 验证网络身份验证
检查节点 2 上的 state,以验证其是否已加入网络。在两分钟内,节点 2 从 child 转换到 router:
> state child Done ... > state router Done
5. 重置配置
为了准备进行下一个练习,请重置配置。在每个节点上,停止 Thread、恢复出厂设置并退出模拟的 Thread 设备:
> thread stop Done > factoryreset > > exit
在执行 factoryreset 命令后,您可能需要按几次 enter 才能重新显示 > 提示。
6. 使用 OpenThread Daemon 管理网络
在此练习中,我们将模拟一个 CLI 实例(单个嵌入式 SoC Thread 设备)和一个无线电协处理器 (RCP) 实例。
ot-daemon 是 OpenThread Posix 应用的一种模式,它使用 UNIX 套接字作为输入和输出,以便 OpenThread 核心可以作为服务运行。客户端可以通过使用 OpenThread CLI 作为协议连接到套接字来与此服务通信。
ot-ctl 是 ot-daemon 提供的一个 CLI,用于管理和配置 RCP。我们将使用此命令将 RCP 连接到 Thread 设备创建的网络。
使用 ot-daemon
本练习将使用三个终端窗口,分别对应于以下内容:
- 模拟 Thread 设备 (Node 1) 的 CLI 实例
ot-daemon流程ot-ctlCLI 实例
如果您是从上一个练习继续操作,则应该已经打开了两个终端窗口。打开第三个,确保您有三个终端窗口可用于本练习。
1. 启动节点 1
在第一个终端窗口中,为模拟的 Thread 设备生成 CLI 进程:
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
注意:如果您在运行此命令后没有看到 > 提示,请按 enter。
创建新的运行数据集,将其提交为有效数据集,然后启动 Thread:
> dataset init new Done > dataset Active Timestamp: 1 Channel: 13 Channel Mask: 07fff800 Ext PAN ID: 97d584bcd493b824 Mesh Local Prefix: fd55:cf34:dea5:7994/64 Network Key: ba6e886c7af50598df1115fa07658a83 Network Name: OpenThread-34e4 PAN ID: 0x34e4 PSKc: 38d6fd32c866927a4dfcc06d79ae1192 Security Policy: 0, onrcb Done
将此数据集提交为有效数据集:
> dataset commit active Done
启动 IPv6 接口:
> ifconfig up Done
启动 Thread 协议操作:
> thread start Done
查看分配给节点 1 的 Thread 接口的 IPv6 地址:
> ipaddr fd55:cf34:dea5:7994:0:ff:fe00:fc00 fd55:cf34:dea5:7994:0:ff:fe00:d000 fd55:cf34:dea5:7994:460:872c:e807:c4ab fe80:0:0:0:9cd8:aab6:482f:4cdc Done >
如模拟 Thread 网络步骤中所述,一个地址是链路本地地址 (fe80),三个地址是网状本地地址 (fd)。EID 是不包含 ff:fe00 的网状本地地址。在此示例输出中,EID 为 fd55:cf34:dea5:7994:460:872c:e807:c4ab。
从 ipaddr 输出中确定将用于与节点通信的特定 EID。
2. 启动 ot-daemon
在第二个终端窗口中,导航到 openthread 目录,然后为 RCP 节点启动 ot-daemon,我们将其称为节点 2。使用 -v 详细标志,以便查看日志输出并确认其正在运行,同时确保使用 sudo:
$ cd ~/src/openthread
$ sudo ./build/posix/src/posix/ot-daemon -v \
'spinel+hdlc+forkpty://build/simulation/examples/apps/ncp/ot-rcp?forkpty-arg=2'
成功时,详细模式下的 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
让此终端保持打开状态并在后台运行。您不会在其中输入任何其他命令。
3. 使用 ot-ctl 加入网络
我们尚未将节点 2(即 ot-daemon RCP)委托给任何 Thread 网络。这时,ot-ctl 就派上用场了。ot-ctl 使用与 OpenThread CLI 应用相同的 CLI。因此,您可以像控制其他模拟 Thread 设备一样控制 ot-daemon 节点。
在第三个终端窗口中,启动 ot-ctl:
$ sudo ./build/posix/src/posix/ot-ctl >
注意:如果您在运行此命令后没有看到 > 提示,请按 enter。
您将在第三个终端窗口中使用 ot-ctl 来管理在第二个终端窗口中使用 ot-daemon 启动的节点 2(RCP 节点)。检查节点 2 的 state:
> state disabled Done
获取节点 2 的 eui64,以限制加入到特定加入者:
> eui64 18b4300000000001 Done
在节点 1(第一个终端窗口)上,启动 Commissioner 并限制仅允许该 eui64 加入:
> commissioner start Done > commissioner joiner add 18b4300000000001 J01NME Done
在节点 2(第三个终端窗口)上,启动网络接口并加入网络:
> ifconfig up Done > joiner start J01NME Done
... 等待几秒钟以进行确认 ...
Join success
作为加入者,RCP(节点 2)已成功向专员(节点 1)验证自身身份,并收到了 Thread 网络凭据。
现在,将节点 2 加入到 Thread 网络:
> thread start Done
4. 验证网络身份验证
检查节点 2 上的 state,以验证其是否已加入网络。在两分钟内,节点 2 从 child 转换到 router:
> state child Done ... > state router Done
5. 验证连接
使用 Ctrl+D 或 exit 命令退出 ot-ctl,然后在主机命令行中,使用 ping6 命令通过 EID 对节点 1 执行 ping 操作。如果 ot-daemon RCP 实例已成功加入 Thread 网络并与该网络通信,则 ping 会成功:
$ ping6 -c 4 fd55:cf34:dea5:7994:460:872c:e807:c4ab PING fd55:cf34:dea5:7994:460:872c:e807:c4ab (fd55:cf34:dea5:7994:460:872c:e807:c4ab): 56 data bytes 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=0 ttl=64 time=4.568 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=1 ttl=64 time=6.396 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=2 ttl=64 time=7.594 ms 64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=3 ttl=64 time=5.461 ms --- fd55:cf34:dea5:7994:460:872c:e807:c4ab ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max/stddev = 4.568/6.005/7.594/1.122 ms
7. 恭喜!
您已使用 OpenThread 成功模拟了第一个 Thread 网络。也很棒!
在此 Codelab 中,你学习了如何:
- 设置 OpenThread build 工具链
- 模拟 Thread 网络
- 对 Thread 节点进行身份验证
- 使用 OpenThread 守护程序管理 Thread 网络
如需了解详情,请参阅以下参考资料: