低功耗蓝牙 Mesh 详解:架构、协议栈、安全与开发实践
目标:系统理解 BLE Mesh 的设计动机、协议栈、节点角色、消息模型、安全体系和开发流程,能独立搭建并调试一个小型 Mesh 网络。
适合读者:已掌握 BLE GAP/GATT 基础,想进一步学习 Mesh 的嵌入式开发者。
预计阅读 + 实践时间:3–5 天(阅读 1–2 天,动手 2–3 天)
文章目录
- 低功耗蓝牙 Mesh 详解:架构、协议栈、安全与开发实践
-
- 1. 为什么需要 BLE Mesh
- 2. BLE Mesh 是什么
- 3. BLE Mesh 与经典 BLE 拓扑的对比
- 4. 核心概念:节点、元素、模型、状态
- 5. Mesh 节点角色详解
- 6. Mesh 协议栈分层架构
-
- 6.1 消息封装过程
- 6.2 两种 Bearer
- 7. 消息模型:发布/订阅与地址类型
-
- 7.1 发布/订阅模型
- 7.2 三种地址类型
- 7.3 地址与模型的关系
- 8. 消息传输:Managed Flooding 机制
-
- 8.1 什么是 Managed Flooding
- 8.2 关键控制机制
- 8.3 泛洪的代价与优化
- 9. 配网(Provisioning)流程
- 10. 安全体系:三层安全
-
- 10.1 为什么需要两层加密
- 10.2 防重放机制
- 11. Mesh 模型详解
-
- 11.1 模型分类
- 11.2 常用标准模型
- 11.3 模型消息示例:Generic OnOff
- 12. 网络管理与配置
- 13. 开发平台与 SDK
- 14. 开发实践:从零搭建 Mesh 网络
-
- 14.1 实验目标
- 14.2 开发步骤
- 14.3 代码示意(Nordic/Zephyr 风格)
- 14.4 配网关键参数
- 15. 性能与规模考量
- 16. 常见问题与排障
- 17. 学习检查点
- 18. 动手实验
-
- 推荐实验顺序
- 19. 面试与工程高频问题
- 总结
1. 为什么需要 BLE Mesh
传统 BLE 是点对点或星形拓扑:一个 Central(手机)连接多个 Peripheral(传感器)。这种模型在消费电子里很成功,但在楼宇照明、工业传感、资产追踪等场景下会遇到明显瓶颈:
| 几百个灯要统一控制 | 一个 Central 连接数有限(通常 8–20 个) |
| 设备分布在整栋楼 | 单跳距离只有几十米 |
| 网络要覆盖大面积 | 星形拓扑依赖中心网关,单点故障 |
| 消息要广播到一组设备 | 需要逐个连接、逐个写入 |
| 低功耗节点要长期在线 | 保持连接功耗高 |
BLE Mesh 的核心思路是:用广播承载消息,用多跳中继扩展覆盖,用发布/订阅实现组控制。它不追求高吞吐,而是追求大规模、低功耗、可靠组播。
#mermaid-svg-3xiALg56i2VNw8g9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3xiALg56i2VNw8g9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3xiALg56i2VNw8g9 .error-icon{fill:#552222;}#mermaid-svg-3xiALg56i2VNw8g9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3xiALg56i2VNw8g9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3xiALg56i2VNw8g9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3xiALg56i2VNw8g9 .marker.cross{stroke:#333333;}#mermaid-svg-3xiALg56i2VNw8g9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3xiALg56i2VNw8g9 p{margin:0;}#mermaid-svg-3xiALg56i2VNw8g9 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3xiALg56i2VNw8g9 .cluster-label text{fill:#333;}#mermaid-svg-3xiALg56i2VNw8g9 .cluster-label span{color:#333;}#mermaid-svg-3xiALg56i2VNw8g9 .cluster-label span p{background-color:transparent;}#mermaid-svg-3xiALg56i2VNw8g9 .label text,#mermaid-svg-3xiALg56i2VNw8g9 span{fill:#333;color:#333;}#mermaid-svg-3xiALg56i2VNw8g9 .node rect,#mermaid-svg-3xiALg56i2VNw8g9 .node circle,#mermaid-svg-3xiALg56i2VNw8g9 .node ellipse,#mermaid-svg-3xiALg56i2VNw8g9 .node polygon,#mermaid-svg-3xiALg56i2VNw8g9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3xiALg56i2VNw8g9 .rough-node .label text,#mermaid-svg-3xiALg56i2VNw8g9 .node .label text,#mermaid-svg-3xiALg56i2VNw8g9 .image-shape .label,#mermaid-svg-3xiALg56i2VNw8g9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-3xiALg56i2VNw8g9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3xiALg56i2VNw8g9 .rough-node .label,#mermaid-svg-3xiALg56i2VNw8g9 .node .label,#mermaid-svg-3xiALg56i2VNw8g9 .image-shape .label,#mermaid-svg-3xiALg56i2VNw8g9 .icon-shape .label{text-align:center;}#mermaid-svg-3xiALg56i2VNw8g9 .node.clickable{cursor:pointer;}#mermaid-svg-3xiALg56i2VNw8g9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3xiALg56i2VNw8g9 .arrowheadPath{fill:#333333;}#mermaid-svg-3xiALg56i2VNw8g9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3xiALg56i2VNw8g9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3xiALg56i2VNw8g9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3xiALg56i2VNw8g9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3xiALg56i2VNw8g9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3xiALg56i2VNw8g9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3xiALg56i2VNw8g9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3xiALg56i2VNw8g9 .cluster text{fill:#333;}#mermaid-svg-3xiALg56i2VNw8g9 .cluster span{color:#333;}#mermaid-svg-3xiALg56i2VNw8g9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3xiALg56i2VNw8g9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3xiALg56i2VNw8g9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-3xiALg56i2VNw8g9 .icon-shape,#mermaid-svg-3xiALg56i2VNw8g9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3xiALg56i2VNw8g9 .icon-shape p,#mermaid-svg-3xiALg56i2VNw8g9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3xiALg56i2VNw8g9 .icon-shape .label rect,#mermaid-svg-3xiALg56i2VNw8g9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3xiALg56i2VNw8g9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3xiALg56i2VNw8g9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3xiALg56i2VNw8g9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
BLE Mesh 多跳
Node
Node
Node
Node
Node
Node
传统 BLE 星形
Central
Peripheral 1
Peripheral 2
Peripheral 3
Peripheral 4
2. BLE Mesh 是什么
Bluetooth Mesh 是 Bluetooth SIG 于 2017 年发布的网络层规范(Mesh Profile 1.0,后续有 1.0.1、1.1),它不是新的射频技术,而是建立在 BLE 广播和 GATT 之上的组网协议。
| 基础射频 | 仍然是 BLE 的 2.4 GHz、40 信道、GFSK |
| 承载方式 | Advertising Bearer(广播承载)+ GATT Bearer(代理承载) |
| 拓扑 | 多跳、泛洪式(Managed Flooding) |
| 寻址 | 单播地址、组地址、虚拟地址 |
| 安全 | 网络层 + 应用层 + 设备层三重密钥 |
| 典型规模 | 几十到几百个节点(理论可达 32767 个单播地址) |
| 典型应用 | 智能照明、楼宇自动化、工业传感、资产追踪 |
关键理解:Mesh 不是“BLE 的升级版”,而是“在 BLE 广播上搭的一套组网协议”。它牺牲了吞吐和实时性,换来了规模、覆盖和组控能力。
3. BLE Mesh 与经典 BLE 拓扑的对比
| 拓扑 | 点对点 / 星形 | 多跳 Mesh |
| 连接方式 | 面向连接(Connected) | 主要基于广播(无连接) |
| 消息传播 | 一对一读写/通知 | 发布/订阅 + 泛洪 |
| 覆盖范围 | 单跳,几十米 | 多跳,可覆盖整栋楼 |
| 节点数量 | 受 Central 连接数限制 | 理论上千、实际几百 |
| 吞吐 | 高(可达数百 Kbps) | 低(适合小控制消息) |
| 延迟 | 低且确定 | 较高且受跳数影响 |
| 功耗 | 连接保持功耗高 | 低功耗节点可休眠 |
| 安全 | SMP 配对 + 链路加密 | 网络层/应用层/设备层三级密钥 |
| 典型协议 | GATT Service | Mesh Model(Generic/Lighting/Sensor) |
4. 核心概念:节点、元素、模型、状态
Mesh 的数据组织是层级式的,理解这四个概念是入门关键。
#mermaid-svg-VarsUbfwXTx28qZq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VarsUbfwXTx28qZq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VarsUbfwXTx28qZq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VarsUbfwXTx28qZq .error-icon{fill:#552222;}#mermaid-svg-VarsUbfwXTx28qZq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VarsUbfwXTx28qZq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VarsUbfwXTx28qZq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VarsUbfwXTx28qZq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VarsUbfwXTx28qZq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VarsUbfwXTx28qZq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VarsUbfwXTx28qZq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VarsUbfwXTx28qZq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VarsUbfwXTx28qZq .marker.cross{stroke:#333333;}#mermaid-svg-VarsUbfwXTx28qZq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VarsUbfwXTx28qZq p{margin:0;}#mermaid-svg-VarsUbfwXTx28qZq .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-VarsUbfwXTx28qZq .cluster-label text{fill:#333;}#mermaid-svg-VarsUbfwXTx28qZq .cluster-label span{color:#333;}#mermaid-svg-VarsUbfwXTx28qZq .cluster-label span p{background-color:transparent;}#mermaid-svg-VarsUbfwXTx28qZq .label text,#mermaid-svg-VarsUbfwXTx28qZq span{fill:#333;color:#333;}#mermaid-svg-VarsUbfwXTx28qZq .node rect,#mermaid-svg-VarsUbfwXTx28qZq .node circle,#mermaid-svg-VarsUbfwXTx28qZq .node ellipse,#mermaid-svg-VarsUbfwXTx28qZq .node polygon,#mermaid-svg-VarsUbfwXTx28qZq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VarsUbfwXTx28qZq .rough-node .label text,#mermaid-svg-VarsUbfwXTx28qZq .node .label text,#mermaid-svg-VarsUbfwXTx28qZq .image-shape .label,#mermaid-svg-VarsUbfwXTx28qZq .icon-shape .label{text-anchor:middle;}#mermaid-svg-VarsUbfwXTx28qZq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VarsUbfwXTx28qZq .rough-node .label,#mermaid-svg-VarsUbfwXTx28qZq .node .label,#mermaid-svg-VarsUbfwXTx28qZq .image-shape .label,#mermaid-svg-VarsUbfwXTx28qZq .icon-shape .label{text-align:center;}#mermaid-svg-VarsUbfwXTx28qZq .node.clickable{cursor:pointer;}#mermaid-svg-VarsUbfwXTx28qZq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VarsUbfwXTx28qZq .arrowheadPath{fill:#333333;}#mermaid-svg-VarsUbfwXTx28qZq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VarsUbfwXTx28qZq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VarsUbfwXTx28qZq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VarsUbfwXTx28qZq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VarsUbfwXTx28qZq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VarsUbfwXTx28qZq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VarsUbfwXTx28qZq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VarsUbfwXTx28qZq .cluster text{fill:#333;}#mermaid-svg-VarsUbfwXTx28qZq .cluster span{color:#333;}#mermaid-svg-VarsUbfwXTx28qZq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VarsUbfwXTx28qZq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VarsUbfwXTx28qZq rect.text{fill:none;stroke-width:0;}#mermaid-svg-VarsUbfwXTx28qZq .icon-shape,#mermaid-svg-VarsUbfwXTx28qZq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VarsUbfwXTx28qZq .icon-shape p,#mermaid-svg-VarsUbfwXTx28qZq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VarsUbfwXTx28qZq .icon-shape .label rect,#mermaid-svg-VarsUbfwXTx28qZq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VarsUbfwXTx28qZq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VarsUbfwXTx28qZq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VarsUbfwXTx28qZq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Node(节点)一个 Mesh 设备
Element 1(主功能)
Element 2(扩展功能)
Model A(Generic OnOff Server)
Model B(Generic Level Server)
Model C(Light Lightness Server)
State: OnOff
State: Level
State: Lightness
| Node(节点) | 一个加入 Mesh 网络的设备 | 一台设备 |
| Element(元素) | 节点内的功能单元,每个 Element 有独立单播地址 | 设备上的一个功能模块 |
| Model(模型) | 定义一类行为(Server/Client),包含状态和消息 | 功能定义(如“开关服务”) |
| State(状态) | 模型维护的数据(如 OnOff、Level、亮度) | 变量 |
| Binding(绑定) | 一个模型的状态变化可触发另一个模型 | 模型间联动 |
重要规则:一个节点至少有一个 Element(Primary Element),每个 Element 有唯一单播地址;Model 必须属于某个 Element。
5. Mesh 节点角色详解
Mesh 节点可以承担多种角色,角色可以叠加。
#mermaid-svg-dCpPrky0EgWLLxnr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dCpPrky0EgWLLxnr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dCpPrky0EgWLLxnr .error-icon{fill:#552222;}#mermaid-svg-dCpPrky0EgWLLxnr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dCpPrky0EgWLLxnr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dCpPrky0EgWLLxnr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dCpPrky0EgWLLxnr .marker.cross{stroke:#333333;}#mermaid-svg-dCpPrky0EgWLLxnr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dCpPrky0EgWLLxnr p{margin:0;}#mermaid-svg-dCpPrky0EgWLLxnr .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dCpPrky0EgWLLxnr .cluster-label text{fill:#333;}#mermaid-svg-dCpPrky0EgWLLxnr .cluster-label span{color:#333;}#mermaid-svg-dCpPrky0EgWLLxnr .cluster-label span p{background-color:transparent;}#mermaid-svg-dCpPrky0EgWLLxnr .label text,#mermaid-svg-dCpPrky0EgWLLxnr span{fill:#333;color:#333;}#mermaid-svg-dCpPrky0EgWLLxnr .node rect,#mermaid-svg-dCpPrky0EgWLLxnr .node circle,#mermaid-svg-dCpPrky0EgWLLxnr .node ellipse,#mermaid-svg-dCpPrky0EgWLLxnr .node polygon,#mermaid-svg-dCpPrky0EgWLLxnr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dCpPrky0EgWLLxnr .rough-node .label text,#mermaid-svg-dCpPrky0EgWLLxnr .node .label text,#mermaid-svg-dCpPrky0EgWLLxnr .image-shape .label,#mermaid-svg-dCpPrky0EgWLLxnr .icon-shape .label{text-anchor:middle;}#mermaid-svg-dCpPrky0EgWLLxnr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dCpPrky0EgWLLxnr .rough-node .label,#mermaid-svg-dCpPrky0EgWLLxnr .node .label,#mermaid-svg-dCpPrky0EgWLLxnr .image-shape .label,#mermaid-svg-dCpPrky0EgWLLxnr .icon-shape .label{text-align:center;}#mermaid-svg-dCpPrky0EgWLLxnr .node.clickable{cursor:pointer;}#mermaid-svg-dCpPrky0EgWLLxnr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dCpPrky0EgWLLxnr .arrowheadPath{fill:#333333;}#mermaid-svg-dCpPrky0EgWLLxnr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dCpPrky0EgWLLxnr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dCpPrky0EgWLLxnr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dCpPrky0EgWLLxnr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dCpPrky0EgWLLxnr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dCpPrky0EgWLLxnr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dCpPrky0EgWLLxnr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dCpPrky0EgWLLxnr .cluster text{fill:#333;}#mermaid-svg-dCpPrky0EgWLLxnr .cluster span{color:#333;}#mermaid-svg-dCpPrky0EgWLLxnr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dCpPrky0EgWLLxnr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dCpPrky0EgWLLxnr rect.text{fill:none;stroke-width:0;}#mermaid-svg-dCpPrky0EgWLLxnr .icon-shape,#mermaid-svg-dCpPrky0EgWLLxnr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dCpPrky0EgWLLxnr .icon-shape p,#mermaid-svg-dCpPrky0EgWLLxnr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dCpPrky0EgWLLxnr .icon-shape .label rect,#mermaid-svg-dCpPrky0EgWLLxnr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dCpPrky0EgWLLxnr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dCpPrky0EgWLLxnr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dCpPrky0EgWLLxnr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Mesh 节点角色
普通节点(Normal Node)
中继节点(Relay Node)
代理节点(Proxy Node)
友节点(Friend Node)
低功耗节点(Low Power Node)
| 普通节点 | 收发自己的消息 | 传感器、灯 | 中 |
| Relay Node | 转发其他节点的消息,扩展覆盖 | 常供电的灯/网关 | 较高 |
| Proxy Node | 通过 GATT 让手机等非 Mesh 设备接入 | 网关、常供电节点 | 较高 |
| Friend Node | 为低功耗节点缓存消息 | 常供电节点 | 较高 |
| Low Power Node (LPN) | 大部分时间休眠,周期性向 Friend 取消息 | 电池传感器、开关 | 极低 |
Friend 与 LPN 的配合流程:
其他节点
Friend Node
Low Power Node
其他节点
Friend Node
Low Power Node
#mermaid-svg-hsBV3xvaCs6mGnBr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hsBV3xvaCs6mGnBr .error-icon{fill:#552222;}#mermaid-svg-hsBV3xvaCs6mGnBr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hsBV3xvaCs6mGnBr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hsBV3xvaCs6mGnBr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hsBV3xvaCs6mGnBr .marker.cross{stroke:#333333;}#mermaid-svg-hsBV3xvaCs6mGnBr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hsBV3xvaCs6mGnBr p{margin:0;}#mermaid-svg-hsBV3xvaCs6mGnBr .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hsBV3xvaCs6mGnBr text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hsBV3xvaCs6mGnBr .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-hsBV3xvaCs6mGnBr .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-hsBV3xvaCs6mGnBr #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-hsBV3xvaCs6mGnBr .sequenceNumber{fill:white;}#mermaid-svg-hsBV3xvaCs6mGnBr #sequencenumber{fill:#333;}#mermaid-svg-hsBV3xvaCs6mGnBr #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-hsBV3xvaCs6mGnBr .messageText{fill:#333;stroke:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hsBV3xvaCs6mGnBr .labelText,#mermaid-svg-hsBV3xvaCs6mGnBr .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .loopText,#mermaid-svg-hsBV3xvaCs6mGnBr .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-hsBV3xvaCs6mGnBr .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-hsBV3xvaCs6mGnBr .noteText,#mermaid-svg-hsBV3xvaCs6mGnBr .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-hsBV3xvaCs6mGnBr .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hsBV3xvaCs6mGnBr .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hsBV3xvaCs6mGnBr .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-hsBV3xvaCs6mGnBr .actorPopupMenu{position:absolute;}#mermaid-svg-hsBV3xvaCs6mGnBr .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-hsBV3xvaCs6mGnBr .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-hsBV3xvaCs6mGnBr .actor-man circle,#mermaid-svg-hsBV3xvaCs6mGnBr line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-hsBV3xvaCs6mGnBr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Friend Request(建立友谊)
1
Friend Offer
2
Friend Poll(周期性询问)
3
发给 LPN 的消息
4
缓存消息(Friend Queue)
5
Friend Poll
6
下发缓存的消息
7
Friend Poll(确认收到)
8
工程意义:LPN 让电池供电的开关/传感器可以休眠数秒甚至数分钟,同时不丢消息。这是 Mesh 低功耗的核心机制。
6. Mesh 协议栈分层架构
Mesh 协议栈是在 BLE 协议栈之上叠加的一层,分为 7 层:
#mermaid-svg-EQ7JyX1C42HeTe9l{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EQ7JyX1C42HeTe9l .error-icon{fill:#552222;}#mermaid-svg-EQ7JyX1C42HeTe9l .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EQ7JyX1C42HeTe9l .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EQ7JyX1C42HeTe9l .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EQ7JyX1C42HeTe9l .marker.cross{stroke:#333333;}#mermaid-svg-EQ7JyX1C42HeTe9l svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EQ7JyX1C42HeTe9l p{margin:0;}#mermaid-svg-EQ7JyX1C42HeTe9l .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster-label text{fill:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster-label span{color:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster-label span p{background-color:transparent;}#mermaid-svg-EQ7JyX1C42HeTe9l .label text,#mermaid-svg-EQ7JyX1C42HeTe9l span{fill:#333;color:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l .node rect,#mermaid-svg-EQ7JyX1C42HeTe9l .node circle,#mermaid-svg-EQ7JyX1C42HeTe9l .node ellipse,#mermaid-svg-EQ7JyX1C42HeTe9l .node polygon,#mermaid-svg-EQ7JyX1C42HeTe9l .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EQ7JyX1C42HeTe9l .rough-node .label text,#mermaid-svg-EQ7JyX1C42HeTe9l .node .label text,#mermaid-svg-EQ7JyX1C42HeTe9l .image-shape .label,#mermaid-svg-EQ7JyX1C42HeTe9l .icon-shape .label{text-anchor:middle;}#mermaid-svg-EQ7JyX1C42HeTe9l .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EQ7JyX1C42HeTe9l .rough-node .label,#mermaid-svg-EQ7JyX1C42HeTe9l .node .label,#mermaid-svg-EQ7JyX1C42HeTe9l .image-shape .label,#mermaid-svg-EQ7JyX1C42HeTe9l .icon-shape .label{text-align:center;}#mermaid-svg-EQ7JyX1C42HeTe9l .node.clickable{cursor:pointer;}#mermaid-svg-EQ7JyX1C42HeTe9l .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EQ7JyX1C42HeTe9l .arrowheadPath{fill:#333333;}#mermaid-svg-EQ7JyX1C42HeTe9l .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EQ7JyX1C42HeTe9l .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EQ7JyX1C42HeTe9l .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EQ7JyX1C42HeTe9l .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EQ7JyX1C42HeTe9l .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EQ7JyX1C42HeTe9l .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster text{fill:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l .cluster span{color:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EQ7JyX1C42HeTe9l .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EQ7JyX1C42HeTe9l rect.text{fill:none;stroke-width:0;}#mermaid-svg-EQ7JyX1C42HeTe9l .icon-shape,#mermaid-svg-EQ7JyX1C42HeTe9l .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EQ7JyX1C42HeTe9l .icon-shape p,#mermaid-svg-EQ7JyX1C42HeTe9l .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EQ7JyX1C42HeTe9l .icon-shape .label rect,#mermaid-svg-EQ7JyX1C42HeTe9l .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EQ7JyX1C42HeTe9l .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EQ7JyX1C42HeTe9l .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EQ7JyX1C42HeTe9l :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
BLE 协议栈
Mesh 协议栈
Model Layer(模型层)
Foundation Model Layer(基础模型层)
Access Layer(访问层)
Upper Transport Layer(上层传输)
Lower Transport Layer(下层传输)
Network Layer(网络层)
Bearer Layer(承载层)
GATT
Advertising
| Model Layer | 定义应用行为 | Generic/Lighting/Sensor Model |
| Foundation Model Layer | 网络管理模型 | Configuration Server/Client、Health Model |
| Access Layer | 应用数据的封装/解封装 | Access PDU、Opcode、参数 |
| Upper Transport Layer | 应用层加密/认证、分片控制 | AppKey、Device Key、分片 |
| Lower Transport Layer | 分段与重组(SAR) | Segment/Unsegmented PDU |
| Network Layer | 网络寻址、网络加密、中继判断 | NetKey、TTL、SEQ、IV Index |
| Bearer Layer | 承载方式 | Advertising Bearer、GATT Bearer |
6.1 消息封装过程
一条应用消息从 Model 发出,逐层封装:
Model 消息
↓ Access Layer:加 Opcode + 参数 → Access PDU
↓ Upper Transport:AppKey 加密 + 认证 → Upper Transport PDU
↓ Lower Transport:分段(如需要)→ Lower Transport PDU
↓ Network Layer:NetKey 加密 + 寻址 + TTL + SEQ → Network PDU
↓ Bearer:放入 BLE 广播包或 GATT 写入
6.2 两种 Bearer
| Advertising Bearer | 用 BLE 广播承载 Mesh 消息 | 节点间通信(主要方式) |
| GATT Bearer | 用 GATT 连接承载 Mesh 消息 | 手机通过 Proxy 接入 Mesh |
注意:Mesh 消息在广播包里使用 Mesh Message AD Type(0x2A) 或 Mesh Beacon(0x2B),不是普通 BLE 广播。
7. 消息模型:发布/订阅与地址类型
7.1 发布/订阅模型
Mesh 不采用“客户端直接调用服务端”的一对一模式,而是发布/订阅:
#mermaid-svg-7H26XJEHj6trXdn9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7H26XJEHj6trXdn9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7H26XJEHj6trXdn9 .error-icon{fill:#552222;}#mermaid-svg-7H26XJEHj6trXdn9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7H26XJEHj6trXdn9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7H26XJEHj6trXdn9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7H26XJEHj6trXdn9 .marker.cross{stroke:#333333;}#mermaid-svg-7H26XJEHj6trXdn9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7H26XJEHj6trXdn9 p{margin:0;}#mermaid-svg-7H26XJEHj6trXdn9 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-7H26XJEHj6trXdn9 .cluster-label text{fill:#333;}#mermaid-svg-7H26XJEHj6trXdn9 .cluster-label span{color:#333;}#mermaid-svg-7H26XJEHj6trXdn9 .cluster-label span p{background-color:transparent;}#mermaid-svg-7H26XJEHj6trXdn9 .label text,#mermaid-svg-7H26XJEHj6trXdn9 span{fill:#333;color:#333;}#mermaid-svg-7H26XJEHj6trXdn9 .node rect,#mermaid-svg-7H26XJEHj6trXdn9 .node circle,#mermaid-svg-7H26XJEHj6trXdn9 .node ellipse,#mermaid-svg-7H26XJEHj6trXdn9 .node polygon,#mermaid-svg-7H26XJEHj6trXdn9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7H26XJEHj6trXdn9 .rough-node .label text,#mermaid-svg-7H26XJEHj6trXdn9 .node .label text,#mermaid-svg-7H26XJEHj6trXdn9 .image-shape .label,#mermaid-svg-7H26XJEHj6trXdn9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-7H26XJEHj6trXdn9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7H26XJEHj6trXdn9 .rough-node .label,#mermaid-svg-7H26XJEHj6trXdn9 .node .label,#mermaid-svg-7H26XJEHj6trXdn9 .image-shape .label,#mermaid-svg-7H26XJEHj6trXdn9 .icon-shape .label{text-align:center;}#mermaid-svg-7H26XJEHj6trXdn9 .node.clickable{cursor:pointer;}#mermaid-svg-7H26XJEHj6trXdn9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7H26XJEHj6trXdn9 .arrowheadPath{fill:#333333;}#mermaid-svg-7H26XJEHj6trXdn9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7H26XJEHj6trXdn9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7H26XJEHj6trXdn9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7H26XJEHj6trXdn9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7H26XJEHj6trXdn9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7H26XJEHj6trXdn9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7H26XJEHj6trXdn9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7H26XJEHj6trXdn9 .cluster text{fill:#333;}#mermaid-svg-7H26XJEHj6trXdn9 .cluster span{color:#333;}#mermaid-svg-7H26XJEHj6trXdn9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7H26XJEHj6trXdn9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7H26XJEHj6trXdn9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-7H26XJEHj6trXdn9 .icon-shape,#mermaid-svg-7H26XJEHj6trXdn9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7H26XJEHj6trXdn9 .icon-shape p,#mermaid-svg-7H26XJEHj6trXdn9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7H26XJEHj6trXdn9 .icon-shape .label rect,#mermaid-svg-7H26XJEHj6trXdn9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7H26XJEHj6trXdn9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7H26XJEHj6trXdn9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7H26XJEHj6trXdn9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
发布到组地址
Publisher(发布者)
Group Address(组地址 0xC000)
Subscriber 1
Subscriber 2
Subscriber 3
| Publish | 模型将消息发到某个地址 |
| Subscribe | 模型监听某个地址的消息 |
| Publish Address | 可以是单播、组地址、虚拟地址 |
| Subscription List | 每个模型可订阅多个地址 |
优势:一条消息可以同时控制一组灯,无需逐个连接。
7.2 三种地址类型
| Unicast Address | 0x0001–0x7FFF | 标识单个 Element | 0x0005 |
| Group Address | 0xC000–0xFEFF | 组播,多个节点订阅 | 0xC001(一楼灯组) |
| Virtual Address | 128-bit UUID 哈希 | 用 UUID 标识组 | 基于 UUID 生成 |
7.3 地址与模型的关系
#mermaid-svg-Ey8ahOVms8mGCk1X{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ey8ahOVms8mGCk1X .error-icon{fill:#552222;}#mermaid-svg-Ey8ahOVms8mGCk1X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ey8ahOVms8mGCk1X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ey8ahOVms8mGCk1X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ey8ahOVms8mGCk1X .marker.cross{stroke:#333333;}#mermaid-svg-Ey8ahOVms8mGCk1X svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ey8ahOVms8mGCk1X p{margin:0;}#mermaid-svg-Ey8ahOVms8mGCk1X .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster-label text{fill:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster-label span{color:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster-label span p{background-color:transparent;}#mermaid-svg-Ey8ahOVms8mGCk1X .label text,#mermaid-svg-Ey8ahOVms8mGCk1X span{fill:#333;color:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X .node rect,#mermaid-svg-Ey8ahOVms8mGCk1X .node circle,#mermaid-svg-Ey8ahOVms8mGCk1X .node ellipse,#mermaid-svg-Ey8ahOVms8mGCk1X .node polygon,#mermaid-svg-Ey8ahOVms8mGCk1X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ey8ahOVms8mGCk1X .rough-node .label text,#mermaid-svg-Ey8ahOVms8mGCk1X .node .label text,#mermaid-svg-Ey8ahOVms8mGCk1X .image-shape .label,#mermaid-svg-Ey8ahOVms8mGCk1X .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ey8ahOVms8mGCk1X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ey8ahOVms8mGCk1X .rough-node .label,#mermaid-svg-Ey8ahOVms8mGCk1X .node .label,#mermaid-svg-Ey8ahOVms8mGCk1X .image-shape .label,#mermaid-svg-Ey8ahOVms8mGCk1X .icon-shape .label{text-align:center;}#mermaid-svg-Ey8ahOVms8mGCk1X .node.clickable{cursor:pointer;}#mermaid-svg-Ey8ahOVms8mGCk1X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ey8ahOVms8mGCk1X .arrowheadPath{fill:#333333;}#mermaid-svg-Ey8ahOVms8mGCk1X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ey8ahOVms8mGCk1X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ey8ahOVms8mGCk1X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ey8ahOVms8mGCk1X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ey8ahOVms8mGCk1X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ey8ahOVms8mGCk1X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster text{fill:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X .cluster span{color:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ey8ahOVms8mGCk1X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ey8ahOVms8mGCk1X rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ey8ahOVms8mGCk1X .icon-shape,#mermaid-svg-Ey8ahOVms8mGCk1X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ey8ahOVms8mGCk1X .icon-shape p,#mermaid-svg-Ey8ahOVms8mGCk1X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ey8ahOVms8mGCk1X .icon-shape .label rect,#mermaid-svg-Ey8ahOVms8mGCk1X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ey8ahOVms8mGCk1X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ey8ahOVms8mGCk1X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ey8ahOVms8mGCk1X :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Mesh 网络
订阅
订阅
订阅
Unicast 0x0001Node A Element 1
Unicast 0x0002Node B Element 1
Unicast 0x0003Node C Element 1
Group 0xC001客厅灯组
Publisher 发到 0xC001
8. 消息传输:Managed Flooding 机制
8.1 什么是 Managed Flooding
Mesh 不使用路由表,而是受控泛洪:节点收到消息后,如果 TTL 允许且不是自己发的,就转发。
目标节点
Relay 2
Relay 1
源节点
目标节点
Relay 2
Relay 1
源节点
#mermaid-svg-LBl0Qpm7vXMERxFp{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LBl0Qpm7vXMERxFp .error-icon{fill:#552222;}#mermaid-svg-LBl0Qpm7vXMERxFp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LBl0Qpm7vXMERxFp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LBl0Qpm7vXMERxFp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LBl0Qpm7vXMERxFp .marker.cross{stroke:#333333;}#mermaid-svg-LBl0Qpm7vXMERxFp svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LBl0Qpm7vXMERxFp p{margin:0;}#mermaid-svg-LBl0Qpm7vXMERxFp .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LBl0Qpm7vXMERxFp text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LBl0Qpm7vXMERxFp .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-LBl0Qpm7vXMERxFp .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-LBl0Qpm7vXMERxFp #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-LBl0Qpm7vXMERxFp .sequenceNumber{fill:white;}#mermaid-svg-LBl0Qpm7vXMERxFp #sequencenumber{fill:#333;}#mermaid-svg-LBl0Qpm7vXMERxFp #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-LBl0Qpm7vXMERxFp .messageText{fill:#333;stroke:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LBl0Qpm7vXMERxFp .labelText,#mermaid-svg-LBl0Qpm7vXMERxFp .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .loopText,#mermaid-svg-LBl0Qpm7vXMERxFp .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LBl0Qpm7vXMERxFp .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-LBl0Qpm7vXMERxFp .noteText,#mermaid-svg-LBl0Qpm7vXMERxFp .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-LBl0Qpm7vXMERxFp .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LBl0Qpm7vXMERxFp .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LBl0Qpm7vXMERxFp .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LBl0Qpm7vXMERxFp .actorPopupMenu{position:absolute;}#mermaid-svg-LBl0Qpm7vXMERxFp .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-LBl0Qpm7vXMERxFp .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LBl0Qpm7vXMERxFp .actor-man circle,#mermaid-svg-LBl0Qpm7vXMERxFp line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-LBl0Qpm7vXMERxFp :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
通过 SEQ + 源地址去重
消息(TTL=5)
1
消息(TTL=5)
2
转发(TTL=4)
3
转发(TTL=4)
4
收到重复消息,去重
5
8.2 关键控制机制
| TTL | 限制跳数,防止无限泛洪 |
| SEQ(Sequence Number) | 每条消息递增,用于去重和防重放 |
| IV Index | 网络级计数器,配合 SEQ 防重放 |
| Message Cache | 节点缓存最近消息,重复则丢弃 |
| Relay 开关 | 可配置是否中继,控制泛洪规模 |
| Friend Queue | 为 LPN 缓存消息 |
8.3 泛洪的代价与优化
| 消息重复多 | 合理设置 TTL、限制 Relay 节点数量 |
| 网络拥塞 | 控制发布频率、使用组地址而非广播地址 |
| 延迟随跳数增加 | 减少跳数、增加 Relay 密度 |
| 功耗高 | 非关键节点关闭 Relay,使用 LPN |
9. 配网(Provisioning)流程
新设备加入 Mesh 网络需要经过 Provisioning(配网),由 Provisioner(通常是手机/网关)完成。
未配网设备
Provisioner
未配网设备
Provisioner
#mermaid-svg-UKJeitMrhS6bpjUX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UKJeitMrhS6bpjUX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UKJeitMrhS6bpjUX .error-icon{fill:#552222;}#mermaid-svg-UKJeitMrhS6bpjUX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UKJeitMrhS6bpjUX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UKJeitMrhS6bpjUX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UKJeitMrhS6bpjUX .marker.cross{stroke:#333333;}#mermaid-svg-UKJeitMrhS6bpjUX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UKJeitMrhS6bpjUX p{margin:0;}#mermaid-svg-UKJeitMrhS6bpjUX .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UKJeitMrhS6bpjUX text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-UKJeitMrhS6bpjUX .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UKJeitMrhS6bpjUX .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-UKJeitMrhS6bpjUX .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-UKJeitMrhS6bpjUX .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-UKJeitMrhS6bpjUX #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-UKJeitMrhS6bpjUX .sequenceNumber{fill:white;}#mermaid-svg-UKJeitMrhS6bpjUX #sequencenumber{fill:#333;}#mermaid-svg-UKJeitMrhS6bpjUX #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-UKJeitMrhS6bpjUX .messageText{fill:#333;stroke:none;}#mermaid-svg-UKJeitMrhS6bpjUX .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UKJeitMrhS6bpjUX .labelText,#mermaid-svg-UKJeitMrhS6bpjUX .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-UKJeitMrhS6bpjUX .loopText,#mermaid-svg-UKJeitMrhS6bpjUX .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-UKJeitMrhS6bpjUX .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UKJeitMrhS6bpjUX .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-UKJeitMrhS6bpjUX .noteText,#mermaid-svg-UKJeitMrhS6bpjUX .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-UKJeitMrhS6bpjUX .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UKJeitMrhS6bpjUX .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UKJeitMrhS6bpjUX .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UKJeitMrhS6bpjUX .actorPopupMenu{position:absolute;}#mermaid-svg-UKJeitMrhS6bpjUX .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-UKJeitMrhS6bpjUX .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UKJeitMrhS6bpjUX .actor-man circle,#mermaid-svg-UKJeitMrhS6bpjUX line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-UKJeitMrhS6bpjUX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
ECDH P-256 生成共享密钥
Mesh Beacon(广播可配网)
1
Provisioning Invite
2
Capabilities
3
Provisioning Start
4
Public Key
5
Public Key
6
认证( blink / 输入 / 输出 / 静态 OOB)
7
认证确认
8
分发 Provisioning Data(NetKey、Unicast 地址、IV Index)
9
保存配网信息,加入网络
10
Provisioning Complete
11
| Beacon | 设备广播“我可被配网” | 使用 PB-ADV 或 PB-GATT |
| Invite/Capabilities | 交换能力(元素数、支持算法) | — |
| Public Key 交换 | ECDH P-256 | 抗窃听 |
| 认证 | Blink/Input/Output/Static OOB/No OOB | 决定是否抗 MITM |
| 分发配网数据 | NetKey、Unicast Address、IV Index | 用设备公钥加密 |
配网认证方式对比:
| No OOB | 低(可被中间人) | 快速配网、低安全场景 |
| Static OOB | 中 | 设备预置密钥 |
| Output OOB | 高 | 设备显示、用户输入 |
| Input OOB | 高 | 用户操作设备 |
| Blink | 中 | 灯具闪烁确认 |
10. 安全体系:三层安全
Mesh 的安全是分层加密的,这是它与传统 BLE 最大的不同之一。
#mermaid-svg-rN8JqtmVY3CeE3L3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rN8JqtmVY3CeE3L3 .error-icon{fill:#552222;}#mermaid-svg-rN8JqtmVY3CeE3L3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rN8JqtmVY3CeE3L3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .marker.cross{stroke:#333333;}#mermaid-svg-rN8JqtmVY3CeE3L3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rN8JqtmVY3CeE3L3 p{margin:0;}#mermaid-svg-rN8JqtmVY3CeE3L3 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster-label text{fill:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster-label span{color:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster-label span p{background-color:transparent;}#mermaid-svg-rN8JqtmVY3CeE3L3 .label text,#mermaid-svg-rN8JqtmVY3CeE3L3 span{fill:#333;color:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .node rect,#mermaid-svg-rN8JqtmVY3CeE3L3 .node circle,#mermaid-svg-rN8JqtmVY3CeE3L3 .node ellipse,#mermaid-svg-rN8JqtmVY3CeE3L3 .node polygon,#mermaid-svg-rN8JqtmVY3CeE3L3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .rough-node .label text,#mermaid-svg-rN8JqtmVY3CeE3L3 .node .label text,#mermaid-svg-rN8JqtmVY3CeE3L3 .image-shape .label,#mermaid-svg-rN8JqtmVY3CeE3L3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-rN8JqtmVY3CeE3L3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .rough-node .label,#mermaid-svg-rN8JqtmVY3CeE3L3 .node .label,#mermaid-svg-rN8JqtmVY3CeE3L3 .image-shape .label,#mermaid-svg-rN8JqtmVY3CeE3L3 .icon-shape .label{text-align:center;}#mermaid-svg-rN8JqtmVY3CeE3L3 .node.clickable{cursor:pointer;}#mermaid-svg-rN8JqtmVY3CeE3L3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .arrowheadPath{fill:#333333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rN8JqtmVY3CeE3L3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rN8JqtmVY3CeE3L3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rN8JqtmVY3CeE3L3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster text{fill:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 .cluster span{color:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rN8JqtmVY3CeE3L3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rN8JqtmVY3CeE3L3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-rN8JqtmVY3CeE3L3 .icon-shape,#mermaid-svg-rN8JqtmVY3CeE3L3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rN8JqtmVY3CeE3L3 .icon-shape p,#mermaid-svg-rN8JqtmVY3CeE3L3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rN8JqtmVY3CeE3L3 .icon-shape .label rect,#mermaid-svg-rN8JqtmVY3CeE3L3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rN8JqtmVY3CeE3L3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rN8JqtmVY3CeE3L3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rN8JqtmVY3CeE3L3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Mesh 三层安全
Network SecurityNetKey(网络层加密)
Application SecurityAppKey(应用层加密)
Device SecurityDevKey(配网/配置)
Network PDU
Provisioning / Configuration
| Network Security | NetKey | 整个网络的消息 | 所有持有 NetKey 的节点 |
| Application Security | AppKey | 应用数据 | 只有持有对应 AppKey 的节点 |
| Device Security | DevKey | 配网和配置消息 | 设备与 Provisioner |
10.1 为什么需要两层加密
- NetKey 让所有节点都能中继消息(Relay 只需要 NetKey 就能转发,看不到应用数据)。
- AppKey 让不同应用域隔离(照明 AppKey 与传感 AppKey 分开)。
- 一个节点可以持有多个 NetKey 和多个 AppKey。
10.2 防重放机制
| SEQ(Sequence Number) | 每条消息递增,旧 SEQ 被拒绝 |
| IV Index | 网络级计数器,定期更新 |
| Key Refresh | 定期更换 NetKey/AppKey |
| Message Cache | 去重,防止重复处理 |
11. Mesh 模型详解
11.1 模型分类
#mermaid-svg-1tQCFdfwvH7nt9Yq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1tQCFdfwvH7nt9Yq .error-icon{fill:#552222;}#mermaid-svg-1tQCFdfwvH7nt9Yq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1tQCFdfwvH7nt9Yq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .marker.cross{stroke:#333333;}#mermaid-svg-1tQCFdfwvH7nt9Yq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1tQCFdfwvH7nt9Yq p{margin:0;}#mermaid-svg-1tQCFdfwvH7nt9Yq .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster-label text{fill:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster-label span{color:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster-label span p{background-color:transparent;}#mermaid-svg-1tQCFdfwvH7nt9Yq .label text,#mermaid-svg-1tQCFdfwvH7nt9Yq span{fill:#333;color:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .node rect,#mermaid-svg-1tQCFdfwvH7nt9Yq .node circle,#mermaid-svg-1tQCFdfwvH7nt9Yq .node ellipse,#mermaid-svg-1tQCFdfwvH7nt9Yq .node polygon,#mermaid-svg-1tQCFdfwvH7nt9Yq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .rough-node .label text,#mermaid-svg-1tQCFdfwvH7nt9Yq .node .label text,#mermaid-svg-1tQCFdfwvH7nt9Yq .image-shape .label,#mermaid-svg-1tQCFdfwvH7nt9Yq .icon-shape .label{text-anchor:middle;}#mermaid-svg-1tQCFdfwvH7nt9Yq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .rough-node .label,#mermaid-svg-1tQCFdfwvH7nt9Yq .node .label,#mermaid-svg-1tQCFdfwvH7nt9Yq .image-shape .label,#mermaid-svg-1tQCFdfwvH7nt9Yq .icon-shape .label{text-align:center;}#mermaid-svg-1tQCFdfwvH7nt9Yq .node.clickable{cursor:pointer;}#mermaid-svg-1tQCFdfwvH7nt9Yq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .arrowheadPath{fill:#333333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1tQCFdfwvH7nt9Yq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1tQCFdfwvH7nt9Yq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1tQCFdfwvH7nt9Yq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster text{fill:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq .cluster span{color:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1tQCFdfwvH7nt9Yq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1tQCFdfwvH7nt9Yq rect.text{fill:none;stroke-width:0;}#mermaid-svg-1tQCFdfwvH7nt9Yq .icon-shape,#mermaid-svg-1tQCFdfwvH7nt9Yq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1tQCFdfwvH7nt9Yq .icon-shape p,#mermaid-svg-1tQCFdfwvH7nt9Yq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1tQCFdfwvH7nt9Yq .icon-shape .label rect,#mermaid-svg-1tQCFdfwvH7nt9Yq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1tQCFdfwvH7nt9Yq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1tQCFdfwvH7nt9Yq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1tQCFdfwvH7nt9Yq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Mesh Model
Server Model(维护状态)
Client Model(发起请求)
Control Model(组合)
Generic OnOff ServerLight Lightness ServerSensor Server
Generic OnOff ClientLight Lightness ClientSensor Client
11.2 常用标准模型
| Generic OnOff | 开关 | OnOff |
| Generic Level | 电平/亮度 | Level |
| Generic Default Transition Time | 默认过渡时间 | Transition Time |
| Light Lightness | 灯具亮度 | Lightness |
| Light CTL | 色温 | Temperature、Delta UV |
| Light HSL | 色相/饱和度 | Hue、Saturation |
| Sensor | 传感器数据 | Sensor Data |
| Configuration | 网络配置 | 各类配置状态 |
| Health | 故障上报 | Fault |
11.3 模型消息示例:Generic OnOff
| Generic OnOff Get | 0x8201 | Client → Server | 无 |
| Generic OnOff Set | 0x8202 | Client → Server | OnOff, TID, Transition Time, Delay |
| Generic OnOff Set Unacknowledged | 0x8203 | Client → Server | 同上 |
| Generic OnOff Status | 0x8204 | Server → Client | Present OnOff, Target OnOff, Remaining Time |
TID(Transaction Identifier) 用于识别重复消息,避免重复执行。
12. 网络管理与配置
Mesh 网络由 Configuration Server/Client 模型管理,Provisioner 通过它配置节点。
| 添加 AppKey | 给节点分配应用密钥 |
| 绑定 Model 到 AppKey | 决定模型用哪个 AppKey 收发 |
| 设置 Publish 地址 | 模型发布到哪个地址 |
| 添加 Subscription | 模型订阅哪些地址 |
| 设置 Relay | 是否中继、中继次数 |
| 设置 Friend/LPN | 友谊关系 |
| 设置 TTL | 消息默认 TTL |
| 设置 Network Transmit | 网络层重传次数 |
节点
Provisioner
节点
Provisioner
#mermaid-svg-ymM9VVoaaQVUp8Zb{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ymM9VVoaaQVUp8Zb .error-icon{fill:#552222;}#mermaid-svg-ymM9VVoaaQVUp8Zb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ymM9VVoaaQVUp8Zb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ymM9VVoaaQVUp8Zb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ymM9VVoaaQVUp8Zb .marker.cross{stroke:#333333;}#mermaid-svg-ymM9VVoaaQVUp8Zb svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ymM9VVoaaQVUp8Zb p{margin:0;}#mermaid-svg-ymM9VVoaaQVUp8Zb .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ymM9VVoaaQVUp8Zb text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ymM9VVoaaQVUp8Zb .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-ymM9VVoaaQVUp8Zb .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-ymM9VVoaaQVUp8Zb #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-ymM9VVoaaQVUp8Zb .sequenceNumber{fill:white;}#mermaid-svg-ymM9VVoaaQVUp8Zb #sequencenumber{fill:#333;}#mermaid-svg-ymM9VVoaaQVUp8Zb #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-ymM9VVoaaQVUp8Zb .messageText{fill:#333;stroke:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ymM9VVoaaQVUp8Zb .labelText,#mermaid-svg-ymM9VVoaaQVUp8Zb .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .loopText,#mermaid-svg-ymM9VVoaaQVUp8Zb .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ymM9VVoaaQVUp8Zb .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-ymM9VVoaaQVUp8Zb .noteText,#mermaid-svg-ymM9VVoaaQVUp8Zb .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-ymM9VVoaaQVUp8Zb .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ymM9VVoaaQVUp8Zb .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ymM9VVoaaQVUp8Zb .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ymM9VVoaaQVUp8Zb .actorPopupMenu{position:absolute;}#mermaid-svg-ymM9VVoaaQVUp8Zb .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-ymM9VVoaaQVUp8Zb .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ymM9VVoaaQVUp8Zb .actor-man circle,#mermaid-svg-ymM9VVoaaQVUp8Zb line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-ymM9VVoaaQVUp8Zb :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Config AppKey Add
1
Config Model App Bind
2
Config Model Publication Set
3
Config Model Subscription Add
4
Config Relay Set
5
Config Status
6
13. 开发平台与 SDK
| Nordic | nRF Connect SDK (Zephyr) | ✅ 完善 | 生态最好,文档全 |
| Espressif | ESP-IDF BLE Mesh | ✅ | 中文资料多,价格低 |
| Silicon Labs | Gecko SDK | ✅ | 低功耗好 |
| Telink | Telink SDK | ✅ | 灯具市场常用 |
| Android/iOS | 手机 App | 作为 Provisioner | 配网和控制 |
建议组合:Nordic nRF52 开发板 × 3 + nRF Mesh App(手机 Provisioner)+ nRF Sniffer(抓包)。
14. 开发实践:从零搭建 Mesh 网络
14.1 实验目标
搭建一个 3 节点 Mesh 网络:1 个 Provisioner(手机)+ 2 个灯节点,实现组控开关。
#mermaid-svg-UxdAqF6TTQA5loGE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UxdAqF6TTQA5loGE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UxdAqF6TTQA5loGE .error-icon{fill:#552222;}#mermaid-svg-UxdAqF6TTQA5loGE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UxdAqF6TTQA5loGE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UxdAqF6TTQA5loGE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UxdAqF6TTQA5loGE .marker.cross{stroke:#333333;}#mermaid-svg-UxdAqF6TTQA5loGE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UxdAqF6TTQA5loGE p{margin:0;}#mermaid-svg-UxdAqF6TTQA5loGE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-UxdAqF6TTQA5loGE .cluster-label text{fill:#333;}#mermaid-svg-UxdAqF6TTQA5loGE .cluster-label span{color:#333;}#mermaid-svg-UxdAqF6TTQA5loGE .cluster-label span p{background-color:transparent;}#mermaid-svg-UxdAqF6TTQA5loGE .label text,#mermaid-svg-UxdAqF6TTQA5loGE span{fill:#333;color:#333;}#mermaid-svg-UxdAqF6TTQA5loGE .node rect,#mermaid-svg-UxdAqF6TTQA5loGE .node circle,#mermaid-svg-UxdAqF6TTQA5loGE .node ellipse,#mermaid-svg-UxdAqF6TTQA5loGE .node polygon,#mermaid-svg-UxdAqF6TTQA5loGE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UxdAqF6TTQA5loGE .rough-node .label text,#mermaid-svg-UxdAqF6TTQA5loGE .node .label text,#mermaid-svg-UxdAqF6TTQA5loGE .image-shape .label,#mermaid-svg-UxdAqF6TTQA5loGE .icon-shape .label{text-anchor:middle;}#mermaid-svg-UxdAqF6TTQA5loGE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UxdAqF6TTQA5loGE .rough-node .label,#mermaid-svg-UxdAqF6TTQA5loGE .node .label,#mermaid-svg-UxdAqF6TTQA5loGE .image-shape .label,#mermaid-svg-UxdAqF6TTQA5loGE .icon-shape .label{text-align:center;}#mermaid-svg-UxdAqF6TTQA5loGE .node.clickable{cursor:pointer;}#mermaid-svg-UxdAqF6TTQA5loGE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UxdAqF6TTQA5loGE .arrowheadPath{fill:#333333;}#mermaid-svg-UxdAqF6TTQA5loGE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UxdAqF6TTQA5loGE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UxdAqF6TTQA5loGE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UxdAqF6TTQA5loGE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UxdAqF6TTQA5loGE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UxdAqF6TTQA5loGE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UxdAqF6TTQA5loGE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UxdAqF6TTQA5loGE .cluster text{fill:#333;}#mermaid-svg-UxdAqF6TTQA5loGE .cluster span{color:#333;}#mermaid-svg-UxdAqF6TTQA5loGE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UxdAqF6TTQA5loGE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UxdAqF6TTQA5loGE rect.text{fill:none;stroke-width:0;}#mermaid-svg-UxdAqF6TTQA5loGE .icon-shape,#mermaid-svg-UxdAqF6TTQA5loGE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UxdAqF6TTQA5loGE .icon-shape p,#mermaid-svg-UxdAqF6TTQA5loGE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UxdAqF6TTQA5loGE .icon-shape .label rect,#mermaid-svg-UxdAqF6TTQA5loGE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UxdAqF6TTQA5loGE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UxdAqF6TTQA5loGE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UxdAqF6TTQA5loGE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
发布到 0xC001
手机nRF Mesh App(Provisioner)
Node 1Generic OnOff Server
Node 2Generic OnOff Server
Group 0xC001
14.2 开发步骤
| 1 | 编译并烧录 Mesh 灯示例(Nordic light_switch) | 串口打印未配网 Beacon |
| 2 | 手机打开 nRF Mesh App,扫描未配网设备 | 能看到两个设备 |
| 3 | 逐个配网,分配单播地址 | 设备加入网络 |
| 4 | 添加 AppKey 并绑定到 OnOff Server | 配置成功 |
| 5 | 创建组地址 0xC001 | 组地址存在 |
| 6 | 两个节点订阅 0xC001 | 订阅成功 |
| 7 | 手机发布 OnOff Set 到 0xC001 | 两个灯同时亮/灭 |
| 8 | 用 Sniffer 抓包 | 看到 Network PDU 和泛洪 |
14.3 代码示意(Nordic/Zephyr 风格)
// 定义 Generic OnOff Server 模型
static struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV(&cfg_srv), // Configuration Server
BT_MESH_MODEL_GEN_ONOFF_SRV(&onoff_srv), // Generic OnOff Server
};
// 元素定义
static struct bt_mesh_elem elements[] = {
BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE),
};
// 初始化 Mesh
static const struct bt_mesh_comp comp = {
.cid = BT_COMP_ID_LF,
.elem = elements,
.elem_count = ARRAY_SIZE(elements),
};
bt_mesh_init(&prov, &comp);
14.4 配网关键参数
| Unicast Address | 每个 Element 分配一个 |
| NetKey | 网络密钥,所有节点共享 |
| AppKey | 应用密钥,绑定到 Model |
| IV Index | 网络级计数器 |
| Device Key | 配网时生成,用于配置 |
15. 性能与规模考量
| 单跳延迟 | 10–50 ms | 广播间隔、处理时间 |
| 多跳延迟 | 每跳增加 10–50 ms | 跳数、Relay 密度 |
| 网络规模 | 几十到几百节点 | 泛洪拥塞、Relay 数量 |
| 消息负载 | 小(几字节到十几字节) | 不适合大文件 |
| 吞吐 | 低(Kbps 级) | 广播承载限制 |
| 功耗 | LPN 可 μA 级 | Friend 缓存 + 轮询间隔 |
规模优化建议:
- 控制 Relay 节点比例(约 10–20%)
- 使用组地址而非广播地址
- 合理设置 TTL(通常 5–7)
- 降低发布频率
- 分区组网(多个 NetKey)
16. 常见问题与排障
| 设备无法配网 | Beacon 未广播/距离远 | 看串口、靠近重试 |
| 配网成功但控制不了 | AppKey 未绑定/未订阅 | 检查 Model 绑定和订阅 |
| 组控只亮一个 | 另一个未订阅组地址 | 检查 Subscription List |
| 消息延迟大 | 跳数多/Relay 少 | 增加 Relay、减少跳数 |
| 网络拥塞 | 发布频率高/广播地址 | 降频、用组地址 |
| LPN 收不到消息 | Friend 未建立/轮询间隔长 | 检查 Friendship、Poll Timeout |
| 抓包看不到 Mesh 消息 | 过滤条件错 | 过滤 btmesh 或 AD Type 0x2A |
| 重放攻击告警 | SEQ/IV Index 不同步 | 检查 Key Refresh、IV Update |
Wireshark 常用过滤:
| btmesh | 所有 Mesh 消息 |
| btmesh.network | 网络层 |
| btmesh.transport | 传输层 |
| btmesh.access | 访问层 |
| btmesh.provisioning | 配网流程 |
17. 学习检查点
- 能解释 Mesh 为什么用泛洪而不是路由
- 能画出 Mesh 七层协议栈并说出每层职责
- 能区分 Node、Element、Model、State
- 能说出五种节点角色及 Friend/LPN 的配合流程
- 能解释三种地址类型和发布/订阅模型
- 能说清 NetKey、AppKey、DevKey 的区别
- 能描述配网流程和认证方式
- 能搭建 3 节点网络并实现组控
- 能用 Wireshark 抓 Mesh 消息并定位问题
18. 动手实验
| 烧录 Mesh 灯示例 | nRF52 × 2 | 熟悉 SDK |
| 手机配网两个节点 | nRF Mesh App | 理解 Provisioning |
| 创建组地址并订阅 | nRF Mesh App | 理解发布/订阅 |
| 组控开关 | 手机 + 两个灯 | 验证组播 |
| 抓包分析 Network PDU | Sniffer + Wireshark | 看到 NetKey 加密 |
| 配置 Relay 并观察泛洪 | 3 个节点 | 理解 TTL 和中继 |
| 配置 LPN + Friend | 电池节点 + 常供电节点 | 理解低功耗机制 |
| 修改 AppKey 并观察 | nRF Mesh App | 理解应用层隔离 |
推荐实验顺序
#mermaid-svg-IF1IKIhx1YBIT8qr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IF1IKIhx1YBIT8qr .error-icon{fill:#552222;}#mermaid-svg-IF1IKIhx1YBIT8qr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IF1IKIhx1YBIT8qr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IF1IKIhx1YBIT8qr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IF1IKIhx1YBIT8qr .marker.cross{stroke:#333333;}#mermaid-svg-IF1IKIhx1YBIT8qr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IF1IKIhx1YBIT8qr p{margin:0;}#mermaid-svg-IF1IKIhx1YBIT8qr .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster-label text{fill:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster-label span{color:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster-label span p{background-color:transparent;}#mermaid-svg-IF1IKIhx1YBIT8qr .label text,#mermaid-svg-IF1IKIhx1YBIT8qr span{fill:#333;color:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr .node rect,#mermaid-svg-IF1IKIhx1YBIT8qr .node circle,#mermaid-svg-IF1IKIhx1YBIT8qr .node ellipse,#mermaid-svg-IF1IKIhx1YBIT8qr .node polygon,#mermaid-svg-IF1IKIhx1YBIT8qr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IF1IKIhx1YBIT8qr .rough-node .label text,#mermaid-svg-IF1IKIhx1YBIT8qr .node .label text,#mermaid-svg-IF1IKIhx1YBIT8qr .image-shape .label,#mermaid-svg-IF1IKIhx1YBIT8qr .icon-shape .label{text-anchor:middle;}#mermaid-svg-IF1IKIhx1YBIT8qr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IF1IKIhx1YBIT8qr .rough-node .label,#mermaid-svg-IF1IKIhx1YBIT8qr .node .label,#mermaid-svg-IF1IKIhx1YBIT8qr .image-shape .label,#mermaid-svg-IF1IKIhx1YBIT8qr .icon-shape .label{text-align:center;}#mermaid-svg-IF1IKIhx1YBIT8qr .node.clickable{cursor:pointer;}#mermaid-svg-IF1IKIhx1YBIT8qr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IF1IKIhx1YBIT8qr .arrowheadPath{fill:#333333;}#mermaid-svg-IF1IKIhx1YBIT8qr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IF1IKIhx1YBIT8qr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IF1IKIhx1YBIT8qr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IF1IKIhx1YBIT8qr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IF1IKIhx1YBIT8qr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IF1IKIhx1YBIT8qr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster text{fill:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr .cluster span{color:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IF1IKIhx1YBIT8qr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IF1IKIhx1YBIT8qr rect.text{fill:none;stroke-width:0;}#mermaid-svg-IF1IKIhx1YBIT8qr .icon-shape,#mermaid-svg-IF1IKIhx1YBIT8qr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IF1IKIhx1YBIT8qr .icon-shape p,#mermaid-svg-IF1IKIhx1YBIT8qr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IF1IKIhx1YBIT8qr .icon-shape .label rect,#mermaid-svg-IF1IKIhx1YBIT8qr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IF1IKIhx1YBIT8qr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IF1IKIhx1YBIT8qr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IF1IKIhx1YBIT8qr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
实验 1烧录示例
实验 2配网
实验 3组地址订阅
实验 4组控
实验 5抓包
实验 6Relay 泛洪
实验 7LPN/Friend
实验 8AppKey 隔离
19. 面试与工程高频问题
| Mesh 和传统 BLE 有什么区别? | 广播承载、多跳泛洪、发布/订阅、三层安全 |
| 为什么用 Managed Flooding 而不是路由? | 实现简单、无路由表维护、适合小控制消息 |
| NetKey 和 AppKey 的区别? | NetKey 网络层加密/中继,AppKey 应用数据隔离 |
| Relay 和 Proxy 的区别? | Relay 转发 Mesh 消息,Proxy 让 GATT 设备接入 |
| Friend 和 LPN 如何配合? | Friend 缓存,LPN 轮询取消息,实现低功耗 |
| 配网流程有哪些阶段? | Beacon → Invite → 公钥交换 → 认证 → 分发数据 |
| TTL 的作用? | 限制跳数,防止无限泛洪 |
| SEQ 和 IV Index 的作用? | 防重放、去重 |
| 如何控制网络规模? | 限制 Relay 比例、用组地址、降频、分区 |
| Mesh 适合传大数据吗? | 不适合,适合小控制消息 |
| 抓包为什么看不到应用数据? | 被 AppKey 加密,需要密钥才能解密 |
| 组控不生效怎么排查? | 检查订阅、AppKey 绑定、发布地址 |
总结
BLE Mesh 的本质:在 BLE 广播之上,用泛洪 + 发布/订阅 + 三层密钥,解决大规模、多跳、低功耗的组网问题。
学习路径建议:
最容易卡住的三个点:Model 绑定与订阅配置、Friend/LPN 友谊建立、抓包时看不到应用层数据(因为被加密)。
