2. Mesh网络基础概念:节点、元素、模型、状态、消息

好,咱们正式开始啃Mesh网络的核心概念。说实话,我刚接触蓝牙Mesh那会儿,被这些术语绕得够呛。什么节点、元素、模型,听着像哲学课。但搞嵌入式的人都知道,概念不清,后面写代码就是给自己挖坑。

这一章,我就用最直白的方式,把这五个核心概念——节点(Node)、元素(Element)、模型(Model)、状态(State)、消息(Message)——给你讲透。它们之间的关系,说白了就是一句话:节点是物理设备,元素是功能单元,模型定义行为,状态是数据,消息是通信手段。

核心记忆口诀:一个节点包含多个元素,每个元素包含多个模型,模型操作状态,状态通过消息传递。

2.1 节点(Node)——Mesh网络中的“人”

节点,就是加入Mesh网络的每一个设备。一个灯泡、一个开关、一个传感器,只要它加入了Mesh网络,就是一个节点。

我个人习惯把节点比作一个公司里的员工。每个员工都有自己的工号(单播地址),有自己的岗位职责(模型),也能跟其他员工沟通(收发消息)。

节点有几个关键属性:

  • 单播地址(Unicast Address):节点在网内的唯一ID,由配网器分配。我见过有人把地址写死在固件里,结果两个设备冲突,调试了一整天——嗯,千万别这么干。
  • 中继能力(Relay):节点是否转发别人的消息。不是所有节点都需要中继,比如电池供电的传感器,为了省电,通常不当中继。
  • 朋友节点(Friend):低功耗节点的“保姆”,帮它缓存消息。

避坑指南:我曾经在一个项目中,把所有节点都配置成中继节点,结果网络拥塞得一塌糊涂。后来才明白,中继节点数量控制在30%左右就够了,不是越多越好。

2.2 元素(Element)——节点里的“部门”

一个节点可以有多个元素。元素是什么?它是节点内部一个独立的功能单元,拥有自己的地址。

举个例子:一个三路开关面板,里面有三个物理按键。每个按键可以独立控制不同的灯。那这个面板节点,就至少需要三个元素——每个元素对应一个按键。

元素的特点:

  • 每个元素都有一个元素地址(Element Address),是节点单播地址的偏移。
  • 元素是模型的容器。模型必须挂载在元素上。
  • 一个节点至少有一个元素(主元素),最多可以有N个。

我记得有一次做智能灯项目,客户要求一个灯同时支持调光、色温和场景切换。我就在一个节点里设计了三个元素:一个负责调光,一个负责色温,一个负责场景。这样每个功能独立,互不干扰。

2.3 模型(Model)——元素里的“岗位说明书”

模型定义了元素能做什么。它是一组行为、状态和消息的集合。

蓝牙Mesh规范里把模型分为三类:

模型类型 说明 例子
服务器模型(Server Model) 维护状态,响应客户端请求 Generic OnOff Server
客户端模型(Client Model) 发送请求,读取或修改服务器状态 Generic OnOff Client
控制模型(Control Model) 既当服务器又当客户端,通常用于场景控制 Scene Control Model

你想想看,一个灯泡节点里,通常有一个Generic OnOff Server模型,它维护着“开关”这个状态。而开关节点里,有一个Generic OnOff Client模型,它发送“开”或“关”的消息。

注意:模型不能独立存在,必须挂载在元素上。一个元素可以挂载多个模型,但同一个模型不能重复挂载在同一个元素上。

2.4 状态(State)——模型里的“数据”

状态,就是模型当前的值。比如灯的亮度、开关的通断、色温的数值。

状态有几个重要特性:

  • 绑定(Binding):一个状态的变化可以触发另一个状态的变化。比如,你把灯关了(OnOff状态变为0),亮度状态(Level)也应该变为0。
  • 状态类型:分为布尔型、整型、枚举型等。蓝牙Mesh规范里对每个状态都有明确的字节定义。
  • 状态持久化:设备掉电后,状态是否保存?我建议关键状态(如开关、亮度)一定要保存到Flash,否则用户断电再上电,灯突然亮了,会吓一跳。

我曾经遇到过一个坑:客户反馈灯偶尔会自己亮。查了半天,发现是状态绑定没做好——调光模型把亮度设为0,但开关模型没跟着关。后来加了绑定逻辑,问题解决。

2.5 消息(Message)——设备间的“对话”

消息,就是节点之间通信的数据包。客户端模型发消息,服务器模型收消息并响应。

消息分为几类:

  • GET:客户端请求读取状态。服务器回复STATUS。
  • SET:客户端请求设置状态。服务器回复STATUS(可选)。
  • STATUS:服务器返回当前状态。
  • PUBLISH:服务器主动发布状态变化,不需要客户端请求。

消息的格式是固定的,包含操作码(Opcode)和参数。比如开关消息的操作码是0x8201,参数是一个字节:0x00表示关,0x01表示开。

// 伪代码示例:发送开关消息
uint8_t onoff = 0x01;  // 开
mesh_message_t msg;
msg.opcode = 0x8201;   // Generic OnOff Set
msg.params = &onoff;
msg.length = 1;
mesh_send(&msg, target_address);

2.6 五者关系——一张图看懂

说了这么多,咱们用一张SVG图把关系理清楚。这张图我画了很多遍,每次给团队新人培训都用它。

Mesh网络核心概念关系图 Mesh网络核心概念关系图 节点(Node) 元素 1(Element) Generic OnOff Server 模型(Model) Light Lightness Server 模型(Model) OnOff = 0 / 1 状态(State) 元素 2(Element) Generic OnOff Client 模型(Model) Light Lightness Client 模型(Model) 消息 消息 节点包含元素,元素挂载模型,模型操作状态 客户端模型通过消息与服务器模型通信

从这张图可以清楚看到:一个节点包含两个元素,每个元素挂载了不同的模型,模型维护着状态,而客户端和服务器模型之间通过消息通信。

2.7 实战中的关系理解

咱们用一个实际场景串一遍:

  1. 物理设备:一个智能灯泡,它是一个节点。
  2. 功能划分:灯泡里有调光和开关两个功能,所以设计两个元素。
  3. 行为定义:开关元素挂载Generic OnOff Server模型,调光元素挂载Light Lightness Server模型。
  4. 数据存储:模型维护状态——OnOff状态(0或1)和Lightness状态(0~65535)。
  5. 通信:手机App(客户端节点)发送消息(SET),灯泡收到后更新状态,并回复STATUS消息。

我的建议:设计产品时,先画一张类似上面的关系图。把节点、元素、模型、状态、消息都标清楚。我每次做新项目都这么干,能省掉后面至少一半的调试时间。

2.8 常见误区

误区 正确理解
一个节点只能有一个元素 一个节点可以有多个元素,每个元素独立编址
模型就是状态 模型是行为的集合,状态是模型维护的数据
消息只能由客户端发 服务器也可以主动发布(Publish)消息
状态只存在于服务器 客户端也可以有状态,比如缓存的上次读取值

嗯,这一章的内容就到这里。概念虽然多,但搞清楚了,后面学配置、学模型、学通信,就会顺畅很多。记住那张关系图,它就是Mesh网络的骨架。