最近有时间将之前整理的,关于蓝牙mesh开发学习过程的一些笔记,以及一些对mesh协议文档理解的翻译文档,发布出来给大家一起学习和参考,主要是一个学习的过程参考。
蓝牙Mesh通过网状网的组网结构,可以实现室内的大范围网络覆盖。节点(Node)组成了蓝牙Mesh的主干网络,在Node之间使用了低功耗蓝牙的技术进行对连,而具有不同能力特性的节点在网络中承担了不同的角色。
承担网络角色,需要节点之间遵守蓝牙Mesh的语法(通信规则、数据格式)进行对话,通过协商组成网络并向应用提供网络路由服务。
节点间的网络协商过程,是通过“消息携带组网信息”,从“源地址向目的地址传递”,并形成“网络信息的交互”而构成的。
1.网络地址
蓝牙Mesh网络中,统一的地址长度为16位,分四种类型:单播地址(unicast address)、组播地址(group address)、虚拟地址(virtual address)、未分配地址(unassigned)。
(1)单播地址(Unicast Address)
单播地址在蓝牙Mesh网络中具有唯一性,可以标识出节点内的一个元素,节点在接入网络的时候被分配获得。一个mesh网络可以有32767个单播地址。
(2)组播地址(group address)
组播地址即是多播地址,标识一个或多个元素。SIG预定义了四类组播:“All-proxies”, “All-friends”,“All-relays” 和 “All-nodes”。开发者也可以将多个元素自定义到一个多播地址,便于应用的统一控制和管理。
(3)虚拟地址(Virtual Address)
虚拟地址可以赋给一个或多个元素,且可以由多个节点共有。虚拟地址类似于标签,可以在设备出厂前就配置,标签可以使得节点容易在网络被识别和应用。例如,可以表示某个厂商生产的某一个特定型号的摄像头。
(4)未分配地址(unassigned)
16位全零的地址,表示元素还没有配置地址。
2.消息(Message)
蓝牙mesh网络通过消息承载数据信息进行通信。一个节点可以通过消息来询问其它节点的状态,也可以将自己状态消息发送给别的节点。在蓝牙mesh技术规范中,定义了很多种类型的消息。
在蓝牙mesh网络中,无论节点间相距多远,所有节点均可以订阅某一节点发布的状态数据。
(1)消息的应用类型:
消息有两种应用类型:控制消息(Control Message)和接入消息(Access Message)
控制消息(Control Message),是与蓝牙mesh网络操作有关的消息,例如Low Power Node和Friend Node之间的连接请求消息。
接入消息(Access Message),该类消息会携带节点中的模型和状态值,用来实现节点之间对模型状态的查询和控制。应用层通过接入消息中的操作码(opcode) 和参数,来识别并执行设备的相关操作。
接入消息有两种交互类型:有应答(acknowledged)消息和无应答(unacknowledged)消息。
有应答消息:表示该消息需要“提问-应答”式的交互,消息发送方需要接收方的响应。响应消息携带相关的状态信息,以向发送方表示某种操作执行成功,并反馈操作执行后的状态值。如果没有响应,发送方可以重复发送该消息。
无应答消息:发送方向接收方发送消息,但不需要回复。
(2)消息的操作类型
消息中包含三种消息的操作类型:GET、SET、STATUS。三种操作类型对应三种信息操作的方式:
GET:发送节点使用GET消息,向一个或多个节点请求元素模块中的状态值。
SET:发送节点使用SET消息,向一个或多个节点设置或改变某些状态值。
STATUS:该消息是应答消息,是对GET消息或SET消息的响应。STATUS消息中会携带当前的状态值,返回给GET/SET消息的发送节点。
3.节点模式
根据节点在实际应用中承担的不同角色,将其分成三类模式:服务器模式(Server Model)、客户端模式(Client Model)、控制模式(Control Model)。
(1)服务器模式(Server Model)
“服务器”,可以理解为“处理器”和“执行器”,其对两部分内容进行了定义:
数据的定义:定义了元素模型中的状态属性(格式、类型)和相关消息。状态属性包括状态(state)、状态转换(state transitions), 状态绑定(state bindings)等等。
行为的定义:定义了各类实体操作(Behaviors),以及这些操作和状态参数的对应关系。例如,当蓝牙电灯就收到一个“开关状态为‘On’”的消息时,它就给灯泡通电发光。
(2)客户端模式(Client Model)
“客户端”可以理解为“操作端”或“触发器”,它没有状态信息,但定义了消息的格式和收发方式,用于获取“服务器”提供的应用服务:发送信息、查询状态、控制开关、调节级别等等。“客户端”就像是电视机的遥控机,由人来操作并切换电视频道。
(3)控制模式(Control Model)
控制模式兼具了服务器模式和客户端模式,并且还定义了各模式之间数据交互的处理逻辑(规则和行为),即称为“控制器逻辑(Controller logic)”。
4.Publish/Subscribe 发布和订阅
在实际应用中,节点发送应用消息的行为称为“发布”。消息的发布方向是组地址或者虚拟地址。在应用设计中,组地址或者虚拟地址通常代表一个空间区域或同一类设备,易于用户和应用系统统一辨识和使用。
“订阅”就是某个节点被配置成可以接受某个特定消息。换一种说法,节点“订阅”了某消息,就意味着它可以读取该消息的内容。
生成消息的节点(客户端)“发布”消息,使用消息的节点(服务器)“订阅”消息。
发布和订阅关系举例:
在由电灯和开关组成的蓝牙Mesh网络应用中:
(1)开关1可以发布消息到厨房组地址
(2)电灯1号、2号、3号订阅了厨房组地址的消息
(3)开关2可以发布消息到客厅组地址
(4)电灯3号订阅了客厅组地址的消息
当开关1发布消息(其模型中携带“开灯”的状态)至蓝牙Mesh网络时,因为存在订阅关系,所以电灯1号、2号、3号接收到开关1的消息,会执行其中表达的指令---将灯(1号、2号、3号)点亮。
当开关2发布消息(其模型中携带“关灯”的状态)至蓝牙Mesh网络时,因为存在订阅关系,所以电灯3号接收到开关2的消息,会执行其中表达的指令---将灯熄灭。其他电灯(1、2)虽然也会收到2的消息,但因为它们订阅的消息地址并不包括客厅组地址,所以2的消息会被丢弃。
消息的发布/订阅模式的使用,结合组地址和虚拟地址的配置,可以方便地在蓝牙网络中移除或添加节点,其它在网节点无需做任何配置。
5.节点间的连接类型
各类节点之间形成各种类型的联接,主要有4种:
(1)非中继连接:普通节点之间的连接,两节点之间可以收发数据,但是节点在收到信息后不会转发。
(2)亲友连接(也翻译为“友谊”连接):低功耗节点和亲友节点间的连接,在建立亲友关系后,低功耗节点会定期向亲友节点发送消息,询问是否有自己的消息。亲友节点如果有暂存的低功耗节点的消息,它会将该消息送还给低功耗节点。
(3)中继连接:包括普通节点与中继、代理、亲友节点的连接,中继、代理、亲友节点的相互连接。在该类链接上,会传递普通的蓝牙Mesh广播消息。
(4)GATT连接:没有蓝牙Mesh组网能力的蓝牙设备(具备GATT接口),需要通过代理节点帮其转换连接模式转发信息,这些节点和代理节点之间的连接就是GATT连接。
6.消息转发处理的机制
在蓝牙Mesh中,当一个节点收到一个消息时,它会根据自身的节点角色(模式),与相邻节点间的连接状态、以及收到消息中的网络参数,来决定是否丢弃、缓存、处理,还是转发该消息。
在消息中,影响转发的参数主要有:NID(网络ID,从网络密钥-NetKey 派生而来的唯一公共标识符)、TTL(Time To Live,消息转发最大允许“跳跃-Hop”次数)、SRC(Source Address,源地址)和DST(Destination Address,目的地址)。
接受消息后,转发节点(中继、代理、亲友节点)在转发消息前有两部分的处理工作:消息健康检测、消息转发判定。
(1)健康检测:
在收到消息后,节点先判断该消息的发送源是否是一个已注册节点(以NID作为判定条件),再对消息的数据包做完整性效验(MIC),并对数据包中的源地址、目的地址进行有效性判断,最后确认是存在重复收包的情况,即检查转发缓存(转发队列)中是否已经有该数据包。如果以上步骤中有一项未通过,则该消息会被节点丢弃,如果通过了,则进入下一个转发判定的环节。
(2)转发判定:
如果消息中的目的地址是本节点,则消息会被传递到应用层,不再转发。如果目的地址非本节点,则根据自己的节点角色和数据包中的TTL值来确定是否转发。非转发类节点会将数据丢弃,转发类节点则会检查TTL值是否大等于2,如果满足条件则转发,否则也将数据丢弃。
(3)以图例进行举例:
亲友节点L、M分别和低功耗节点X、Y建立了亲友连接关系
P为中继节点
Q为非中继节点D的代理节点,它本身也是中继节点。
A、低功耗节点X发消息至普通节点A
a) 低功耗节点X在入网时,和亲友节点L建立了“友谊连接”。他在发送消息中将TTL标识设置为“3”,然后发给L,L则会对该消息进行广播,广播前将TTL设置为“2”。
b) 非中继节点B和中继节点P离L很近,它们都能收到L的消息。在收到消息后,B发现消息中的目的地址不是它,而它又不是中继节点,故它会将该消息丢弃。
c) 中继节点P收到L的消息后,先完成健康检测(确认数据包信息无异常),再进行转发判断:发现目的地址不是它,并且TTL值等于2,于是它将TTL改成“1”后广播了该消息。
d) 中继节点Q在作转发判断时,发现该消息的TTL等于1,且该消息的目的地址并不是它,于是就将该消息丢弃。非中继节点B收到P发来的消息,它会采取和步骤2一样的处理方式将数据丢弃。
e) 非中继节点A收到P转来的消息,发现该消息的目的地址是它自己,于是消息在经过通过传输层、接入层的预处理后,被A送到其应用层(模型层)。
B、非转发节点(不支持蓝牙Mesh)D发消息至低功耗节点Y
f) 无Mesh协议栈的蓝牙节点D在入网时,和中继节点 Q建立了“代理连接”,Q作为D在Mesh网络中的代理节点。他将消息中的TTL标识设置为“3”,并发送给Q。
g) Q作为中继节点,将信息(TTL=2)广播出去,节点M和P都收到了该信息。
h) 中继节点P继续广播该消息(TTL=1),节点A、B、L收到后确认消息的目的地址不是自己,且TTL=1,则就将消息丢弃。
i) 亲友节点M收到该消息,发现消息的目的地址是低功耗节点Y,于是将该消息放进缓存。当Y向M发送“轮询(Poll)”消息,查问是否有它的消息时,M会将缓存的消息传给Y。