3、Mesh协议栈架构:承载层、网络层、传输层、接入层、基础模型层的分层设计

说实话,刚接触蓝牙Mesh的时候,我也被那一堆层搞晕过。承载层、网络层、传输层、接入层、基础模型层……光名字就够绕的。但后来我慢慢发现,这个分层设计其实非常巧妙。每一层各司其职,就像一家公司的不同部门。

我个人习惯把协议栈想象成一个快递系统。你想想看,从寄件人到收件人,中间要经过打包、贴单、分拣、运输、派送。Mesh协议栈也是这个道理。数据从应用层一路往下,每一层都给它加点“料”,到了对端再一层层拆开。

下面这张图,是我自己画的分层架构。你一眼就能看明白数据是怎么“旅行”的。

蓝牙Mesh协议栈分层架构图 蓝牙Mesh协议栈分层架构 基础模型层(Model Layer) 定义标准模型(如Generic OnOff Server/Client)及模型间通信行为 接入层(Access Layer) 定义应用数据格式、操作码(Opcode)及访问控制 传输层(Transport Layer) 负责数据的分段与重组(SAR)、重传及端到端确认 网络层(Network Layer) 负责中继、路由、网络密钥加密及消息去重 承载层(Bearer Layer) 定义数据如何通过广播(Advertising Bearer)或GATT连接(GATT Bearer)传输 数据发送时从上往下逐层封装,接收时从下往上逐层解封装 每一层只关心自己的职责,不越界处理

3.1 承载层(Bearer Layer)—— 数据怎么“上车”

承载层是协议栈的最底层。说白了,它只关心一件事:数据通过什么物理通道发出去。

蓝牙Mesh定义了两种承载方式:

  • Advertising Bearer(广播承载):这是Mesh最常用的方式。节点通过BLE广播信道发送数据包。不需要建立连接,效率高,适合一对多通信。
  • GATT Bearer(GATT承载):通过标准的BLE GATT连接来传输Mesh数据。主要用于手机App与Mesh网络之间的交互。比如你用手机控制灯泡,手机通常走GATT Bearer接入。
我的经验: 在低功耗节点上,我建议优先用广播承载。GATT承载虽然稳定,但功耗高,不适合电池供电的设备。我曾经在一个智能门锁项目里踩过坑——用GATT承载做中继,结果电池两周就耗光了。

3.2 网络层(Network Layer)—— 消息的“交通管制”

网络层是Mesh协议栈的核心。它负责消息的中继、路由、加密和去重。

你想想看,一个消息从节点A发到节点Z,中间可能要经过好几个中继节点。网络层就是干这个活的。它给每个消息加上一个网络头(Network Header),里面包含:

  • 源地址:谁发的
  • 目的地址:发给谁(可以是单播、组播或虚拟地址)
  • TTL(生存时间):消息最多能跳几次。每经过一个中继,TTL减1。减到0就丢弃。
  • 序列号:防止重复消息

网络层还负责网络密钥(NetKey)加密。所有在网络层传输的数据都是加密的。中继节点只能看到网络头,看不到真正的应用数据。这就保证了端到端的安全性。

注意: 网络层只做中继,不做路由表。Mesh网络里没有传统意义上的“路由协议”。消息通过泛洪(Flooding)方式传播——每个中继节点收到消息后,除了自己,还会转发给所有邻居。这看起来有点“笨”,但好处是网络非常健壮,任何一个节点掉线都不影响整体通信。

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模型。当亮度值变化时,灯光亮度自动跟着变。这就像连锁反应——一个状态变了,其他相关状态也跟着更新。

我的建议: 刚开始做Mesh开发时,尽量用标准模型。标准模型经过充分测试,兼容性好。我见过有人非要自己定义私有模型,结果跟其他厂家的设备对不上,最后还得改回来。除非你有特殊需求,否则别折腾。

3.6 各层之间的协作

说了这么多层,它们到底怎么配合?我举个例子你就明白了。

假设你要通过手机App控制一个Mesh灯泡:

  1. 手机端(GATT Bearer):App通过GATT连接把“开灯”命令发给一个Proxy节点。
  2. Proxy节点:收到GATT数据后,转换成Mesh广播包,从网络层开始往下封装。
  3. 网络层:加上源地址、目的地址、TTL,用NetKey加密。
  4. 传输层:如果命令太长,分段成多个小包。
  5. 接入层:加上操作码(Generic OnOff Set)。
  6. 承载层:通过广播信道发出去。
  7. 灯泡节点:接收后,从承载层往上逐层解封装。接入层检查操作码,传输层重组数据,网络层验证加密,最后交给模型层。
  8. 模型层:Generic OnOff Server模型收到命令,状态变为“开”,执行开灯动作。

整个过程看起来复杂,但每一层只做自己的事,互不干扰。这就是分层设计的魅力。

总结一下: 承载层管“怎么传”,网络层管“传给谁”,传输层管“传得稳”,接入层管“传什么”,模型层管“怎么用”。五层各司其职,缺一不可。