持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
一、 States
一个节点的状态,比如 onoff States
、lightness States
二、Bound states
两个相互关联的 states,比如 onoff
和 lightness
。
- 当
onoff
的值由 1 变为 0 的时候,lightness
的值也会变成 0 - 当
onoff
的值由 0 变为 1 的时候,lightness
的值也会由 0 变为关灯之前的lightness
的值 - 同理,当
lightness
的值在 0 和非 0 之间变化时,onoff
的值也会由 0 变为 1。
三、Messages
就是把加密完成后,发送到 mesh 网络中的 packet,我们也叫做 mesh packet
、mesh command
。
四、Node & Elements
Node 表示一个完整的节点或者蓝牙模块,Element 表示 Node 里面的某个操作元素。
Node address
有且只有一个element address
可以是一个或者多个- 当
element address
是多个的情况,这些 address 都会是连续的 - 第一个
element address
又叫做primary address
- 当
Node address
的值和primary address
相同。
比如:
- 插座产品(3通道)的
element
个数是3个,3个generic onoff
控制命令,分别控制3个通道的开关; - 色温灯(CT Light)的
element
个数是2个,2个generic level model
,分别对应lightness
和Temp
; - HSL 灯(RGB 灯)的
element
个数是3个,3个generic level model
,分别对应lightness
、Hue
和Sat
。
在组网的时候:
Node
会在 provision flow 的交互信息里面上报 element 的个数,比如 2;provisioner
会分配一个地址给Node
,比如是 0x0002;Node
收到后,会按顺序分配 0x0002给element 1
, 0x0003 给element 2
;Provisioner
在对下一个节点进行组网的时候,会从0x0004 开始分配。
五、Publish & Subscribe
Publish
是 Element
主动发送 status 的过程
- 通过
Config Model Publication Set
命令配置 publish address,以及设置周期 publish 参数。 - 当配置了 publish address 后,只要状态发生变化,Node 都会自动执行 publish status 的动作。是否需要周期发送,就要看周期 publish 的参数。
Subscribe
是 Element
接收数据并处理的过程
- 通过
Config Model Subscription Add
,Config Model Subscription Virtual Address Add
等命令添加Subscribe list[]地址 Subscribe list[]
里面是group address
或者virtual address
,不能是unicast address
,也不能是 0xffffElement
接收到别的节点 publish 出来的 status message(比如 generic onoff status),或者 control message(比如 generic onoff)- 根据 model 的
Subscribe list[]
来判断是否处理该 message。
判断是否接收并处理的依据是:
- 当收到
message
的destination address
为非unicast address
,则判断是否能在对应 model 的 Subscribe list 的 address 里面匹配到。 - 当收到
message
的destination address
为unicast address
,则判断和自身的element address
是否匹配。 - 当
destination address
为 0xffff,则表示符合判断条件。
六、Security
6.1 access layer加密
- 使用
app key
或者device key
对整个 access layer(包含 op code,parameters)进行加密 - 如果 op code 对应的 model 是 config model,则使用
device key
,否则使用app key
。
6.2 network layer加密
- 使用
network key
+iv index
对整个 network layer 进行加密 - network layer 就是发送到 mesh 网络中的 packet,包含 source address、destination address 和 sequence number 等。
6.3 app key
- SDK 默认支持2个
app key
(APP_KEY_MAX
)。 - 多个
app key
可以用于管理不同安全级别的产品。
比如
- mesh 网络里面既有灯,也有门锁
- 如果需要门锁的安全级别更高的话,只有某些人能控制
- 此时可以通过单独给门锁分配一个独立的 app key,并且保证这个 app key 只有某些手机 app(provisioner)知道,在进行网络分享的时候,也不会分享出去。
这样就可以提高安全级别。
6.4 network key
- SDK 默认支持2个
network key
(NET_KEY_MAX
) - 多个
network key
可用于管理多个 network。
6.5 其他
对于需要分包的 message,因为 access layer 的 payload 在加密的时候是整个 payload 进行加密的,所以需要接收到所有的 packet 后,才能完成解密和校验。
七、Sequence Number
Sequence Number 简称 SNO
或SEQ
7.1 SNO 自增判断
SNO
每发完一次命令都会进行累加- 接收端在进行
SNO
判断的时候,要求大于已经收到过的值,如果小于等于则认为是无效的 message
7.2 SNO 存储处理
如果发送端每发送一个命令后,都要把 SNO
存储到flash 中,这个存储频率太高了,特别是在需要分包发送的时候。由于flash读写次数有限。所以修改成:
- SNO增加了
MESH_CMD_SNO_SAVE_DELTA
(默认 0x80),才存储一次 - 在上电初始化时,把读取到的
SNO
加上MESH_CMD_SNO_SAVE_DELTA
(为了能保证在断电并重新上电后的SNO
大于已经使用过的值)
具体实现部分,请参考 mesh_flash_save_check()和mesh_misc_retrieve()关于MESH_CMD_SNO_SAVE_DELTA 的处理。
八、Friendship
Friendship 是指 Friend Node
(FN
)和 Low Power Node
(LPN
)之间通过规定的 establish friend ship flow 建立的关系。
- 在 friend ship 建立成功后,
LPN
在 sleep 期间 - 当有节点发命令给
LPN
时,FN
会先把这个 message 先保存下来 - 当
LPN
唤醒后,会发送 POLL 的查询命令给FN
,此时FN
就会把保存的 message 发送给 LPN - 这样就能达到较低的功耗,缺点是
LPN
对命令的接收和响应有一定的延迟。
8.1 Friendship建立流程
sequenceDiagram
LPN(低功耗节点) ->> FN(朋友节点): Friend Request
FN(朋友节点)->>LPN(低功耗节点): Friend Offer
LPN(低功耗节点) ->> FN(朋友节点): Friend Poll
FN(朋友节点)->>LPN(低功耗节点): Friend Update
Note right of LPN(低功耗节点): LPN(低功耗节点)进入休眠
8.2 Friendship处理流程
sequenceDiagram
Mesh节点 ->> FN(朋友节点): 发给LPN的消息
FN(朋友节点) ->>Mesh节点 : 代表LPN回复
Note left of LPN(低功耗节点): LPN(低功耗节点)退出休眠
LPN(低功耗节点) ->> FN(朋友节点): Friend Poll
FN(朋友节点)->>LPN(低功耗节点): Message 1
LPN(低功耗节点) ->> FN(朋友节点): Friend Poll
FN(朋友节点)->>LPN(低功耗节点): Message 2
Note left of LPN(低功耗节点): LPN(低功耗节点)进入休眠
九、Features
9.1 Relay feature
Relay中继的作用主要是:让消息在节点中扩散开,多级跳,实现 mesh网络传输距离更远。
但是 为了防止消息无限循环扩散,不消失 。所以做了如下一些限制
- 节点收到有效的 network message
- 先把 message 的 TTL 值减 1,再relay 发送出去
- 如果收到的 TTL 的值小于等于 1,则不进行 relay
引入 TTL,主要是控制最后收到该 message 的节点的 delay 时间在可控范围内。
- SDK的TTL的值默认是
TTL_DEFAULT
(0x0A),可以修改这个宏 - provisioner也可以通过
Config Default TTL Set
配置,最大值是 127
9.2 Proxy feature
proxy 是用于手机 APP 接入 mesh 网络的协议。
- 在 mesh 网络中,APP也是一个独立的节点,有自己的 Node address。
- 引入 proxy,是因为目前大部分手机不能完全自定义发送广播包,以及不能一直处于监听mesh网络的状态(中间要切换到WiFi等)
- 所以手机 APP 需要通过 BLE GATT 连接一个节点,直连节点收到 APP 发过来的数据后会转发出去
- 当直连节点收到 mesh 网络中回复给 app 的 message 后,会先通过 GATT 按 proxy协议回复给手机 APP
9.3 App直连feature
APP 下发 message 给直连节点用的是 ATT_OP_WRITE_CMD(0x52)
,直连节点回复
message 给 APP 用的是 notify,即 ATT_OP_HANDLE_VALUE_NOTI
(0x1B)。
9.4 Low Power feature
八、Friendship
9.5 Friend feature
八、Friendship
十、Mesh网络拓扑图
觉得好,就一键三连呗(点赞+收藏+关注)