目的
此文档的目的在于引导读者思考蓝牙mesh行为,并非一篇完善的mesh行为描述文档。
什么是蓝牙mesh的行为
蓝牙mesh的行为就是指,一个设备在处于某些特定的角色,并开启特定特性时,他是如何组网,并如何进行加解密的,如何进行数据流的传递的,等等,在mesh规范中,常常标有behavior的字样,但规范最大的缺陷是,采用分散描述,并无对某完整的过程进行串行描述,这使得从整体上把握mesh的行为显得比较困难。
举例说明什么是蓝牙mesh的行为
背景描述
假设有一个手机和一个灯,手机可以作为蓝牙主设备与灯进行GATT连接,灯可进行GATT连接的同时又能进行广播数据的发送,灯将relay和proxy特性打开,手机可以作为一个provisioner对灯进行组网操作,那么请描述手机对灯进行GATT连接后的组网过程,配置过程,控制过程等过程的具体行为。
一种行为描述
首先,灯是一个未组网设备,会进行广播,广播分为两种,一种为可连接的未组网广播,另一种为不可连接的未组网网络信标广播,这两者交替进行;
另外,灯设备也会加载provisioning service,并在可连接广播中暴露其服务类型;
手机APP端,会扫描周围灯的可连接的未组网广播,根据广播的AD Type可找到它,最后显示到手机app列表;
手机APP通过BLE连接灯设备,连接后进行service discovery过程,并获取设备的provisioning service,之后使能notify;
然后APP就可以通过发送代理协议数据给灯设备,且灯设备也可以通过代理协议返回应答数据了;
首先说组网过程 ,其中手机充当provisioner角色,此时其代理协议数据类型MessageType为 Provisioning PDU (0x03) :
手机发送 Provisioning invite
灯返回 Provisioning capabilities
手机发送 Provisioning start
手机发送 Provisioning Public Key
灯返回 Provisioning Public Key
手机发送 Provisioning Confirmation
灯返回 Provisioning Confirmation
手机发送 Provisioning Random
灯返回 Provisioning Random
手机发送 Provisioning Data (包含会话密钥)
灯返回 Provisioning Complete
手机主动断开连接。
灯组网完成。
特别说明 :以上过程,每个发送或者返回都可能要分段,数据包长度大于BLE的MTU就要分段,分段采用的策略为代理分段策略,主要控制字段为SAR和Message Type。这与Lower transport layer的分段策略没有任何关系。
通过以上过程,灯就变为一个节点了,已经具备了设备密钥,网络密钥,但还没有应用密钥。
因为灯节点已经是已组网状态,所以灯节点将provisioning service更改为proxy service
同时灯节点变更广播内容,将广播内容改为可连接的node identity广播和不可连接的secure network beacon广播(即安全网络信标)
手机APP重新扫描node id广播,并与之建立GATT连接,之后发现proxy service,然后使能notify
接下来,手机就要对灯节点进行组网后的配置过程了,其中手机充当proxy client,而灯节点则充当proxy server角色。
接下来通过收发以下消息设置地址过滤器 ,此时其代理协议数据类型MessageType为 Proxy Configuration (0x02) :
手机发送 Set Filter Type message
灯返回 Filter Status message
手机发送 Add Addresses to Filter message
灯返回 Filter Status message
地址过滤器设置好后,则可通过以下消息获取灯节点的组成数据 , 此时其代理协议数据类型MessageType为 Network PDU (0x00) :
手机发送 Config Composition Data Get
灯节点返回 Config Composition Data Status
手机发送 Seg Ack Msg(For Config Composition Data Status) :因为我把双方MTU都设置为23了,所以灯节点返回组成数据时在Lower transport layer层分段了,所以手机需要返回该分段应答消息来确认,即告诉灯节点,我收到了你发过来的所有段。(说明:如果只收到了部分段的话,手机也会返回该指令,但后续流程就不一样了,后续灯设备需要补发缺失的段,直到手机发送的ACK中提示自己收到所有的段为止。这是network PDU分段发送专有的应答机制,这种通信增加了传输的可靠性。只要代理协议数据类型MessageType为 Network PDU (0x00) 的数据包,如果发生分段,都需要应答确认,后续不再赘述)
通过以上composition data的获取过程,手机APP了解了灯节点支持哪些feature(例如relay和proxy等),也知道了灯节点由哪些模型(比如general on off service等)组成,同时也知道灯节点的CID、PID、VID、RPL(中继保护列表)数量等等;
接下来,就可以给灯节点下发应用密钥 了, 此时其代理协议数据类型MessageType为 Network PDU (0x00) ,相关指令如下:
手机发送 Config AppKey Add
灯节点返回 Config AppKey Status
接下来,就可以给灯节点模型绑定应用密钥 了,此时其代理协议数据类型MessageType为 Network PDU (0x00) ,相关指令如下:
手机发送 Config Model App Bind
灯节点返回 Config Model App Status message
。。。。。
一般上面发送的指令是成对儿出现的,一次只能给一个模型绑定一个应用密钥,如果有多个模型需要绑定应用密钥,就要发送多次上面的组合,我共绑定了七个模型到上面下发的那个密钥上。
密钥绑定完毕,则配置过程就完毕了,此时手机端和灯节点,均有网络密钥和应用密钥了(当然也有设备密钥--组网生成),且所有模型也都绑定了应用密钥。后续就可以通过手机发送指令控制灯的亮灭了。
控制灯节点亮灭的指令,我没有详细研究,但也是Network PDU的数据,流程与composition data 、appKey下发、appKey绑定等过程相同,后面研究后添加上。
上面就是一个关于mesh行为描述的举例,虽然描述的并不十分完整,但也比直接看规范更能将整个mesh的通讯行为串起来了,更容易弄明白了,我觉得我们需要更多这样的行为描述。
其它行为疑问
对于Network PDU,GATT Client发送的数据是如何通过由代理协议转化为网络层数据的?网络层数据又是如何转化为lower传输层的?lower传输层又是如何传递给upper传输层的?upper传输层又是如何传递给access层的?access层又是如何传输给model层的?模型层处理完数据,应答数据回传的逆向过程又是怎样进行的?等等。
上面提到了灯节点开启了relay和proxy的特性,且手机通过GATT实施代理协议给灯节点发送的provisioning数据、配置过滤器数据、获取composition数据、下发应用密钥数据、下发绑定应用密钥数据、下发灯控命令数据等等,那这其中的哪些数据需要通过ADV BEARER(广播承载)发送出去呢?哪些不需要呢?如果只打开relay特性,关闭proxy特性,又应该怎样呢?如果只打开proxy特性,关闭relay特性,又应该怎样呢?如果两个特性都关闭,又该怎样呢?
posted @
2022-10-20 19:37
unrulife
阅读(
328 )
评论()
编辑
收藏
举报
点击右上角即可分享
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通