【蓝牙mesh】access层(接入层)协议介绍
Access层简介
Access层定义了应用层如何使用upper协议层的接口,它不仅定义了应用层的格式,还定义了应用数据在upper层的加密和解密。当收到下层的数据包时,它会检查数据的netkey(网络密钥)和appkey(应用密钥)是否正确,如果数据正确则将数据提供给应用层处理。
总的来说,Access层从数据流的角度来讲,并不属于某一个单独的协议层, 它只是制定了一系列的网络传输规范的,这点很类似于BLE中的GAP层。
概念介绍
Model ID
Model ID 是一个16Bit 或者32Bit的一个数值。用来表示设备的某个功能模块,比如onoff model, lightness model。
那16Bit的Model ID 和 32Bit的Model ID有什么区别呢?
16Bit的Model ID 是有蓝牙技术联盟分配的。 如下图是Sig制定的几个Model ID
32Bit的Model ID是由各个厂商自定义的Model ID。32Bit的Model ID分为两个部分, 前16Bit是蓝牙技术联盟给各个厂商分配的Company ID, 后16Bit是才是厂商自定义的Model ID。格式如下:
至于各个厂商的Company ID, 可以再蓝牙技术联盟官网查询,链接:https://www.bluetooth.com/specifications/assigned-numbers/
下图就是根据文档搜到的杭州涂鸦智能的Company ID 为 0X07DO, 其他公司的Company ID可以自行搜索。
Access层payload数据
Access层数据每包长度为12个字节,如果超过则底层会进行分包,最多分包32包,所以Access层能够传输的最大数据是384个字节。当然这是包含了TransMIC的长度,如果TransMIC长度为4个字节,则Access层Payload最大380个字节。其次,还要减去对应的Opcode的长度。 如果Opcode长度为1,则Payload为379个字节;pcode长度为2,则Payload为378个字节;pcode长度为3,则Payload为377个字节,厂商自定义的Opcode都是3个字节。
Access层的数据包格式如下图:
那什么是Opcode?
Opcode(操作码)
Opcode可以是1、2、3个字节。第一个字节的最高两位表示Opcode的长度。如下图:
第一个字节的最高位为0表示Opcode是一个字节,
第一个字节的最高两位是10表示Opcode是两个字节
第一个字节的最高两位是11表示Opcode是三个字节。
1个字节的Opcode和2个字节的Opcode是蓝牙技术联盟定义的,用作网络信息配网的数据包和应用传输的数据包中。
3个字节的Opcode是厂商可以自行定义的,但是也不是三个字节都可以自定义。 Opcode中的第二和第三个字节表示的是厂商的Company ID, 只有第一个字节的低6个Bit可以由厂商自定义,也就是说一个厂商可以自定义64个字节的Opcode。
Acces层的功能
发送数据
发送的源地址必须是一个单播地址,即发送方只能是某一个设备。 发送的目的地址可以是单播地址、群组地址或者虚拟地址。
如果发送方发送了一个带回复的数据包到一个单播地址,即数据发给某一个设备,则接收方在收到数据后,应该延时20-50ms后,回复数据包。
如果发送方发送了一个待回复的数据包到一个群组地址,即一对多,则接收方在收到数据后,应该延时20-500ms后,回复数据包,这样是为了避免多个接收方同时回复数据,导致回复数据的网络干扰,减少丢包率。
通常设备节点在状态发生变化的时候,会立即上报状态给订阅的节点。但是如果设备是刚上电的时候上报状态,则应该延时20-500ms,以防止多个设备同时上电导致的上报数据干扰。
由于蓝牙Mesh网络的带宽较小,所以应该注意节点发送数据的频率,一个节点在10秒内发送的数据包最好不要超过100包。
接收数据
当节点收到一包蓝牙Mesh数据后,应该经过下面几步判断,如果条件都满足才进行处理:
- 通过Opcode判断到该数据包是当前设备model使用的
- 目的地址满足下面其中一条:
- 目的地址是当前设备的单播地址
- 目的地址是当前设备订阅的组地址或者虚拟地址
- 目的地址是0xffff之类的特定地址
- 该消息用来加密的appkey或者devkey是当前model已经绑定了的
无需ack的数据包
蓝牙Mesh可以制定消息是否需要回复,例如像一个群组发送应用消息,很多时候会使用noack的数据包,这样可以避免群组内多个设备同时回复造成的网络风暴。 但是这样也有一个概率性丢包的问题,因为发送方不知道接收方到底有没有收到这条消息。 所以noack的消息更适合一些不太重要场景的群组控制。
需要ack的数据包
蓝牙mesh中大部分的数据都是需要ack的,如果发送方在一定的时间内没有收到接收方的ack,发送方可以进行重发,来保证数据包的必达。 但是对于节点内比较多的网络, 最好不是在全组群发需要ack的数据包,应该首先确定有哪些设备需要发送,然后针对这些设备来进行群控,而不是一股脑的全控。
发布和订阅
节点里每个model都可以订阅一个或多个地址,地址可以是群组地址或者虚拟地址。 发送方向这个订阅地址发送的消息,会被订阅这个地址的设备接收到。