Mesh学习笔记-入门篇

参考资料:
https://zhuanlan.zhihu.com/bluetooth-mesh
https://blog.csdn.net/weixin_40204595/article/details/81672523 一、Mesh关键术语
(1)设备和节点
一个Mesh设备,在未配入Mesh网络时,叫“设备”,当被配置加入一个Mesh网络后,叫“节点”。 比如,去超市买了个蓝牙mesh的灯,用之前就是个设备。等到把它连上建立的Mesh网络,可以和开关什么联动的时候,它才是一个节点。

(2)元素
定义:是在设备中可以寻址访问的实体。比如一个灯,其中有三个子灯,那么这一整个灯,就叫一个节点(当然指的是在入网后),这三个子灯就叫这个节点的元素,每个子灯都可以独立被控制。如下:
在这里插入图片描述
每个节点至少拥有一个元素,称为主元素(Primary Element),同时还可能包含其他多个元素(图3)。元素由定义节点功能和元素条件的实体组成。例如,一个灯泡内有一个元素, 并具有两种功能:

  • 节点 = 灯泡*
  • 一个元素 = 主元素
    • 节点功能
  •   		- 开/关                    
    
  •   		- 亮度
    
    • 元素条件/状态
  •   		- “开”或“关”                    
    
  •   		- 0 – 10 (亮度等级)
    

在这里插入图片描述
图 3 –节点必须至少有一个元素,也可能包含多个元素
节点中的每个元素都有一个唯一的地址,称为单播地址(unicast address),使每个元素都有址可寻。我们将在后续的解密蓝牙mesh系列文章中进一步解释“寻址”。

(3)消息
消息是蓝牙Mesh里的一个重要概念。当一个节点需要查询别的节点的状态(Status)或者控制别的节点的时候,就需要发一个对应类型的消息。当一个节点向其他节点报告状态改变的时候,它也需要发出一个消息。在蓝牙Mesh里面定义了很多种类型的消息,每种消息都有对应的操作码(opcode)。消息可以按照有应答(acknowledged)和没应答(unacknowledged)来分类。 和大多数的通讯系统一样,有应答的消息需要接收节点给个响应

(4)地址
要发消息,我应该发给谁呢?那一定会从一个地址发给另一个地址。在蓝牙mesh里面定义了四种类型的地址:
单播地址(unicast address)
组播地址(group address)
虚拟地址(virtual address)
未分配地址(Unassigned Address):未经配置的元素或未被指定地址的元素拥有的就是未分配地址。鉴于这些元素没有唯一的地址,它们不会用于消息的传送。

单播地址可以唯一性的识别出一个元素。这个地址是在配网的时候分配给设备的。一个mesh网络可以有32767个单播地址。在“启动配置”(provisioning)期间,启动配置设备(provisioner)会在网络节点的生命周期内为节点中的每个元素分配一个单播地址。单播地址可能出现在消息的源地址字段或目的地址字段中。发送到单播地址的消息只能由一个元素进行处理。

组播地址是一个表示一个及以上元素的广播地址。
组播地址可以由蓝牙SIG来定义(SIG Fixed Group Addresses), 也可以动态分配。目前SIG定义了4个组播地址,分别是“All-proxies”, “All-friends”,“All-relays” and “All-nodes”。
动态分配的组播地址是设计成在用户配置的时候,可以分配代表一些实际的场所,比如可以定义几个组播地址代表几个不同的房间。一共可以有16384个组播地址,其中SIG保留了256个,其他16128个都是动态分配的。
组播地址是蓝牙mesh网络中的另一种多播地址(multicast address),它通常代表一个或多个节点中的多个元素,包含两种类型:

  • 动态分配的地址(Dynamically Assigned) -> 0xC000-0xFEFF
  • 固定地址(Fixed Address) – 由蓝牙技术联盟分配,分为五段:
  • 保留供将来使用 (RFU) –> 0xFF00-0xFFFB
  • All-proxies -> 0xFFFC - 发送到启用代理(proxy)功能的所有节点
  • All-friends -> 0xFFFD - 发送到启用friend功能的所有节点
  • All-relays -> 0xFFFE - 发送到启用中继(relay)功能的所有节点
  • All-nodes -> 0xFFFF - 发送到所有节点
    发送到固定节点的所有消息都由节点的主元素(primary element)进行处理
    虚拟地址是个挺有意思的概念。虚拟地址是与特定的UUID标签相关联的一组元素;这些地址可能会被发布或订阅。UUID标签是与多个来自一个或多个节点的元素相关联的128位值。
    对于虚拟地址,15和14位分别设置为1和0(如下图);13 – 0位被设置为散列值(hash value)(提供16,384个散列值)。散列(hash)来自于Label UUID。使用订阅元素(subscribing element)来检查完整的128位UUID是十分低效的,特别当UUID跨越多个消息段时更为低效。散列值提供了一种更为有效的方式来确定哪些消息被发送至哪些元素。
    在这里插入图片描述
    简单来说,基本可以认为虚拟地址是组播地址的一个扩展。虚拟地址可以使用128位的标签Label UUID逻辑上来表示。可是每次要传这么长的uuid不是很累?于是有用了哈希值来表示这些UUID。一共有16384个哈希值,每个哈希值代表一串虚拟地址。所以会有非常多的虚拟地址可以使用。按照SIG的说法,虚拟地址不用集中管理,增加了随意性, 更像一个标签。比如每个品牌出产的投影机都可以使用虚拟地址被预配置成一个场景使得以后的寻找会更加简单。

(5)发布和订阅
在蓝牙mesh里面发消息的动作我们叫做发布(Publish)。光从字面意思理解大家基本上就能看懂了。我想告诉别人什么事情发生或者做什么事情就叫做发布。谁对某些消息感兴趣就可以订阅这些内容。就像是在知乎里面,如果是你对哪个专栏或者内容感兴趣, 可以进行订阅。所有发布到这个专栏的文章你都会收到。节点发布消息到单播地址,组播地址或者虚拟地址。节点有兴趣接收这些数据的可以订阅这些地址。如下图:
在这里插入图片描述
这张图是SIG在介绍这一章节的时候使用的例子。我给这些灯和开关标了号以便于理解。在上图中,开关1 发布信息给组播地址”厨房“, 节点灯1, 灯2, 灯3 每个都注册到了”厨房“这个地址上, 因此他们能收到处理发给厨房的消息。换句话说, 灯1,灯2 和灯3 都能被开关1控制开关。 开关2 发布消息到”餐厅“,只有灯3订阅了"餐厅"这个地址,所以只有灯3能被开关2控制。在这个例子里同样说明了每个节点可以订阅多个确切的地址。同样的,你一定也注意到了,开关5和开关6同样都可以发布消息到”花园“。
使用这种方式的一个很大的好处是当需要有一些节点添加,删除或者替换的时候,其他的节点不用重新配置。比如你新买了一个开关,把它配网以后发布到”花园“, 那么”花园“里的灯一样可以被这个新的开关和开关6控制。

(6)状态和属性
在蓝牙mesh中,元素的不同情况叫做状态(States),状态是一个特定类型的值,在每个元素内部存在。除了本身的值以外,状态还有一些相关的行为。 拿灯来说,蓝牙mesh定义了一个状态叫”Generic OnOff.“ 灯收到了一个ON的状态,理解以后就会执行相应的动作比方说 点亮灯泡的行为。还记得属性(Properties)吗?在之前的BLE的规范里, 每一个Characteristic都有自己的属性。但是Characteristic是没有上下文含义的?(什么意思?) 就是说他只是表明了一个量,但这个两你可以用在很多的场合,比如一个温度值,她并没有体现这里温度值和什么相关。在蓝牙mesh里面的属性它提供一个来解释Characteristic的上下文。举个例子。如果有一个Characteristic,叫做Temperature 8,一个8位的温度状态类型,它有着一些相关联的属性, 包含现在室内环境温度和现在室外环境温度。这两个属性允许一个传感器来发布传感器消息,收到的客户端(关于客户端和服务器端的内容我们后面会讲)会根据属性得知到底是哪个温度信息。这样就有上下文的概念啦。

(7)消息、状态和属性的关系
蓝牙Mesh里面,要进行某种操作,就是调用消息这一基本机制。一个给定的消息类型代表了一个对状态的操作或者对多个状态的采集。所有的消息都可以分成三种简单类型。哪三种呢? 想想之前我们说的和状态的关系,对了, 一定有SET,然后还有GET,除了这个一拿一放以外,还有一个STATUS类型。
GET 顾名思义,就是获取一个节点或者多个节点的给定的状态。当收到GET消息以后,STATUS消息就发出来了。当然,它里面带着的是相对应的状态内容。
SET, 也一样,一定是要设置什么。设置什么呢?设置状态! 当收到SET消息之后,要不要有STATUS发出来呢?还记得咱们之前说过“消息可以按照有应答(acknowledged)和没应答(unacknowledged)来分类”这里和GET不一样的是,SET消息分为有应答和无应答两种。如果是有应答的,就会有STATUS消息跟着出来,如果是无应答的话,那就没有应答包啦。
STATUAS 消息,除了刚才说的两种情况会出现以外,也可以在其他的消息中出现,当然也可以独立出现。比方说某个元素用定时器每隔一段时间发送一次。其实在蓝牙mesh里面定义了很多种消息,通过Opcode来区分,还包含了相关联的参数和行为。Opcode可以是单字节,双字节(常见)或者三字节(厂商指定)。所以绝大部分的mesh消息都是对状态进行操作的,只有特别的和属性相关的消息,才会对属性进行操作,而且需要制定16位的属性ID。

(8)状态转换
我们刚才说到了状态的设置和获取,那么在进行状态改变的时候,这种改变可以是立刻发生的,也可以是过一段时间发生的。如下:
在这里插入图片描述
初始化状态(initial State)是指刚收到SET新的状态值的时间。从收到SET消息到状态改变的时间叫做转换时间。从STATUS消息发出(可以在中间的任何时间点)到目标状态完成这个叫保持时间(Remaining time), 所以当你收到STATUS消息的时候,状态可能还没有变化,在STATUS消息里也可以包含离目标状态的变化还有多少时间。 这一部分,我相信各家的协议栈应该都有涉及,等我们分析了各家的协议处理基本就清楚了。

(9)状态绑定
不同的状态之间可能会有一些关系。比如一个状态的变化会造成另外状态的出发,这种关系叫状态绑定。状态的绑定是可以跨Model的,(Model这个重要概念我们马上会提到),也可以在多个元素中。再举个例子,灯光亮度状态和开光状态。当你把亮度状态改到0了,也就触发了开关状态的“关”状态,反之亦然。

(10)Models模型
无论节点位于制造厂房、酒店、办公楼、还是商业园区的网络中,节点的基本功能都由模型 (Model) 来定义和实施。模型位于元素内,元素必须具有至少一个模型(图4A)。模型能够定义并实施节点的功能和行为,而状态 (State) 能够定义元素的条件(图4B)。
在这里插入图片描述
图4A - 节点、元素与模型
在这里插入图片描述
图4B - 节点、元素、模型以及状态之间的关系
以灯泡为例,该模型的功能是开关和调节亮度。相关的状态分别为“开”/ “关”和0-10:

  • 模型 (节点功能)
  •   1. 开/关                    
    
  •   	状态 -> “开”或“关”             
    
  •   2. 亮度 (0-10)                    
    
  •   	状态 -> 0-10
    

蓝牙mesh支持复合状态,即由两个或多个值组成的状态。变色灯就是这样的一个例子,色调可以不受颜色饱和度或亮度的局限而改变。“绑定状态” (Bound State) 这一术语的定义源自一种状态的变化导致另一状态变化的情况。级别状态和开/关状态通常就相互绑定。如果级别从0变为1,则“开/关”的状态也从“关”变为“开”。
每个模型都有唯一的标识符。蓝牙技术联盟采用16位的模型,而供应商采用32位(其中包含蓝牙技术联盟指定的16位公司标识符以及16位供应商指定的模型标识符)。这确保了每个模型的地址都独一无二并且能确定被寻址到。
Mesh包含三种模型:server model(服务器模型)、client model(客户端模型)、control model(控制模型),如下图:
在这里插入图片描述
Server model:定义了状态states, 状态转换 state transitions, 状态绑定state bindings 和包含了哪些消息,当然也同样定义了与这些消息,状态,状态转换相关的行为Behaviors。
* 由至少一个或多个状态跨越一个或多个元素的状态组成
* 定义模型能够发送/接收的消息,并根据这些消息定义元素的行为
* 实例:
* ? 开/关切换——可以暴露开关状态
* ? 传感器——可以暴露传感器的状态(可能为温度值或传感器测量的“满”、“待充”或“空”的结果)
* ? 功率级别——可以暴露电源状态(等级1-10)

Client model:没有定义任何的状态States,但是它定义了要收发那些消息。定义这些消息当然是为了GET,SET或者获取在Server models里面定义的状态. 这张图其实很简单的就把关系说清楚了。比如说一个灯元素,我总要有个地方定义和存放灯的状态比如On/OFF。那它就可以是一个Server model。开关就要定义一个对应的model来读取或者控制这个状态。这能听懂吧。其实在之前的BLE里面,用的也是这样的架构。如下图:
在这里插入图片描述
* 定义客户端为请求、更改或使用服务器相应状态所使用的消息。
* 实例:
* ? 开/关切换——客户端发送打开或关闭的消息
* ? 电源级别——定义电源状态的消息(0-10)

Control Model:还有一种情况,需要同时具备两种模式。比如说一个复杂一些的灯光控制器,它可以根据采集外部的光亮的变化来控制某些灯的开关。那么这种模式下,即有一些状态要被别的元素获得,同时也需要控制别的元素。这种Model在Mesh里面就叫做Control Model。其实就是一个Server和Client模式的结合。如下图,里面所谓的控制器逻辑(Controller logic)就是上面说的一些规则和行为,像是天黑开灯
在这里插入图片描述
* 控制模型具有多种功能,同时可能包含一个或多个:
* ? 客户端模型 (Server Model)
* ? 服务器模型 (Client Model)
* ? 控制逻辑(规则和行为)用于协调与其相连模型之间的交互。
* 实例:控制模型可用在支持机器周围循环的液体冷却剂水泵上。
* ? 应用场景——温度传感器会记录机器的温度。如果机器超过设定的温度,冷却泵则会被打开。
* ? 冷却泵的控制模块 (Control Module)
* ?与温度传感器相连的客户端(用于接受温度值)
* ?连接到开/关切换的服务器(用于打开或关闭水泵)
* ?控制逻辑(规则和行为)— 负责定义如果温度传感器超过设定值,则打开水泵。

(11)场景
这个概念很好理解,就是一系列状态的集合。比如下班,希望打开空调,灯,以及灯的颜色,这些提前设置好,存储成一个场景,以后当下班这个状态被触发,则对应的场景就会开始生效。

(12)配置(Provisioning)
配置是设备加入Mesh网络并成为节点的过程,涉及几个阶段,最终生成各种安全密钥,并且配置过程本身也是一个安全的过程。使用诸如手机或者平板电脑之类的设备上的APP来完成配置。以这种能力,用于驱动配置过程的设备称为配置者(provisioner),被配置者称为provisionee。配置分为五个步骤进行:
a. 广播信标
b. 邀请
c. 交换公钥
d. 认证/鉴权
e. 配置数据的分发每一步的具体操作详情可参考”蓝牙mesh技术概览中文版“

(13)特性
在配置完成后,节点Node就可以收发mesh的消息Message了。Mesh给每个节点有一些额外的四种可选的特性(Features)。分别是中继Relay,代理Proxy,朋友Friend和 低功耗Low Power features。节点可以在某个时间点选择不支持或者支持多个Feature。
a. 中继
支持中继功能的节点,称为中继节点,能够重新传输接收的消息,中继是消息可以遍历整个Mesh网络的机制,通过中继,消息在设备之间产生多个”跳跃“。Mesh网络PDU包括称为TTL(生存时间,time-to-live)的字段,这是一个整数值,用于限制消息在网络中的跳数。比如将TTL设置为3,那么消息被中继,距始发节点最多3跳,如果设置为0则不被中继,只能单跳一次。 中继节点最多可进行127跳。节点是否能够具备这一特性取决于其电源和计算能力。

b. 低功耗和朋友节点
有些类型的节点具有有限的供电电源以需要尽可能地节省能量,此外,这种类型的节点仍需要涉及到发送以及偶尔的接收消息。比如一个温度传感器设备,当温度高于上限或者低于下限时,它需要发出通知消息,当温度在上下限范围之内时,则不需要通知任何消息。然而,用户还能够向传感器发送改变温度阈值状态值的消息,虽然这种可能性不高,但设备必须支持这个功能。那么问题就来了:如果设备随时处于监听状态,则可以保证消息被及时收到,但这样会消耗太多能量,导致功耗过高;如果为了节省电量,则消息可能会丢失。为了解决这个问题,Mesh引入了朋友节点这个概念, 承担这一角色的节点需要固定的电源和计算资源。
在这里插入图片描述下面的简单的拓扑结构基本上说明了这两种Feature和其他一般Node的关系和消息路径。显而易见,如果有消息要发从T发给L,S会帮忙转发,O会帮忙L存起来。L要消息的时候,O再把T的消息发给L:
在这里插入图片描述c. 代理节点
代理节点是Mesh想到的兼容现有的非Mesh设备的方法。在Proxy节点, 其实是可以通过BLE的GATT来交流的。这是连接非mesh设备和mesh节点的大门。他会负责把mesh和非mesh的BLE设备两边的报文进行处理转发。由于Mesh协议是基于BLE协议之上,所以市面上的BLE设备虽然有些不支持Mesh协议,但肯定支持BLE协议,所以代理节点就可以使用GATT接口将非Mesh设备和Mesh设备连接起来,如下图:
在这里插入图片描述

二、Mesh系统架构
Mesh结构基于BLE核心规范之上,BLE提供基本的无线通信功能,由位于其上的Mesh结构调用。但各家厂商的实现方式可能会有所不同。如下图:
在这里插入图片描述
(一)bearer layer(承载层)
Bearer Layer 定义了Mesh节点怎么传递网络消息的。定义了两种Bearer,广播advertising bearer 和GATT bearer
Advertising Bearer 利用的是BLE GAP广播包的advertising 和scanning的功能来传递接收mesh的报文。
GATT Bearer 允许不支持Advertising Bearer的设备间接的与mesh节点进行通讯。怎么通讯呢?使用代理(Proxy Protocol)。Proxy Protocol是封装在GATT里面,当然会用特别定义的GATT characteristics。支持Proxy Feature的Proxy Node也就是代理节点,因为可以同时支持两种Bearer Layer,所以可以作为mesh节点和非mesh节点的中间桥梁。

(二)网络层(Network Layer)
网络层定义了几件事情:
一、定义了多种网络地址类型,我之前有说过关于Mesh地址的内容。
二、定义了网络层的格式,打通传输层(Transport layer)和承载层(Bearer layer)。
三、定义了一些输入输出Filter,决定哪些消息需要转发,处理还是拒绝。
四、定义了网络消息的加密和认证。

(三)底层传输层(Lower Transport Layer)
这层做的事情很简单,就是拆拆拼拼。把太长的传输层的包拆成若干个分给网络层,把短的网络层的包再组成一个长的传输层的PDU。

(四)上层传输层Upper Transport Layer
上层传输层主要是负责加密,揭秘和应用数据授权。一句话,消息的安全性和机密性就是有这一层负责的。还有就是会定义一些节点间在这一层的一些会话,比如Friend功能,心跳包(Heartbeats)。

(五)访问层Access Layer
访问层定义了应用层的数据,怎样控制和使用加密和解密。验证消息的上下文,密码等等,看看是不是应该再交给更上层。

(六)基础Model层(Foundation Models Layer)
负责基础模型的实现与Mesh网络的配置和管理

(七)Model层(Models Layer)
最上面这一层就是Model的实现啦,包括之前讲过的行为啊,消息,状态等等们,都定义在这一层

三、Mesh系统安全
(一)安全
如果开发过BLE的产品,就会知道现在市面上绝大部分的BLE产品都是“裸奔”的。虽然SIG提供了很多种安全的机制和选项,但是事实上只有少有的几款产品使用了简单的加密。也许是因为大家觉得手机的附件像手环什么的,也没什么隐私,也不是一直连接着,加不加密的也没关系。到了Mesh可就不一样了。蓝牙mesh的目标市场是往家居方向在发展,那就需要长连接和高安全性的要求。所有蓝牙mesh是没有不加密这个选项的。网络,应用还有设备层面上都是要有安全性的,而且,开发者不可以更改。
BLE mesh里有几个基本的安全要求。
o 所有的消息Message都是要被加密和授权的。
o 网络安全,应用安全和设备安全是相互独立的。
o 密钥是可以在网络中更新的o 消息混淆(obfuscation)提供了一种让节点难以被追踪的方法。
o 可以防止重放攻击(replay attack)
o 节点入网的过程同样也是加密流程
o 节点的删除也有安全流程,可以防止别人拆解后获得安全信息。在蓝牙mesh的规格中,提供了三种独立密钥,三种密钥提供了mesh网络不同方面的安全能力。再拿一个灯举例子,如果有一个mesh的灯,我们假设它有mesh的relay功能,可以帮别的节点转发消息,比如家里的插座。它自己本身也需要处理一些特别节点的信息,比如说门磁,做到一开灯就亮。听起来没什么难的对吧,其实这里面牵涉到听得到和听得懂的问题。我们先说说蓝牙Mesh的加密,看懂了这一部分,你也就知道蓝牙mesh是怎么做的了。
前面有说到,蓝牙mesh有三层相对独立的安全机制。我们先说NetKey,这是第一层,你有了这一层的密钥,你就可以成为网络的一员。它可以派生出network encryption key 和 Privacy Key,在讲网络架构的时候我说过,网络层负责这部分的工作,同时负责Relay, 对吗? 好了,那你有了Netkey,你就可以加密和解密,当然就可以实现网络数据的转发。但你真的不是里面装的是什么,有没有有点像快递小哥。要指出的一点是,因为蓝牙mesh网络可以分成若干个子网subnet,所以呢,如果每个子网都用的是自己的NetKey,那么不同子网之间的设备是没有办法转发的。这个作用有点像“隔离”,比如说酒店里面的每个房间,你不想让他们互相转发。
要想解决应用层数据的事情,就要用到AppKey –application key。在一个mesh的网络中,可能会有多个AppKey,每个Appkey对应的一组应用和相关的节点。比如,所有灯和开关,他们可以用一个AppKey,这样的话,它们就只能处理到相关的数据和报文了。AppKey是在上层传输层来实现的。所以有了AppKey,才能实现在上层传输层之上的所有功能。
讲到这里,估计你已经知道之前我们说的听得到和听得懂的答案了把。用NetKey和AppKey就可以解决这个问题。还有一点就是每个AppKey都只能对应一个NetKey,但每个NetKey可以对应多个AppKeys,这个叫做”Key-binding”。所以每个AppKey的使用范围也就是在NetKey对应的子网里,这一点大家理解起来没有问题吧。
那还有一个Key就是叫做Device Key(DevKey)。DevKey其实是一种特殊的AppKey,每个节点的Devkey都是独一无二的,它用于在配网阶段和配网器进行安全传输用的, 所以只有配网器和入网的节点知道这个DevKey。

(二)垃圾桶攻击( Trashcan Attacks)
好了,讲完三个Key,你一定可以想象到每个蓝牙Mesh的节点里面很可能有多个Key,你有没有想过这些Key怎么协同工作?好吧,这一部分我先不讲啦,说起来又有很多内容,毕竟我们是入门篇啊。在安全部分我们要讨论的是这么多Key在节点中,如果被偷了,或者扔掉,又或者卖个别人的话,怎么能保证这些安全内容不会成为别人攻击自己mesh网络的工具。这个也叫做“垃圾桶攻击”(Trashcan Attacks)。在蓝牙mesh里面也规定了一套流程来保证这一攻击方式无效。配网器(Provisioner)可以把特定的设备拉入黑名单并且启动一个叫做“密钥更新”的流程。简单来讲,整个网络中不管是NetKey还是AppKey都会被更新一遍,那些被拉入黑名单的设备不会在这个流程中,所以他们得不到最新的密钥。

(三)重放攻击(Replay Attacks)
还有一种很常见的攻击方式是重放攻击,什么叫重放攻击,就是把之前收到的报文经过一些加工,比方说假如一些恶意的代码来攻击网络。最常见的就是收到汽车钥匙的发包顺序,重放汽车钥匙的滚动码报文,有很大几率未授权的打开车门。这一部分就不戏讲啦,大家自行搜索就好了。蓝牙Mesh通过网络PDU的序号SEQ和IV index, 也就是每次比较收到的SEQ和IV index,看看是不是新的, 来保证如果发Replay message,节点不会被处理,也就避免了Replay attack

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页