Thread 网络诊断 Cluster(ThreadNetworkDiagnostics)
Cluster ID: 0x0035 |
所在 Endpoint: Endpoint 0(根端点)
ThreadNetworkDiagnostics 是 Thread 设备的网络诊断 Cluster,提供 Thread Mesh 网络的完整运行状态。 它包含网络标识、拓扑路由、收发包统计、错误计数等 60+ 个属性,是排查 Thread 设备连接问题和分析网络质量的核心工具。
这个 Cluster 主要用于诊断和调试,不控制设备功能。当 Thread 设备连接不稳定、网络延迟高、丢包严重时, 通过读取此 Cluster 可以快速定位问题 —— 是信号差(看 RSSI/LQI)、路由不优(看 RouteTable)、 还是链路错误多(看错误计数器)。
Feature 位图
ThreadNetworkDiagnostics 通过 FeatureMap(0xFFFC)声明设备支持哪些计数器类别。
不同 Feature 控制不同分组的计数器属性是否可用。
基础网络信息(Channel、RoutingRole、NeighborTable 等)所有 Thread 设备都支持,不需要任何 Feature。
计数器属性则按 Feature 分组 —— 例如只有启用了 PKTCNT 的设备才会上报 TxTotalCount 等收发统计。
读取前先检查 FeatureMap,避免读到不支持的属性返回错误。
命令(Commands)
ThreadNetworkDiagnostics 只有一个命令,用于重置所有计数器。
| ID | 名称 | 说明 | 所需特性 |
|---|---|---|---|
0x00 |
ResetCounts | 将所有可选计数器归零 | ERRCNT 或 MACCNT |
ResetCounts —— 重置计数器(0x00)
将设备上所有已启用 Feature 对应的计数器(包括 OverrunCount)归零。 不需要参数。执行后所有统计从 0 开始重新累计。
使用场景
诊断网络问题时,先调用 ResetCounts 清零,然后观察一段时间内的计数器增长情况, 用来判断当前的错误率和网络质量。避免历史累积数据干扰判断。
属性详解
ThreadNetworkDiagnostics 有 60+ 个属性,按功能分为以下几组。 基础网络信息所有 Thread 设备都支持,计数器属性按 Feature 分组。
网络标识(0x0000 - 0x0005)
Thread 网络的基本身份信息,标识设备所在的 Thread 网络。
| ID | 名称 | 类型 | 说明 |
|---|---|---|---|
0x0000 |
Channel 信道 |
uint16 | 当前 Thread 网络使用的 IEEE 802.15.4 信道号。Thread 使用 2.4GHz 的 11~26 信道 |
0x0001 |
RoutingRole 路由角色 |
RoutingRoleEnum / null | 设备在 Thread 网络中的当前角色(见枚举值)。null 表示尚未确定 |
0x0002 |
NetworkName 网络名称 |
string / null | Thread 网络名称,最长 16 字节的 UTF-8 字符串 |
0x0003 |
PanId PAN ID |
uint16 / null | IEEE 802.15.4 的 16 位 PAN 标识符 |
0x0004 |
ExtendedPanId 扩展 PAN ID |
uint64 / null | 64 位扩展 PAN 标识符,用于区分相同 PAN ID 的不同网络 |
0x0005 |
MeshLocalPrefix Mesh 本地前缀 |
octstr / null | Thread Mesh 本地 IPv6 前缀(fd00::/8 范围内的 /64 前缀) |
拓扑与路由(0x0007 - 0x000D)
Thread Mesh 网络的拓扑结构和路由信息,包括邻居表、路由表和分区数据。
| ID | 名称 | 类型 | 说明 |
|---|---|---|---|
0x0007 |
NeighborTable 邻居表 |
list<NeighborTableStruct> | 直接通信邻居的详细信息列表(见结构体说明) |
0x0008 |
RouteTable 路由表 |
list<RouteTableStruct> | 网络路由条目列表(见结构体说明) |
0x0009 |
PartitionId 分区 ID |
uint32 / null | 当前 Thread 网络分区的标识符。网络分裂时不同分区有不同 ID |
0x000A |
Weighting 分区权重 |
uint16 / null | 当前分区的权重,网络合并时优先保留权重高的分区 |
0x000B |
DataVersion 数据版本 |
uint16 / null | Thread 网络数据的版本号,每次网络数据变更时递增 |
0x000C |
StableDataVersion 稳定数据版本 |
uint16 / null | 稳定网络数据的版本号(不含临时路由等易变数据) |
0x000D |
LeaderRouterId Leader 路由 ID |
uint8 / null | 当前 Thread 网络 Leader 的 Router ID |
NeighborTableStruct 结构体
邻居表中每个条目描述一个直接通信的邻居节点。信号质量(LQI/RSSI)和错误率是判断链路健康的关键字段。
| 字段 | 类型 | 说明 |
|---|---|---|
| ExtAddress | uint64 | 邻居的 64 位扩展 MAC 地址 |
| Age | uint32 | 最后一次通信以来的秒数 |
| Rloc16 | uint16 | 邻居的 16 位路由定位符 |
| LinkFrameCounter | uint32 | 链路层帧计数器 |
| MleFrameCounter | uint32 | MLE 层帧计数器 |
| LQI | uint8 | 链路质量指示(0-255,越高越好) |
| AverageRssi | int8 / null | 平均 RSSI(dBm),典型范围 -100 到 0 |
| LastRssi | int8 / null | 最近一次收包的 RSSI(dBm) |
| FrameErrorRate | uint8 | 帧错误率(0-100%,缩放到 0-255) |
| MessageErrorRate | uint8 | 消息错误率(0-100%,缩放到 0-255) |
| RxOnWhenIdle | bool | 空闲时是否保持接收(false = 嗜睡设备) |
| FullThreadDevice | bool | 是否为全功能 Thread 设备(FTD) |
| FullNetworkData | bool | 是否接收完整网络数据 |
| IsChild | bool | 该邻居是否为本节点的子节点 |
RouteTableStruct 结构体
路由表中每个条目描述一条到目标 Router 的路由信息。
| 字段 | 类型 | 说明 |
|---|---|---|
| ExtAddress | uint64 | 目标路由器的 64 位扩展 MAC 地址 |
| Rloc16 | uint16 | 目标路由器的 16 位路由定位符 |
| RouterId | uint8 | 路由器 ID(0-62) |
| NextHop | uint8 | 下一跳的 Router ID |
| PathCost | uint8 | 到达目标的路径开销(越小越优) |
| LQIIn | uint8 | 入站链路质量指示 |
| LQIOut | uint8 | 出站链路质量指示 |
| Age | uint8 | 路由条目的存活时间 |
| Allocated | bool | 该 Router ID 是否已被分配 |
| LinkEstablished | bool | 与该路由器是否已建立双向链路 |
数据集参数(0x0006, 0x0038 - 0x003E)
Thread 操作数据集(Operational Dataset)相关的参数,包括时间戳、安全策略和网络故障信息。
| ID | 名称 | 类型 | 所需特性 | 说明 |
|---|---|---|---|---|
0x0006 |
OverrunCount 溢出次数 |
uint64 | ERRCNT | 接收缓冲区溢出的累计次数 |
0x0038 |
ActiveTimestamp 活跃时间戳 |
uint64 / null | 无 | 当前活跃操作数据集的时间戳 |
0x0039 |
PendingTimestamp 待定时间戳 |
uint64 / null | 无 | 待生效操作数据集的时间戳(用于延迟更新网络配置) |
0x003A |
Delay 延迟 |
uint32 / null | 无 | 待定数据集生效前的延迟时间(毫秒) |
0x003B |
SecurityPolicy 安全策略 |
SecurityPolicy / null | 无 | 网络安全策略,包括密钥轮换时间和安全标志位 |
0x003C |
ChannelPage0Mask 信道掩码 |
octstr / null | 无 | Page 0 的信道掩码,标识网络允许使用的信道集合 |
0x003D |
OperationalDatasetComponents 数据集组件 |
Struct / null | 无 | 标识操作数据集中哪些组件存在(见结构体说明) |
0x003E |
ActiveNetworkFaultsList 活跃网络故障 |
list<NetworkFaultEnum> | 无 | 当前活跃的网络故障列表(见枚举值),空列表表示无故障 |
SecurityPolicy 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
| RotationTime | uint16 | 安全密钥轮换周期(小时) |
| Flags | uint16 | 安全策略标志位(控制外部 Commissioner 接入、Native Commissioner 等) |
OperationalDatasetComponents 结构体
每个字段为 bool,标识操作数据集中对应组件是否存在。
| 字段 | 说明 |
|---|---|
| ActiveTimestampPresent | 活跃时间戳 |
| PendingTimestampPresent | 待定时间戳 |
| MasterKeyPresent | 主密钥(Network Key) |
| NetworkNamePresent | 网络名称 |
| ExtendedPanIdPresent | 扩展 PAN ID |
| MeshLocalPrefixPresent | Mesh 本地前缀 |
| DelayPresent | 延迟计时器 |
| PanIdPresent | PAN ID |
| ChannelPresent | 信道号 |
| PskcPresent | PSKc(Commissioner 密钥) |
| SecurityPolicyPresent | 安全策略 |
| ChannelMaskPresent | 信道掩码 |
发送计数器 — TX Counters(0x0016 - 0x0026)PKTCNT / MACCNT
统计设备发送数据包的各类计数。所有字段均为 uint32 类型,需要 PKTCNT 或 MACCNT Feature。
| ID | 名称 | 说明 |
|---|---|---|
0x0016 | TxTotalCount | 发送的数据包总数 |
0x0017 | TxUnicastCount | 发送的单播包数量 |
0x0018 | TxBroadcastCount | 发送的广播包数量 |
0x0019 | TxAckRequestedCount | 请求 ACK 确认的发送包数量 |
0x001A | TxAckedCount | 已收到 ACK 确认的发送包数量 |
0x001B | TxNoAckRequestedCount | 不要求 ACK 确认的发送包数量 |
0x001C | TxDataCount | 发送的数据帧数量 |
0x001D | TxDataPollCount | 发送的数据轮询帧数量(嗜睡设备唤醒拉取数据) |
0x001E | TxBeaconCount | 发送的 Beacon 帧数量 |
0x001F | TxBeaconRequestCount | 发送的 Beacon 请求帧数量 |
0x0020 | TxOtherCount | 发送的其他类型帧数量 |
0x0021 | TxRetryCount | 发送重试次数(重试率 = TxRetryCount / TxTotalCount) |
0x0022 | TxDirectMaxRetryExpiryCount | 直接传输达到最大重试次数的包数量 |
0x0023 | TxIndirectMaxRetryExpiryCount | 间接传输达到最大重试次数的包数量 |
0x0024 | TxErrCcaCount | CCA(信道空闲评估)失败导致的发送失败次数 |
0x0025 | TxErrAbortCount | 发送中止的次数 |
0x0026 | TxErrBusyChannelCount | 信道繁忙导致的发送失败次数 |
关注 TxRetryCount / TxTotalCount 比值 —— 重试率超过 10% 说明链路质量较差。
TxErrCcaCount 持续增长通常意味着信道拥挤,可能需要换信道。
TxDirectMaxRetryExpiryCount 非零说明有丢包,需要检查目标节点是否在线。
接收计数器 — RX Counters(0x0027 - 0x0031)PKTCNT / MACCNT
统计设备接收数据包的各类计数。所有字段均为 uint32 类型,需要 PKTCNT 或 MACCNT Feature。
| ID | 名称 | 说明 |
|---|---|---|
0x0027 | RxTotalCount | 接收的数据包总数 |
0x0028 | RxUnicastCount | 接收的单播包数量 |
0x0029 | RxBroadcastCount | 接收的广播包数量 |
0x002A | RxDataCount | 接收的数据帧数量 |
0x002B | RxDataPollCount | 接收的数据轮询帧数量 |
0x002C | RxBeaconCount | 接收的 Beacon 帧数量 |
0x002D | RxBeaconRequestCount | 接收的 Beacon 请求帧数量 |
0x002E | RxOtherCount | 接收的其他类型帧数量 |
0x002F | RxAddressFilteredCount | 被地址过滤丢弃的接收包数量 |
0x0030 | RxDestAddrFilteredCount | 因目的地址不匹配而过滤的包数量 |
0x0031 | RxDuplicatedCount | 接收到的重复包数量 |
接收错误计数器(0x0032 - 0x0037)ERRCNT
统计各类接收错误。所有字段均为 uint32 类型,需要 ERRCNT Feature。
| ID | 名称 | 说明 |
|---|---|---|
0x0032 | RxErrNoFrameCount | 接收到无帧内容的错误包数量 |
0x0033 | RxErrUnknownNeighborCount | 来自未知邻居的包数量(可能是网络攻击或新节点) |
0x0034 | RxErrInvalidSrcAddrCount | 源地址无效的包数量 |
0x0035 | RxErrSecCount | 安全校验失败的包数量(解密失败或 MIC 不匹配) |
0x0036 | RxErrFcsCount | FCS(帧校验序列)错误的包数量 —— 通常是射频干扰导致 |
0x0037 | RxErrOtherCount | 其他类型的接收错误 |
RxErrFcsCount 持续增长:射频干扰严重,检查是否有 2.4GHz WiFi 或微波炉等干扰源,考虑换信道。
RxErrSecCount 非零:安全层失败,可能是网络密钥不一致或有未授权设备尝试通信。
RxErrUnknownNeighborCount 突增:有新设备加入或附近有其他 Thread 网络干扰。
MLE 计数器(0x000E - 0x0015)MLECNT
MLE(Mesh Link Establishment)层事件计数,反映设备在 Thread 网络中的角色变化和附着行为。
所有字段均为 uint16 类型,需要 MLECNT Feature。
| ID | 名称 | 说明 |
|---|---|---|
0x000E | DetachedRoleCount | 进入 Detached(脱离)状态的次数 |
0x000F | ChildRoleCount | 变为 Child(子节点)角色的次数 |
0x0010 | RouterRoleCount | 变为 Router(路由器)角色的次数 |
0x0011 | LeaderRoleCount | 变为 Leader(领导者)角色的次数 |
0x0012 | AttachAttemptCount | 尝试附着到网络的次数 |
0x0013 | PartitionIdChangeCount | 分区 ID 变更的次数(网络分裂/合并) |
0x0014 | BetterPartitionAttachAttemptCount | 尝试附着到更优分区的次数 |
0x0015 | ParentChangeCount | 父节点变更的次数 |
DetachedRoleCount 频繁增长:设备经常与网络断开,需检查信号强度或父节点稳定性。
ParentChangeCount 过高:设备频繁切换父节点,说明周围路由器不稳定或信号边界。
PartitionIdChangeCount 非零:网络曾发生分裂和重新合并,通常是部分节点通信中断导致。
枚举值速查
RoutingRoleEnum —— 路由角色
描述设备在 Thread Mesh 网络中担任的角色。
Thread 网络中的角色从低到高:SleepyEndDevice → EndDevice → REED → Router → Leader。 Leader 本质上也是一个 Router,只是额外承担了管理职责。当 Leader 离线时,其他 Router 会自动选举新的 Leader。
ConnectionStatusEnum —— 连接状态
NetworkFaultEnum —— 网络故障类型
事件(Events)
ThreadNetworkDiagnostics 定义了 2 个事件,用于通知网络连接状态变化和故障发生。
| 事件 | 优先级 | 字段 | 说明 |
|---|---|---|---|
| ConnectionStatus | Info | ConnectionStatus: ConnectionStatusEnum | Thread 网络连接状态变化时触发(连上或断开) |
| NetworkFaultChange | Info |
Current: list<NetworkFaultEnum> Previous: list<NetworkFaultEnum> |
网络故障列表变化时触发,携带变化前后的故障列表 |
事件订阅用途
ConnectionStatus 事件:App 可以订阅此事件来实时感知 Thread 设备的在线/离线状态变化, 比如在设备列表中显示连接状态图标、断开时弹出提示。
NetworkFaultChange 事件:用于监控网络健康状况。当 Current 列表从空变为非空时说明出现了故障; 从非空变为空表示故障已恢复。对比 Current 和 Previous 可以判断是新增故障还是故障恢复。
示例数据
一个 Thread Router 设备的 ThreadNetworkDiagnostics Cluster 典型读取结果(选取关键属性):
{
// --- 网络标识 ---
"0x0000": 15, // Channel = 15(Thread 信道)
"0x0001": 5, // RoutingRole = Router
"0x0002": "MyThreadNet", // NetworkName
"0x0003": 4660, // PanId = 0x1234
"0x0004": "1111111122222222", // ExtendedPanId
"0x0005": "fd11:2233:4455::/64", // MeshLocalPrefix
// --- 拓扑信息 ---
"0x0009": 12345678, // PartitionId(网络分区标识)
"0x000A": 64, // Weighting(分区权重)
"0x000D": 42, // LeaderRouterId(Leader 路由 ID)
// --- 发送计数器(PKTCNT)---
"0x0016": 158432, // TxTotalCount(累计发送总数)
"0x0017": 120050, // TxUnicastCount(单播发送)
"0x0018": 38382, // TxBroadcastCount(广播发送)
"0x0021": 1024, // TxRetryCount(重试次数)
// --- 接收计数器(PKTCNT)---
"0x0027": 203841, // RxTotalCount(累计接收总数)
"0x0028": 185200, // RxUnicastCount(单播接收)
"0x0029": 18641, // RxBroadcastCount(广播接收)
// --- 错误计数器(ERRCNT)---
"0x0006": 0, // OverrunCount(缓冲区溢出次数)
"0x0036": 3, // RxErrFcsCount(FCS 校验错误)
// --- 活跃网络故障 ---
"0x003E": [] // ActiveNetworkFaultsList = 空(当前无故障)
}
实际使用中,通常不需要一次读取全部 60+ 个属性。根据诊断目的选择性读取:
排查连接问题读 RoutingRole + NeighborTable + ActiveNetworkFaultsList;
分析网络质量读各类计数器;了解网络配置读 Channel + NetworkName + SecurityPolicy。
读取前先检查 FeatureMap,避免请求设备不支持的计数器属性。
常见场景
场景 1:排查 Thread 设备离线
- 读取
RoutingRole (0x0001)—— 如果为null或Unassigned,设备未成功加入网络 - 读取
ActiveNetworkFaultsList (0x003E)—— 检查是否有 LinkDown 或 HardwareFailure - 读取
NeighborTable (0x0007)—— 查看邻居列表中的 LQI 和 RSSI,判断信号质量 - 订阅 ConnectionStatus 事件,实时感知连接状态变化
场景 2:评估网络通信质量
- 调用
ResetCounts (0x00)清零所有计数器 - 等待一段时间(如 10 分钟),然后读取计数器
- 计算重试率:
TxRetryCount / TxTotalCount,超过 10% 说明链路差 - 检查
RxErrFcsCount—— 非零说明有射频干扰 - 检查
TxErrCcaCount—— 持续增长说明信道拥挤,考虑换信道
场景 3:了解网络拓扑
- 读取
RoutingRole (0x0001)—— 确认设备的网络角色 - 读取
LeaderRouterId (0x000D)—— 找到当前 Leader - 读取
NeighborTable (0x0007)—— 获取邻居节点列表和链路质量 - 读取
RouteTable (0x0008)—— 查看路由拓扑和路径开销 - 读取
PartitionId (0x0009)—— 确认所有设备是否在同一分区
场景 4:监控网络稳定性
- 读取 MLE 计数器(需 MLECNT Feature):
DetachedRoleCount (0x000E)—— 频繁脱离说明连接不稳定ParentChangeCount (0x0015)—— 频繁换父节点说明周围路由器不稳定PartitionIdChangeCount (0x0013)—— 非零说明网络曾分裂
- 订阅 NetworkFaultChange 事件,及时感知故障发生和恢复
- 定期对比计数器增量,建立网络质量基线