1. Mesh概览
1.1. mesh消息的收发
mesh消息收发方式区别于ble的连接方式,而是通过消息的发布(publish)与订阅(subscribe)进行消息的传递。
mesh的数据包主要包含有以下字段:
其中IVI/NID/CTL/TTL/SEQ暂不做解释,其中SRC/DST就代表这条消息是从哪里发来的和这条消息是要发送到哪里去。
a.每个节点都有一个发布地址和多个订阅地址。
b.发送端将要发送的消息(msg)发送至一个地址(address),该地址包含在数据包里面,接受端对每一条收到的消息进行解析,判断该地址是否是自己订阅的,如果订阅了该地址则接收该消息。
c.每一个节点既是发送端,又是接收端。
1.2. address
上面我们谈到mesh消息的收发都是依靠地址(address)这一数据段,在数据包中共占用了2个字节(16bits)。address分为四种类型:
address type | value | description |
unsigned address | 0x0000 | 全0,共计1个 |
unicast address | 0x0001 - 0x7FFF | 最高1位为0,共计32767个 |
virtual address | 0x8000 - 0xBFFF | 最高2位为10,共计16384个 |
group address | 0xC000 - 0xFFFF | 最高2位为11,共计16384个 |
a. 无效地址(unsigned address)
可以作为地址的初始化值,或者手动设置该值,使某些关于地址的操作无效化。
b. 单播地址(unicast address)
每个节点都有一个单播地址,作为该节点的唯一标识。
c. 虚拟地址(virtual address)
虚拟地址是由一组128-bit的label-UUID hash而来,可以通过传入相同的label-UUID给不同节点,使他们订阅相同的虚拟地址,则可以把这些节点划分为同一组。这样可以大大地增加组的数量。由于virtual address是hash而来,所有有一定的概率存在冲突。
d. 组播地址(group address)
组播地址共有16384个,其中SIG固定了256个地址,剩下用户可使用的组播地址共16128个。
value | Fixed Group Address Name |
0xFF00 -0xFFFB | RFU |
0xFFFC | all-proxies |
0xFFFD | all-friends |
0xFFFE | all-relays |
0xFFFF | all-nodes |
关于proxy/friend/relay属于mesh节点的特性,以后再讲。只需要知道的是:
地址0xFFFC表示发送给所有的支持代理功能的节点,每个支持代理功能的节点都需要订阅0xFFFC;
地址0xFFFD表示发送给所有的支持友谊功能的节点,每个支持friend功能的节点都需要订阅0xFFFD;
地址0xFFFE表示发送给所有的支持中继功能的节点,每个支持中继功能的节点都需要订阅0xFFFE;
地址0xFFFF表示发送给所有的节点,每个节点都需要订阅0xFFFF;
publish时使用的地址类型有unicast/virtual/group address。
subscribe时使用的地址类型有virtual/group address。
publish时使用virtual/group address地址类型的消息,只有订阅了相同virtual/group address地址类型的节点才能收到该消息。
publish时使用unicast address地址类型的消息,只有指定该unicast address的节点才能收到该消息。
1.3. 子网
如果要把同一区域分成多个独立的区域,使各个区域能不受其他区域的影响,所以就有了子网的概念。
首先每个节点至少有一个128-bit的Netkey,具有相同Netkey的设备之间能够相互通信。有多个Netkey的节点能够在多个子网中通信。
由于128-bit的Netkey不好管理,所以将Netkey进行统一的编号,生成一个12-bit的Netkeylndex,可以知道NetkeyIndex最多有4096个。
其中NetkeyIndex=0x000的子网被称作主子网。
那么谁来对所有的Netkey进行编号呢?这就是配置客户端(Configuration Client)所做的事情之一,包括之前提到的节点pub/sub地址的设置,都是Configuration Client的任务之一。这里对主子网和配置客户端先不做过多介绍,知道有这个概念就行。
1.4. IV/Sequence Number
由于mesh网络是泛洪网络,没有建立链接,所以不能保证消息的可靠传输,因此发送出来的消息通常采取的策略是多发几次,那么问题来了,我们怎么保证同样的消息我们只需要处理一次呢?mesh数据包里面增加了Sequence Number数据段,为24bit的SeqNum,该SeqNum是严格递增,保证了同一个节点发送的每次消息的SeqNum都是不同的。因此接受端只需要缓存上一次该节点消息的必要信息就可以过滤掉重复的消息。 当然过期的消息我们也不需要处理,因此就有了一个列表,叫做重传保护列表(replay protection list)。它缓存了已接受节点消息的SeqNum,当接收的SeqNum小于等于的缓存的SeqNum,则该消息会被抛弃。 重传保护列表的大小决定了当前节点能处理多少不同节点的消息。不同节点的内部SeqNum是相互独立的。 因为SeqNum只有24bits,所以假设我们发送消息的频率是10,那么19天就会耗尽。因此增加字段32bits的IV值,IV值加上SeqNum组合成56bits的SeqAuth值,那么要消耗完所有的IV和SeqNum需要2亿年。因为IV值变化是很缓慢的。所以我们一般取IV值的最低有效位,即IVI,这就是数据包中的第一个字段IVI的含义。
1.5. publish/respond
mesh的消息分为主动publish和被动respond。节点发送需要响应的消息,则期待对端响应一个消息,即对端收到需要响应的消息时,需要respond一个消息回原地址。而节点发送不需要响应的消息,则不会等待respond。这里涉及的重传次数,重传周期,都由配置客户端配置。
1.6. 总结
a.消息通过Pub address,Sub address进行通信,Pub address在数据段中作为DST地址。b.每个节点都有一个Unicast address作为唯一标识,在数据段中作为SRC地址。c.节点通过NetKey和Sub address判断是否是属于自己的消息。d.节点通过IV和SeqNum来过滤重复的消息。
2. Mesh Feature
Mesh中一共有4个Feature,分别是代理(Proxy),中继(Relay),Friend和LPN。
2.1. 代理(proxy)
若某一节点A(通常为手机)不能通过ADV广播的方式收发mesh包,但支持常规的GATT连接方式;节点B除了支持mesh协议可以通过ADV的方式接收mesh包外,还支持GATT常规的连接方式;节点C(Mesh大部分节点)只支持ADV,不支持GATT。那么节点的消息可以通过GATT连接来进行代理。
节点C传送至节点A的广播消息可以通过节点B进行proxy转发,将ADV的消息转化成GATT格式,发送至节点A,从而使节点A收到该消息。
节点A传送至节点C的GATT消息可以通过节点B进行proxy转发,将GATT的消息转化成ADV格式,发送至节点C,从而使节点C收到该消息。
代理详细内容见Bearer Layer。
2.2. 中继(relay)
由于mesh消息传递使用广播的形式,所以传播的距离有限,因此增加中继的特性,扩大节点的传送范围。当节点收到消息时,先判断该消息是否是属于本网络,再决定是否进行中继转发。
一条消息肯定不能无限制的转发,这样会造成网络拥堵,所以这里采取的两个措施:
a. Network message cache
每个节点都有一个缓存,存储最近收到消息的部分信息,主要有NID,SRC,SeqNum。NID是由NetKey生成的7bit字段,SRC是发送端的单播地址。可以通过判断SeqNum来过滤中继消息。此时的Network message cache可以和之前的Relay protection list具有相似的功能,可以合在一起。
b. Time to live(TTL)
上面的消息缓存从空间上避免了消息的泛滥,这里的TTL则从时间上避免消息的多次中继。每段消息都有一个7-bit的TTL字段(最大值为127),该消息每被中继一次,该TTL值就会被减1。若TTL等于1,则该消息不能被中继。TTL的大小需要通过配置客户端设置。
mesh的数据包是要经过加密的,那么我们收到需要中继的包,获取里面的信息需要解密,但是解密后该中继节点就能得到消息的所有内容,这明显是不安全的,所以就出现了AppKey,AppKey同NetKey一样,也是由配置客户端生成的128-bit的key,关于消息的主体内容都是通过AppKey加密,加密完成后,在下一层对NID,SRC,SeqNum,TTL等再进行二次加密。同一个网络里面的节点具有相同的NetKey,但是只有发送端和接收端才有相同的AppKey,这样就把中继的消息和应用的消息有效的隔离开来了。
2.3. friend/lpn
BLE全称Bluetooth Low Energy,意思是蓝牙低功耗。那么如何在mesh上体现出低功耗的特性呢?所以引入两个feature,分别是Friend和Low Power Node(LPN)。
a. LPN
低功耗节点,该节点长时间处于睡眠状态,在指定时间唤醒,唤醒期间处理所有睡眠期间的消息,处理完消息后再次进入睡眠状态。
b. Friend
友谊节点,在LPN睡眠期间,替LPN缓存消息,当LPN唤醒时,将缓存的消息发送至LPN。
一个LPN只能与一个Friend节点建立友谊关系(friendship),一个Friend节点可以与多个LPN建立friendship
Friend相关内容见Friendship。
3. Mesh分层架构
前面大体介绍了Mesh的基本概念,接下来要详细分析Mesh要实现所提到的功能,协议栈是如何设计的。
Mesh架构主要分为以下7层:
从图中可以看出,Mesh是架构在BLE协议栈之上的,其实Mesh只需要蓝牙的广播(adv)和扫描(scan),以及为Proxy添加的GATT功能就行,因此Ble4.2就能满足要求。
Mesh Profile里面从Bearer层往上讲到Model层,我这里反过来讲,从App层讲到Bearer层。下面先简单讲讲各层的基本功能。
① app layer
app负责组织各个model,将多个模型组合形成app的功能。详见Ble Mesh技术(二)之App Layer。
② model layer 一个model实现一个单一的功能。model消息的通信依靠client和server,一般来讲client发set/get消息,server收到后响应status消息。详见Ble Mesh技术(三)之Model Layer。③ access layer model的数据通过access层的接口将数据下发下去,从下层来的数据通过access层判断该数据上报至哪一个model。详见Ble Mesh技术(四)之Access Layer。④ upper transport layer 这一层第一个功能是将应用的数据进行加密下发至下一层,将下一层的数据解密上报至上一层。另一个功能是传输控制消息,所谓的控制消息就是非应用数据,用于控制流程的消息,主要有lpn/friend相关的非应用交互消息。详见Ble Mesh技术(五)之Upper transport Layer。⑤ lower transport layer 该层主要控制消息的分段和重组。保证上层的消息顺利发送出去,以及对端消息的完整性。详见Ble Mesh技术(六)之Lower Transport Layer。⑥ network layer 控制消息的中继和代理,以及网络数据的加解密。详见Ble Mesh技术(七)之Network Layer。⑦ bearer layer 消息发送和接收的接口,通过adv还是GATT。详见Ble Mesh技术(八)之Bearer Layer。
接下来的文章将依次对各层进行详细的介绍。