4、Mesh协议栈架构:协议栈分层

好,咱们今天聊聊Mesh协议栈的分层结构。说实话,我刚接触蓝牙Mesh那会儿,看着这五层协议栈,心里直犯嘀咕——这不就是套了个Mesh壳子的BLE吗?后来踩了几个坑才明白,每一层都有它存在的道理。

我个人习惯把协议栈比作一个快递系统。你想想看,从寄件人到收件人,中间要经过打包、分拣、运输、派送好几个环节。Mesh协议栈也是这么回事。咱们一层层往下看。

5.1 Bearer Layer(承载层)

承载层是协议栈的最底层。说白了,它负责把数据变成能在物理介质上传输的信号。在Mesh里,主要有两种承载方式:

  • Advertising Bearer(广播承载):利用BLE的广播通道发数据。这是Mesh最常用的方式。
  • GATT Bearer(GATT承载):通过GATT连接传输。主要用于手机App配网场景。

关键点:广播承载用的是BLE的37、38、39三个广播通道。这三个通道避开了Wi-Fi的干扰频段,所以抗干扰能力还不错。

我在项目中遇到过一个问题:设备在金属机箱里,广播信号衰减得厉害。后来发现是天线匹配没做好。嗯,这里要注意,承载层的物理性能直接影响整个网络的可靠性。

5.2 Network Layer(网络层)

网络层负责消息的转发和中继。这是Mesh网络的核心能力所在。它主要干三件事:

  1. 消息中继:收到消息后,判断要不要转发给邻居节点。
  2. 地址处理:识别源地址、目的地址,决定消息流向。
  3. 安全校验:检查网络层加密和完整性校验。

网络层的数据包格式是这样的:

Network PDU:
| IVI | NID | CTL | TTL | SEQ | SRC | DST | Transport PDU | NetMIC |
| 1b  | 7b  | 1b  | 7b  | 24b | 16b | 16b | 可变长度      | 32b/64b |

这里有个坑——TTL字段。我曾经把TTL设得太大,结果消息在网络里到处乱窜,造成广播风暴。后来我学乖了,一般设成3到5就够用了。你想想看,一个消息跳个三五次还到不了目的地,那多半是网络拓扑有问题。

5.3 Transport Layer(传输层)

传输层负责把上层的大数据包拆分成小段,或者把小段重组回去。它分两个子层:

  • Lower Transport Layer(低层传输):处理分段和重组,以及端到端的确认重传。
  • Upper Transport Layer(高层传输):负责应用数据的加密和解密。

小技巧:分段消息最多可以拆成32个Segment。每个Segment最大12字节。所以一条消息最多能传384字节的应用数据。超过这个数?那就得用扩展模型了。

我记得有一次调试,发现设备收不到长消息。查了半天,原来是分段重组超时时间设得太短。默认是10秒,但我的网络里节点比较多,中继延迟大。改成20秒就好了。

5.4 Access Layer(接入层)

接入层是应用层和传输层之间的桥梁。它负责:

  1. 应用密钥管理:决定用哪把密钥加密应用数据。
  2. 消息格式定义:定义Opcode和参数的结构。
  3. 访问控制:检查设备是否有权限发送或接收某个消息。

接入层的PDU结构很简单:

Access PDU:
| Opcode | Parameters |
| 1-3B   | 0-379B     |

Opcode的设计很有意思。1字节的Opcode留给最常用的消息,2字节的给次常用的,3字节的给厂商自定义。说白了,就是省带宽。

5.5 Model Layer(模型层)

模型层是最顶层,直接面向应用开发者。它定义了设备的行为和状态。比如:

  • Generic OnOff Server:开关服务器模型,控制灯的亮灭。
  • Generic OnOff Client:开关客户端模型,发送开关命令。
  • Light Lightness Server:亮度服务器模型,调节灯光亮度。

核心概念:模型分为Server Model和Client Model。Server负责维护状态,Client负责发起请求。一个设备可以同时包含多个模型。

我刚开始做智能照明项目时,把所有的逻辑都塞在一个模型里。结果代码耦合严重,改一个功能要动半套代码。后来我学乖了,按功能拆分成多个模型——开关归开关,调光归调光,场景归场景。清爽多了。

数据封装过程

咱们捋一遍数据从上层到底层的封装过程:

层级 输入 输出 关键操作
Model Layer 应用逻辑 Model Message 定义Opcode和参数
Access Layer Model Message Access PDU 添加Opcode,应用密钥加密
Upper Transport Access PDU Transport PDU 应用层加密,添加SeqAuth
Lower Transport Transport PDU Segment PDU 分段,添加SeqZero和SegN
Network Layer Segment PDU Network PDU 添加网络头,网络层加密
Bearer Layer Network PDU 广播包/GATT包 封装成BLE协议格式

注意:每一层加密用的密钥都不一样。网络层用NetKey,传输层用AppKey。千万别搞混了。我曾经见过有人把AppKey当成NetKey用,结果整个网络都解密失败。

嗯,协议栈分层的好处就在这里——每层只管自己的事,出了问题也好排查。比如消息发不出去,先看承载层有没有广播,再看网络层TTL对不对,一层层往上查,很快就能定位问题。

我个人建议,刚开始学Mesh协议栈的朋友,先别急着看代码。拿张纸,把五层结构画出来,每层的数据格式写清楚。然后找一个实际的Mesh包,用手工一层层解包。这个过程走一遍,比你读十遍协议文档都管用。