欢迎光临
我们一直在努力

低功耗蓝牙 Mesh 详解:架构、协议栈、安全与开发实践

低功耗蓝牙 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(传感器)。这种模型在消费电子里很成功,但在楼宇照明、工业传感、资产追踪等场景下会遇到明显瓶颈:

场景需求传统 BLE 的局限
几百个灯要统一控制 一个 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 拓扑的对比

维度传统 BLE(GAP/GATT)BLE Mesh
拓扑 点对点 / 星形 多跳 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

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

消息Opcode方向参数
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

平台SDKMesh 支持特点
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 广播之上,用泛洪 + 发布/订阅 + 三层密钥,解决大规模、多跳、低功耗的组网问题。

学习路径建议:

  • 先理解节点/元素/模型/状态四层结构
  • 再理解七层协议栈和消息封装
  • 然后动手配网 + 组控
  • 最后用抓包验证 NetKey/AppKey 加密和泛洪
  • 最容易卡住的三个点:Model 绑定与订阅配置、Friend/LPN 友谊建立、抓包时看不到应用层数据(因为被加密)。


    赞(0)
    未经允许不得转载:171主机测评 » 低功耗蓝牙 Mesh 详解:架构、协议栈、安全与开发实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址