3、Mesh协议栈架构:承载层、网络层、传输层、接入层、基础模型层的分层设计
说实话,刚接触蓝牙Mesh的时候,我也被那一堆层搞晕过。承载层、网络层、传输层、接入层、基础模型层……光名字就够绕的。但后来我慢慢发现,这个分层设计其实非常巧妙。每一层各司其职,就像一家公司的不同部门。
我个人习惯把协议栈想象成一个快递系统。你想想看,从寄件人到收件人,中间要经过打包、贴单、分拣、运输、派送。Mesh协议栈也是这个道理。数据从应用层一路往下,每一层都给它加点“料”,到了对端再一层层拆开。
下面这张图,是我自己画的分层架构。你一眼就能看明白数据是怎么“旅行”的。
3.1 承载层(Bearer Layer)—— 数据怎么“上车”
承载层是协议栈的最底层。说白了,它只关心一件事:数据通过什么物理通道发出去。
蓝牙Mesh定义了两种承载方式:
- Advertising Bearer(广播承载):这是Mesh最常用的方式。节点通过BLE广播信道发送数据包。不需要建立连接,效率高,适合一对多通信。
- GATT Bearer(GATT承载):通过标准的BLE GATT连接来传输Mesh数据。主要用于手机App与Mesh网络之间的交互。比如你用手机控制灯泡,手机通常走GATT Bearer接入。
3.2 网络层(Network Layer)—— 消息的“交通管制”
网络层是Mesh协议栈的核心。它负责消息的中继、路由、加密和去重。
你想想看,一个消息从节点A发到节点Z,中间可能要经过好几个中继节点。网络层就是干这个活的。它给每个消息加上一个网络头(Network Header),里面包含:
- 源地址:谁发的
- 目的地址:发给谁(可以是单播、组播或虚拟地址)
- TTL(生存时间):消息最多能跳几次。每经过一个中继,TTL减1。减到0就丢弃。
- 序列号:防止重复消息
网络层还负责网络密钥(NetKey)加密。所有在网络层传输的数据都是加密的。中继节点只能看到网络头,看不到真正的应用数据。这就保证了端到端的安全性。
3.3 传输层(Transport Layer)—— 大包怎么拆
传输层解决一个很实际的问题:应用层的数据包太大,网络层一次装不下怎么办?
蓝牙Mesh的底层广播包(PDU)最大只有31个字节。去掉网络头和传输头,留给应用数据的空间非常有限。传输层就负责把大消息分段(Segmentation)成多个小包,接收端再重组(Reassembly)回来。
传输层还提供两种服务:
| 服务类型 | 特点 | 适用场景 |
|---|---|---|
| Unacknowledged(无确认) | 发完就不管了,不等待确认 | 状态广播、心跳包、对可靠性要求不高的场景 |
| Acknowledged(有确认) | 发送后等待接收方回复ACK,超时重传 | 控制命令(如开关灯)、配置消息 |
我记得第一次调试分段传输时,发现接收端总是重组失败。查了半天,原来是分段包的序列号顺序乱了。后来我加了个超时机制——如果30秒内收不全所有分段,就直接丢弃,避免死等。
3.4 接入层(Access Layer)—— 应用数据的“翻译官”
接入层是应用层和传输层之间的桥梁。它定义了应用数据的格式和操作码(Opcode)。
举个例子。你要控制一个灯开关。应用层说“把灯打开”。接入层就把这个命令翻译成标准格式:
- Opcode:0x8201(Generic OnOff Set)
- 参数:0x01(开)
接入层还负责访问控制。每个模型(Model)都有自己允许的操作码列表。如果一个消息的操作码不在模型支持的范围内,接入层会直接丢弃。这就像门禁系统——没有权限的人进不来。
3.5 基础模型层(Model Layer)—— 业务逻辑的“剧本”
基础模型层是最顶层,也是开发者最常打交道的一层。它定义了标准的行为和状态。
蓝牙Mesh规范定义了很多标准模型,比如:
- Generic OnOff Server/Client:开关控制
- Generic Level Server/Client:亮度、色温等连续值控制
- Light Lightness Server/Client:灯光亮度控制
- Sensor Server/Client:传感器数据上报
每个模型都包含两部分:
- 状态(State):比如灯的“开/关”状态、当前亮度值
- 行为(Behavior):比如收到“开”命令后,状态变为“开”,并执行开灯动作
模型之间还可以通过绑定(Binding)关联。比如,一个Generic Level Server模型可以绑定到Light Lightness Server模型。当亮度值变化时,灯光亮度自动跟着变。这就像连锁反应——一个状态变了,其他相关状态也跟着更新。
3.6 各层之间的协作
说了这么多层,它们到底怎么配合?我举个例子你就明白了。
假设你要通过手机App控制一个Mesh灯泡:
- 手机端(GATT Bearer):App通过GATT连接把“开灯”命令发给一个Proxy节点。
- Proxy节点:收到GATT数据后,转换成Mesh广播包,从网络层开始往下封装。
- 网络层:加上源地址、目的地址、TTL,用NetKey加密。
- 传输层:如果命令太长,分段成多个小包。
- 接入层:加上操作码(Generic OnOff Set)。
- 承载层:通过广播信道发出去。
- 灯泡节点:接收后,从承载层往上逐层解封装。接入层检查操作码,传输层重组数据,网络层验证加密,最后交给模型层。
- 模型层:Generic OnOff Server模型收到命令,状态变为“开”,执行开灯动作。
整个过程看起来复杂,但每一层只做自己的事,互不干扰。这就是分层设计的魅力。