LV03-03-蓝牙Mesh进阶-01-蓝牙Mesh网络分层
本文主要是蓝牙Mesh进阶——蓝牙Mesh网络分层的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows版本 | windows11 |
Ubuntu版本 | Ubuntu22.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | 阿里云 | 阿里云官网主页 |
阿里生活物联平台 | 生活物联网平台(飞燕平台)主页 | |
AliGenie | 天猫精灵开放平台AliGenie主页 | |
阿里物联网平台 | 阿里物联网平台主页 | |
Bluetooth 技术网站 | 蓝牙协议规范什么的可以来这里找 | |
Telink | Telink | Chips for a Smarter IoT (telink-semi.com) Telink中文官网 | |
开发手册 | AliOS Things开发指南 | AliOS Things开发指南,这里是最新版本,可以直接从官网找到 |
AliOS Things开发指南 | AliOS Things应用开发指南,这里应该是3.3版本的完整开发文档 | |
AliOS Things开发指南(3.0) | AliOS Things应用开发指南,这里应该是3.0版本的完整开发文档 | |
生活物联网平台开发文档 | 生活物联网平台(飞燕平台)开发文档 《设备端开发指南》 | |
Wi-Fi IoT品类定义与功能开发 | 天猫精灵IoT开放平台——Wi-Fi IoT品类定义与功能开发 | |
硬件平台 | mk3080 WiFi开发板 | WiFi开发板使用指南-阿里云开发者社区 |
esp8266开发板 | 一个教程:ESP8266-NodeMCU开发板详解-太极创客 (taichi-maker.com) | |
TLSR8258 Datasheet | Datasheet for Telink BLE + IEEE802.15.4 MultiStandard Wireless SoC TLSR8258 | |
参考资料 | AliOS Things 3.0 应用开发指南 | 这个只是一篇参考文章,里面是一些环境搭建相关的,可以参考 |
IP知识百科 - 华为 (huawei.com) | IP的一些相关知识点 |
点击查看相关文件下载
分类 | 网址 | 说明 |
蓝牙规范相关文档 | Core Specification 5.2 | 核心规格 5.2,该规范定义了创建可互操作的Bluetooth 设备所需的技术。 《Core_v5.2.pdf》 |
Mesh Model(v1.1) | 本Bluetooth 规范定义了模型(以及它们所需的状态和消息),这些模型用于在mesh 网络中的节点上执行基本功能,超出了Bluetooth Mesh 配置文件 规范中定义的基础模型。 本规范包括定义跨设备类型标准功能的通用模型,以及支持关键mesh 场景的模型,如照明控制、传感器、时间和场景。 《MshMDL_v1.1.pdf》 | |
Mesh Profile(v1.0.1) | 该Bluetooth 规范定义了基本要求,以实现可互操作的mesh 网络解决方案,用于Bluetooth 低能量无线技术。 《MshPRFv1.0.1.pdf》 | |
Mesh Device Properties | 本规范包含Bluetooth Mesh 配置文件 和Bluetooth Mesh 模型规范所要求的设备属性的定义。 但是跟之前的有些区别,我主要看的之前的版本:《MMeshDeviceProperties_v1.2.pdf》 | |
GATT Specification Supplement | GATT Specification Supplement | Bluetooth® Technology Website。 好像可以在线看:《GATT Specification Supplement》 | |
Assigned Numbers | GATT的一些类型定义可以在这里找。 | |
AliOS Things | alios-things/AliOS-Things | Gitee上的AliOSThings SDK源码仓库 |
alibaba/AliOS-Things | GitHub上的AliOSThings SDK源码仓库 | |
天猫精灵蓝牙Mesh协议栈 | alibaba-archive/genie-bt-mesh-stack | GitHub上的天猫精灵蓝牙Mesh协议栈源码仓库。 之前是在alibaba/genie-bt-mesh-stack这个仓库。 写笔记的时候最新提交为faf523618a6a2560090fc423222b9db80984bb7a |
蓝牙Mesh设备开发指南 | 阿里云生活服务平台开发手册——蓝牙设备开发一节中的内容 |
在研究技术的时候,最规范的还要说是官方提供的协议说明文档,不至于让我们绕弯子,遗憾的是全英文手册看上去比较头疼,但是从事IT行业的谁又能不跨越这一关呢?接下来就从官方手册入手,逐一了解每一层的用途,为了更方便理解,这里按照图上的顺序进行一个一个的描述。
一、分层体系结构
我们看一下《MshPRFv1.0.1.pdf》的2.1 Layered architecture一节:
二、各层分析
1. Bearer Layer
本层次中需要知道数据到达Bearer Layer的时候数据格式是什么样子的,它是怎么交给上一层的,上一层的又是如何把数据交给这一层并且发送出去的呢?我们会了解Bearer Layer所承载的对象,Bluetooth Low Energy Core Specification对广播和GATT拿到的数据怎样进行识别和交给Bearer Layer层的。
1.1 PDU
在研究Bearer Layer数据格式的时候,不得不回顾一下BLE的广播通道,我们可以看《Core_v5.2.pdf》的Vol 2, Part A,2 FREQUENCY BANDS AND CHANNEL ARRANGEMENT(384):
首先是信道,在蓝牙BLE中有40个信道,从上图可见,当K=0则对应2402Mhz,k=39则对应2482Mhz,在这些信道中又被分为3个广播信道和数据信道,如下图(《Core_v5.2.pdf》 Vol 6, Part B,1.4.1 Physical channel indices)所示:
广播信道的index为37,38,39,但实际上他们对应的物理信道并不是相邻的,我们需要明白为什么这么做,这样做的目的就是为了蓝牙广播的健壮性,在广播的时候会选择三个相差较大的频段来进行数据广播达到抗干扰的能力,还有一个更重要的原因,蓝牙的广播通道避开了Wi-Fi的数据通道,蓝牙的数据通道和Wi-Fi存在重叠。
在知道了存在干扰或者与其他设备碰撞的信道后,我们需要对数据进行识别显然是重中之重,在BLE中也对此阐述过,《Core_v5.2.pdf》Vol 6, Part B,2.1 PACKET FORMAT FOR THE LE UNCODED PHYS:
蓝牙的空中数据包均为这种格式,广播通道和数据通道只有发送的具体内容(PDU)不同,对方设备发射的帧格式为:
Preamble:前导,前导的值取决于Access Address最低位的值
Access Address:接入地址,通过前导和接入地址的配合,保证了数据包为蓝牙数据包的结果
PDU:具体的数据
CRC:校验
1.2 广播通道
- 广播模式(ADV),也就是广播通道
对于PDU来说,最为重要的就是它的类型,通过手册可以见的它的几种模式,对于蓝牙Mesh的广播包来说,一定是不可连接不可扫描的,所以需要选择一种不可扫描和不可连接的一种模式。 我们可以看一下《Core_v5.2.pdf》Vol 6, Part B,2.3 ADVERTISING PHYSICAL CHANNEL PDU:
PDU格式如上图,有一个16bits的header,剩下的是payload数据。数据头的格式可以看Figure2.5。我们继续看,当PDU type位0b0010的时候,广播包是不可被扫描的,我们看一下这种广播包的Payload,如上图Figure2.8所示,AdvA填充的是设备自己的地址,这个地址是随机的。通过上述内容,再来分析广播数据:
我们可以看一下《Core_v5.2.pdf》Vol 3, Part C,11 ADVERTISING AND SCAN RESPONSE DATA FORMAT:
在之前的蓝牙BLE中,会把数据分为多个AD Structure,每一个都会有自己的独有的信息,比如第一个装的公司信息,第二个装的设备名字等等。把我们之前的31个数据,变成N个AD Structure,它的好处在于能将数据进行展示更容易理解,打个比方我们在扫描设备的时候就能得值它的厂商以及其他信息,来分析一下这个格式就能够清楚了。
一个AD Structure里面有31 octets个数据(31字节),可以看到前面的Length和AD Type占了2个,所以从上一层Network Layer 下来的数据其实只有29个。这里我感觉课程老师讲的有点问题,我感觉应该是32个字节(因为上面PDU的Payload数据是0-31),所以上一层应该是30字节数据才对,这里没有深入研究,先这样写,后面发现有问题再补充修改。
在图中可以看到AD Type,我们可以定制AD Type如果等于0x00c1代表厂商类型,后面的AD Data则代表具体厂商的名字,以此类推,我们可以在AD Type中添加定制化的信息,蓝牙Mesh的广播包就是根据这里进行区分的,蓝牙Mesh规定,一个数据包只有一个AD Strusture,同时指定了几种ADType,AD Type也决定了数据最终走向哪里。如下所示 :
AD Type = 0x29 《PB-ADV》 代表入网广播包。
AD type = 0x2A 《Mesh Message》代表普通数据包,比如我们的开灯、关灯均已这种形式发送。
AD type = 0x2B 《Mesh Beacon》 信标包,比如入网要求发送的信标包,安全相关的信标包 。
Bearer Layer层的核心数据就是AD Structure这个位置了,那我们如何知道AD Type类型的? 我们可以来这里找Assigned Numbers | Bluetooth® Technology Website:
我们打开这个文档Assigned Numbers (bluetooth.com),找到2.3 Common Data Types,这例会有AD type的定义和解释:
或者我们也可以去代码里找bluetooth-SIG / public / assigned_numbers / core / ad_types.yaml — Bitbucket:
1.3 数据通道
- 数据通道(GATT)
数据通道的PDU格式,同样是一个Header + Payload,另外多出来一个MIC。广播PDU的Header内容是不可连接,可连接等等这些内容,然而数据通道的Header相对复杂了一些,我们可以看一下《Core_v5.2.pdf》Vol 3, Part C,2.4 DATA PHYSICAL CHANNEL PDU :
数据通道的类型需要选择Data PDU,也就是LLID = 0b01,LL Date PDU在文档中有如下描述:
An LL Data PDU is a Data Channel PDU that is used to send L2CAP data. TheLLID field in the Header shall be set to either 0b01 or 0b10.
An LL Data PDU with the LLID field in the Header set to 0b01, and the Length field set to 0b00000000, is known as an Empty PDU. The master’s Link Layer may send an Empty PDU to the slave to allow the slave to respond with any Data Physical Channel PDU, including an Empty PDU.
An LL Data PDU with the LLID field in the Header set to 0b10 shall not havethe Length field set to 0b00000000.
Note: If the Link Layer receives an HCI ACL Data Packet with Data_Total_Length equal to 0b00000000 and Packet_Boundary_Flag set to 0b00 (i.e., a start fragment), then the Link Layer cannot simply transmit the fragment over the air but, instead, must combine it with one or more of the following continuation fragments to form a PDU with LLID set to 0b10 and nonzero length.
在上层抽象的时候,数据格式和广播通道的时候其实是一样的,同样是《Core_v5.2.pdf》Vol 3, Part C,11 ADVERTISING AND SCAN RESPONSE DATA FORMAT的这张图:
这里的AD Type与广播包肯定是不一样的,我们打开这个文档Assigned Numbers (bluetooth.com),找到3.4 GATT Services,这例会有对应的AD type的定义和解释:
在这里只有两个选择: AD Type = 0x1827 入网时使用;AD Type = 0x1828 数据传输使用 。
1.4 总结
Bearer Layer层的本质其实就是来区分AD Type,以此来决定这个AD Data要给上一层的谁,或者是上一层的数据拿下来之后是通过广播通道还是数据通道发送出去。就相当于是进行了一个数据包流向的判断。我们打开《MshPRFv1.0.1.pdf》找到3.3.1 Advertising bearer :
GAP需要尽量保持100%扫描,两个连续包之间加上一个随机时间,避免碰撞,一般来说是10ms左右。GATT 可以自己查看手册 。
2. Network Layer
进入到本层之前,先回顾一下,数据到了Bearer Layer层的时候数据是什么样子了呢?一共有31字节的数据,其中包括长度(Length)、类型(AD Type)、数据(Data)。那么数据到了Network Layer层的时候,就只剩下29个字节的数据了,因为AD Type和Lenght没有必要传上来了,也就是像火箭一层一层剥离一样,接下来看下Netwrok Layer的数据格式,也就是剩余最多29字节的格式。
2.1 Network PDU
我们看一下《MshPRFv1.0.1.pdf》找到3.4.4 Network PDU :
IVI:此项和设备的存活周期有关,此数据和NID是裸漏在外面的未加密数据。是一个32位的值,用于保证网络层的数据加密和混淆的安全性和随机性。IVI与序列号(SEQ)一起组成了nonce,nonce是用于AES-CCM算法的输入参数,用于对网络层PDU进行加密和认证。IVI可以防止nonce的重复使用,从而提高网络层的安全性。
NID:决定CTL - Source Address(SRC)部分使用什么KEY去混淆,Destination Address(DST) - TransportPUD用什么KEY加密。是一个7位的值,用于标识用于保护网络层PDU的加密密钥和隐私密钥。
CTL:数据包是否为网络控制包,仅参在LNP节点和FRIEND节点使用,如果不是网络控制包则为信息包。是一个1位的值,用于区分网络层PDU(Protocol Data Unit)是访问消息(Access Message)还是控制消息(Control Message)。访问消息是用于传输应用层数据的,控制消息是用于实现网络层的管理功能的,比如创建和维护友谊(Friendship)和心跳(Heartbeat)。CTL的值也会影响网络层PDU的大小和NetMIC(Network Message Integrity Check)的长度。
TTL:消息寿命键值,7位最大128,决定了数据可以被转发多少次。TTL的作用是防止消息在网络中无限循环,同时也可以控制消息的传播范围和效率。TTL的值由消息的发布者设定,每个消息都有一个初始的TTL值,范围是0-127。当消息被中继节点转发时,TTL的值会减1(就发生在这一层中),当TTL的值为0时,消息不会再被转发。TTL的值也会影响消息的优先级,TTL越高的消息越优先被转发。
SEQ:序列,防中继攻击,该值始终在 + 1,让攻击者无法得值该序列,从而不能进行重复包攻击。SEQ的作用是保证每个消息的唯一性和时效性,避免消息被重复处理或滥用。
SRC:源地址。是一个16位的值,用于标识网络层PDU(Protocol Data Unit)的发送者。SRC的作用是让接收者知道消息的来源,以便进行回复或处理。
DST:目的地址。是一个16位的值,用于标识网络层PDU(Protocol Data Unit)的接收者。DST的作用是让发送者指定消息的目的地,以便进行广播或单播。DST的值可以是一个单播地址、一个组播地址或一个虚拟地址,不能是一个未分配的地址。DST的值也会影响消息的安全性和隐私性,因为它会与IVI(Initialization Vector Index)和SEQ(Sequence Number)一起组成nonce,nonce是用于AES-CCM算法的输入参数,用于对网络层PDU进行加密和认证。
TransportPDU:Transport数据。是网络层PDU(Protocol Data Unit)的一部分,用于承载上层传输层的数据或控制信息。TransportPDU的作用是实现网络层和上层传输层之间的数据交换,以及对数据进行分段和重组。
NetMIC:是网络层PDU(Protocol Data Unit)的一部分,用于保证网络层数据的完整性和认证性。NetMIC的作用是防止消息被篡改或伪造,从而提高网络的安全性和可靠性。
了解了每个参数的意思,再来看下其中的混淆和加密的地方是如何做的。
2.2 网络加密的过程
我们看一下 我们看一下《MshPRFv1.0.1.pdf》的3.8.6.3 Network key:
其中k1、k2、k3为蓝牙Mesh提供的标准函数,通过手册一样可以找得到,它们在《MshPRFv1.0.1.pdf》的3.8.2 Security toolbox 这一节:
Network key通过k2函数可以生成三个参数,分别为NID、EncryptionKey(加密key)、PrivacyKey(隐私key),这也验证了上面的参数通过NID可以得到混淆和加密的算法。我们一定好奇那Network key是怎么得来的呢?这里做一个简单的解释,一个设备入网(Provisioning)之后就会拥有Network key,在相同的蓝牙Mesh网络里每个设备都会有相同的Network key,天猫精灵找队友,配网成功,你得设备会有一个Network key,天猫精灵同样会有一个一摸一样的Network key。拿到了EncryptionKey(加密key)、PrivacyKey(隐私key)就可以对数据进行加密了,如下图(《MshPRFv1.0.1.pdf》的3.8.7.2 Network layer authentication and encryption):
上图所示DST和TransportPDU(上一层的数据)通过Network Nonce 和刚才k2生成的Encryption key进行了AES-CCM加密,生成了下面的加密数据和完整校验数据,Network Nonce内容(《MshPRFv1.0.1.pdf》的3.8.5.1 Network nonce):
上述内容即网络加密的过程。
2.3 消息的混淆
我们看一下《MshPRFv1.0.1.pdf》的3.8.7.3 Network layer obfuscation这一节的Figure 3.42:
Privacy key是之前通过Newwork key生成的,其中Privacy Random数据是上面所提到的加密完成后的数据,其余的数据包含明码数据通过亦或进行混淆,过程也在Mesh文档中阐述,反之解密,其中最主要的则是Privacy key 和 IV Index。
我们看一下数据接收过程(《MshPRFv1.0.1.pdf》的3.4.6.3 Receiving a Network PDU这一节的Figure 3.8):
我们再看一下数据发送(《MshPRFv1.0.1.pdf》的3.4.4 Network PDU这一节的Figure 3.7):
发送的过程在手册中没有流程图,只有文字描述,基本流程如下:
(1)设置IVI ,取Iv Index最低有效位。
(2)NID配置,取决于使用哪个Networkey生成的。
(3)SEQ 加 1。
(4)Source address 取决于发送的element的地址。
(5)Destination Address 填写你要发送的地址。
(6)MIC加密后生成的内容
3. Lower transport Layer
Lower transport Layer层主要的工作在与拆包和组包的功能,其中包含四种格式类型,需要掌握,在模型中还会接触到关于此内容相关的东西。
3.1 数据分包
我们看一下《MshPRFv1.0.1.pdf》的3.5.3 Segmentation and reassembly这一节的Figure 3.14:
没有什么能比这一幅图更说明问题,在上图中,可以看到数据从Access Layer传输到Upper Transport Layer层,数据在Access PDU上增加了一个Trans MIC,在向下传输到Lower Transport Layer层,数据到达Lower Transport Layer层的时候被分为了两段,可以理解数据量较大的时候,数据运输过程就会被分开,好比我们买了一台大型设备,物流也是分开进行运输的,等数据全部到达的时候,在通过此图反向推回去将数据完成组合成Access PDU的内容。
3.2 Lower Transport PDU
接下来我们来看一下四种格式类型,我们看一下《MshPRFv1.0.1.pdf》的3.5.2 Lower Transport PDU这一节的Table 3.9:
具体的可以看手册,手册中有很详细的描述。
4. Upper transport layer
The upper transport layer takes an access payload from the access layer or an internally generated upper transport layer Control message and transmits those messages to a peer upper transport layer.
上层传输层从访问层获取访问负载或内部生成的上层传输层控制消息,并将这些消息传输给对等的上层传输层。
For messages from the access layer, encryption and authentication of the message is performed using an application key.This allows the receiving upper transport layer to authenticate received messages.
对于来自访问层的消息,使用应用程序密钥执行消息的加密和身份验证。这允许接收上层传输层对接收到的消息进行身份验证。
Transport Control messages that are internally generated by the upper transport layer are only encrypted and authenticated at the network layer
由上层传输层内部生成的传输控制消息仅在网络层进行加密和身份验证。
5. Access Layer
访问层定义了较高层应用程序如何使用较高层传输层。它定义了应用程序数据的格式;它定义和控制应用程序数据的加密和解密在上层传输层中执行;并且在将传入的应用程序数据转发到更高的层之前,它会检查传入的应用程序数据是否已经在正确的网络和应用程序密钥的上下文中被接收。
通过翻译出来的比较晦涩难懂了,其实它对应的代码就是我们Model中的操作代码,下面我们来一点一点的学习。
我们看一下《MshPRFv1.0.1.pdf》的3.7 Access layer:
从第一点可以得出,本层的数据均采用小段模型,随后阐述了Model标识符,每一个Model都有自己的唯一标识符,这个在代码中可以看见,添加模型的时候后面都会有一个ModelID,且在天猫精灵官方规范中也明确规定了不同产品不同功能对应的模型ID,模型ID的作用是什么呢?首先我们明确每个元素是可以添加多个Model的,通过地址能快速的找到元素,在通过ID快速找到对应的模型进行操作,另外需要考虑ID还可以起到防重复定义的问题,下图为追溯模型定义位置,可以看到被添加了模型ModelID,且为16bit。
下图为厂商模型定义部分,其中0x01A8代表阿里巴巴,此后接天猫精灵文档时会有详细说明,该模型则采用了16bit厂商标识码和16bit的modelID的组合,共计32bit :
6. Foundation Model layer
基础Model,此层定义了配置和状态管理,消息和模型以及Mesh网络,该模型的体现在代码中,两个必填模型,如下图:
BT_MESH_MODEL_CFG_SRV模型则为配置和状态管理的模型 。
BT_MESH_MODEL_HEALTH_SRV模型则为Mesh网路模型,可以从名字上看出来管理网络健壮性的。
7. Model Layer
模型层定义了用于标准化典型用户场景操作的模型,这些模型在蓝牙Mesh Model规范或其他更高层规范中定义。更高层模型规范的例子包括照明和传感器的模型。