更新时间:2024-02-02 09:37:23下载pdf
本文主要介绍蓝牙 Mesh 的主要组网机制与基本概念。
蓝牙 Mesh 是基于蓝牙 LE 4.x 协议实现的组网协议,并在蓝牙的 37/38/39 广播信道上进行通信。
同时,受限于蓝牙广播的数据长度,Mesh 最底层的数据包长度也很短。但是 Mesh transport 层支持对上层的长数据进行分包,但是分包会增加发包的耗时。
常用的 Mesh 数据包类型为 Access message 与 Control message,目前业务用到的大部分都是 Access message。
Access message 在 Low transport 层分为 Unsegmented Access message 与 Segmented Access message。
Unsegmented Access message 即不分包 access 数据,最大长度为 15,减去 MIC(4),最大可以 11 字节。11 字节里包括 opcode
,即在用 vendor model 发送数据时,opcode
长度为 3,即 data 最大为 8。
Segmented Access message 即分包 access 数据,单包最大长度为 12,即总长度为 12 × n,n 为分包数。12 × n 中包括 MIC 4 字节,即用户数据为 12 × n - 4,再减掉 opcode
长度才为实际的用户数据长度,即:12 × n - 4 - opcode_len
。如果对于使用 vendor model,则分包数为 n = (data_len
+ 7) ÷ 12,对 n 取整。
在使用数据包很短的控制命令时,命令的成功率与到达的一致性都很优秀,例如:开关命令、照明的调光命名、传感器的数据上报等。所以采用数据命令长度较长的控制方式时,建议不要选择 Mesh 方案,否则不仅无法发挥其优势而且有可能会出现数据延迟与丢包等问题。
蓝牙 Mesh 属于一种低速率的洪泛式组网技术,网络内的节点如果具备转发能力,在收到同一个网络的消息后,如果消息为可转发的消息,则会将消息继续广播出去,以此达到一条 Mesh 数据能在整个 Mesh 网络内快速传递。
洪泛式的组网有优势也有劣势。
存活时间(time to live,TTL)指的是一条广播包可被转发次数,在每条的 Mesh 广播包中都会存在,占用 7 bit。对于 TTL 的值有以下解释:
• 0
:has not been relayed and will not be relayed
• 1
:may have been relayed, but will not be relayed
• 2
到 126
:may have been relayed and can be relayed
• 127
: has not been relayed and can be relayed
节点间通信为广播通信没有特定的路径,relay 节点收到的广播包只要 TTL 值不为 0
,这条广播包就可以被继续转发,同时将广播包中的 TTL 减一。
SEQ 全称 sequence num,每包的序列号。Mesh 的每一包里都有一个长度为 3 个字节的序列号。对于同一个设备在发送 Mesh 数据时,该序列号必须是累加的。
同时,每个 Mesh 设备内部都有一张 SEQ 缓存表,用来缓存接收到的 Mesh 数据包的源地址(src_addr
)和其最新的 SEQ,这张表只存放在 RAM(掉电丢失)中。每收到一个 Mesh 数据包时都要去表里查询,收到的 SEQ 是否大于缓存表同一个源地址的 SEQ。如果小于等于,则认为此数据包为重传包或者不合法数据包,同时丢弃此数据包。
目前,涂鸦的设备默认都具备 Relay、Proxy 能力,而 LPN 与 Friend 特性未使用。
Mesh profile 规范定义了三种类型密钥:
网络密钥 NetKey
:用于网络层的通信加密,只有 NetKey
保持一致,设备所发出的数据才可以被同一个 Mesh 网络内的节点进行传输。
应用程序密钥 AppKey
:用于上层传输层的通信加密,只有 AppKey
保持一致,节点间通信发送的数据才可以被解密成应用数据。网络密钥和应用程序密钥这两种类型的密钥在 Mesh 节点之间是统一的,只有两个密钥保持一致才能进行通信。
设备秘钥 DevKey
:是每个节点唯一的特殊应用程序密钥,即一机一密。只有节点和配网者知道,用于配网者来配置节点通信加密。
前文提到 Mesh 通信使用的洪泛发包,没有路由,发包后也没有收包的 ACK。只有向单播地址发送 Seg 分包数据时才会有 ACK。
所以没有 ACK 就需要靠增加发包数量来提高成功率,也就是应用层发送一条数据时,在 Network 层中会将同样的数据以固定间隔发送多次。同样设备在 Relay 其他设备的包时也会以固定间隔发送多次。这两个间隔与次数即为 Network 层的网络参数,见下表:
参数 | 释义 | 计算值 | SDK 默认值 |
---|---|---|---|
Network Transmit Cnt | 网络层主动发送次数 | 实际发送次数 = cnt + 1 | 7 |
Network Transmit Step | 网络层主动发送间隔 | 实际发送间隔 = (step + 1) × 10ms | 0 |
Relay Retransmit Cnt | 网络层转发发送次数 | 实际发送次数 = cnt + 1 | 4 |
Relay Retransmit Step | 网络层转发发送间隔 | 实际发送间隔 = (step + 1) × 10ms | 0 |
/**@brief mesh node feature. */
typedef enum {
MESH_FEATURE_RELAY = 0x00, /**< Relay. */
MESH_FEATURE_PROXY, /**< Proxy. */
MESH_FEATURE_FRIEND, /**< Friend. */
MESH_FEATURE_LPN, /**< LPN. */
} MESH_FEATURE_T;
OPERATE_RET tkl_mesh_node_features_set(MESH_FEATURE_T featrue, UCHAR_T enable);
您可以调用以上接口来配置 Mesh 设备角色,可以选择关闭 Relay 和 Proxy 能力。另外某些平台 SDK 也可以开启 Friend 能力,根据接口返回结果。目前的通用 SDK 不支持 LPN 节点能力。
关闭部分设备的 Relay 能力后,网络内网络风暴出现的概率会降低,提高网络的稳定性与数据传输的速率。您可以使用此接口来探索和调试网络下不同 Relay 配置的效果。
OPERATE_RET tkl_mesh_node_default_ttl_set(UCHAR_T ttl);
SDK 中设备默认发送的 TTL 为 8,您可以在 OPERATE_RET tuya_init_last(VOID_T)
初始化函数内调用此接口来修改设备发送的默认 TTL。
App 与网关默认 TTL 也为 8,如果要修改的话需要在 App SDK 或者网关 SDK 内修改。
VOID tkl_mesh_network_transmit_set(UCHAR_T cnt, UCHAR_T step);
VOID tkl_mesh_network_relay_retransmit_set(UCHAR_T cnt, UCHAR_T step);
通过以上接口,配置设备的网络层发送参数与 Relay 节点的转发参数。
VOID tal_mesh_state_callback(TAL_MESH_NET_STATE_T state){
tal_main_debug("mesh_state:%d", state);
switch(state){
case TAL_MESH_PROVISION_SUCCESS:
tkl_mesh_network_transmit_set(7, 0);
tkl_mesh_network_relay_retransmit_set(4, 0);
break;
default:
break;
}
}
可以在 Mesh 状态回调内收到配网成功的状态时,更新此参数。不过修改此参数需要对 Mesh 协议有较深的理解,如果不是很熟悉,则使用此默认的参数。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈