1. 蓝牙Mesh网络基础:Mesh网络拓扑、节点与中继、发布/订阅模型

各位同学,咱们正式开始这门课。第一讲,先把地基打牢。

蓝牙Mesh,说白了,它不是传统蓝牙那种「一对一」或者「一对多」的广播模式。它是一种多对多的网络。你想想看,一个智能灯泡要跟一百个开关通信,用经典蓝牙得累死。Mesh就是来解决这个问题的。

1.1 Mesh网络拓扑:不是星型,是网型

传统蓝牙是星型拓扑,一个中心节点连一堆外围设备。中心挂了,全完蛋。Mesh不一样,它是网型拓扑。

每个节点都可以跟周围的节点通信。消息像水一样,从源头扩散出去。没有单点故障,可靠性高很多。

我记得刚接触Mesh时,有个误区:以为所有节点都必须互相可见。其实不是。Mesh只要求相邻节点能通信就行。距离远的,靠中间节点接力传过去。

核心要点:Mesh网络没有中心节点。每个节点既是终端,也是潜在的转发者。这种结构天然支持大规模设备组网。

我画了一张图,帮你直观理解Mesh拓扑和传统星型拓扑的区别:

蓝牙Mesh网型拓扑 vs 传统星型拓扑 星型拓扑(传统蓝牙) 中心 节点1 节点2 节点3 Mesh网型拓扑 节点A 节点B 节点C 节点D 节点E 中继 说明:Mesh中每个节点可连接多个邻居,消息通过中继节点逐跳转发,覆盖范围远超星型拓扑

1.2 节点与中继:谁在干活?

Mesh网络里,节点不是平等的。它们有不同的角色。我个人习惯把节点分成四类:

节点类型 功能描述 典型场景
中继节点 接收并转发消息,扩展网络覆盖范围 吸顶灯、中继器
低功耗节点 不参与中继,定期休眠省电 传感器、门磁
朋友节点 为低功耗节点缓存消息 网关、常供电设备
代理节点 让非Mesh设备(如手机)通过GATT接入Mesh 手机、平板

这里有个坑,我踩过。有一次项目里,我把所有节点都配成了中继节点。结果网络里消息满天飞,大量重复转发,功耗也上去了。

避坑指南:不是所有节点都需要当中继。中继节点越多,网络冗余越好,但消息洪泛也越严重。我建议:中继节点占比控制在30%-50%,其余节点设为低功耗或普通节点。

中继的工作原理其实很简单。当一个节点收到消息,它会检查:

  1. 这条消息我有没有转发过?(防止环路)
  2. 消息的TTL(生存时间)还有没有剩余?
  3. 这条消息是不是发给我的订阅组?

如果都满足,它就转发出去。TTL减1。TTL到0,消息就丢弃。

1.3 发布/订阅模型:消息怎么传?

这是Mesh最巧妙的设计之一。它不是点对点发消息,而是用发布/订阅模型。

每个节点可以订阅一个或多个组地址。节点也可以向某个组地址发布消息。所有订阅了这个组的节点,都会收到消息。

你想想看,这多方便。一个开关发布「开灯」消息到组地址0xC001。所有订阅了0xC001的灯泡,同时亮起。不需要知道灯泡的具体地址。

个人经验:我在做智能家居项目时,把客厅所有灯都订阅到同一个组地址。一个面板开关控制整个客厅。后来客户要分区控制,我只需要把灯分配到不同的组,开关也对应不同的组。改配置就行,不用动硬件。

发布/订阅模型的核心元素有三个:

  • 发布者:发送消息的节点。比如开关、传感器。
  • 订阅者:接收消息的节点。比如灯泡、执行器。
  • 组地址:消息的「频道」。发布者和订阅者通过组地址关联。

组地址有三种类型:

地址类型 范围 用途
固定组地址 0x0000 - 0x00FF 系统保留,如所有节点、所有中继节点
动态组地址 0xC000 - 0xFFFF 用户自定义,如「客厅灯组」、「卧室灯组」
虚拟组地址 基于UUID 临时或动态场景,如「日落模式」

嗯,这里要注意。发布/订阅模型跟传统蓝牙的GATT通知完全是两码事。GATT是中心-外设模型,Mesh是去中心化的。后面章节我会详细讲怎么用GATT服务把手机接入Mesh,那就是代理节点的活儿了。

最后,我用一张流程图总结一下消息在Mesh网络中的完整旅程:

蓝牙Mesh消息发布/订阅流程 发布者(开关) 组地址 0xC001 订阅者(灯泡1) 订阅者(灯泡2) 中继节点(转发) 订阅者(灯泡3) 说明:发布者向组地址发送消息,所有订阅该组的节点(包括通过中继转发的节点)都能收到 中继节点负责将消息转发到更远的区域,扩展网络覆盖

好了,这一章的基础概念就这些。Mesh的拓扑、节点角色、发布/订阅模型,是后面所有内容的地基。你把这些搞清楚了,后面讲GATT代理、讲模型绑定,你才不会晕。