3. MQTT协议基础:发布/订阅模型、主题(Topic)、服务质量(QoS)
好,咱们进入正题。这一章是MQTT的核心,也是你在储能监控里用得最多的东西。说白了,MQTT就是个“传话”的协议,但它传话的方式很特别——不是点对点,而是通过一个中间人。
3.1 发布/订阅模型:不是“你找我”,而是“我等你”
传统的HTTP通信,就像你打电话给朋友:“喂,给我查一下电池电压。”朋友查完告诉你。这叫请求/响应模式。但在储能系统里,设备数量动不动就成百上千,每个设备都主动去问,服务器早崩了。
MQTT用的是另一种模式:发布/订阅。我习惯把它比作“电台广播”。
- 发布者(Publisher):只管往外发消息,不管谁在听。比如BMS(电池管理系统)每隔1秒发一次电压数据。
- 订阅者(Subscriber):只管接收自己感兴趣的消息。比如监控大屏只订阅“电压”主题,不关心“温度”。
- 代理(Broker):中间人,负责接收发布者的消息,再转发给所有订阅者。
你看,发布者和订阅者完全解耦。它们不需要知道对方的存在,甚至不需要同时在线。我在一个光伏储能项目里就遇到过这种情况:现场网络不稳定,BMS偶尔掉线。但用MQTT,BMS上线后把数据一推,Broker自动缓存,订阅者该收还是能收到。这要是用HTTP,掉线期间的数据全丢了。
核心优势:发布/订阅模型天然支持一对多通信,非常适合储能系统中“一个数据源,多个消费端”的场景。
下面这张图,是我手绘的MQTT通信流程,你看一眼就明白了。
3.2 主题(Topic):消息的“门牌号”
有了发布/订阅模型,消息怎么分类?靠的就是主题(Topic)。你可以把主题想象成快递上的地址,Broker根据这个地址把消息送到对应的订阅者手里。
主题的格式是分层的,用斜杠“/”分隔。比如在储能系统里,我常用的主题结构是这样的:
储能电站ID/设备类型/设备ID/数据点
示例:sz_station_01/bms/bms_001/voltage
sz_station_01/bms/bms_001/temperature
sz_station_01/pcs/pcs_001/power
为什么要分层?因为MQTT支持通配符订阅,这在实际项目中太有用了。
- 单级通配符“+”:匹配一层。比如订阅
sz_station_01/+/bms_001/voltage,就能收到所有设备类型下bms_001的电压数据。 - 多级通配符“#”:匹配剩余所有层。比如订阅
sz_station_01/#,就能收到这个电站的所有数据。
我的经验:主题设计一定要提前规划好。我曾经在一个项目中,因为主题层级太浅(比如直接用“data/voltage”),导致后期设备多了,订阅过滤非常困难。建议至少包含“站点/设备类型/设备ID/数据点”这四层。
另外,主题名不要用中文,也不要用特殊字符。Broker对UTF-8支持没问题,但客户端库不一定。我见过有人用中文主题,结果某个嵌入式设备解析不了,数据全丢了。老老实实用英文加下划线。
3.3 服务质量(QoS):消息能丢吗?
储能系统里,有些数据丢了无所谓,比如环境温度,5秒一次,丢一两次不影响。但有些数据绝对不能丢,比如保护动作信号、告警信息。MQTT用QoS来解决这个问题。
QoS有三个等级,我一个个说。
| QoS等级 | 含义 | 可靠性 | 适用场景 |
|---|---|---|---|
| 0 | 最多发一次 | 最低,可能丢 | 遥测数据(电压、电流、温度) |
| 1 | 至少发一次 | 中等,可能重复 | 状态变更(设备启停、模式切换) |
| 2 | 恰好发一次 | 最高,不丢不重 | 告警、保护动作、控制指令 |
QoS 0:说白了就是“发完拉倒”。Broker收到消息后直接转发,不确认,不存储。性能最高,但可能丢消息。我在项目中,像电池电压、SOC这种高频数据,都用QoS 0。丢了就丢了,下一秒还有。
QoS 1:保证消息至少到达一次。Broker收到后会回复一个PUBACK确认包。如果发布者没收到确认,会重发。但这就可能导致订阅者收到重复消息。嗯,这里要注意:你的业务逻辑必须能处理重复数据。比如设备状态变更,如果重复收到“开机”指令,设备会不会重复执行?
避坑指南:我曾经在一个储能项目中,用QoS 1下发“停止充电”指令。结果因为网络抖动,指令重复发了两次,BMS执行了两次停止操作,导致充电桩报错。后来我改成QoS 2,并在应用层加了去重逻辑,才彻底解决。
QoS 2:最严格,保证消息恰好到达一次。它用了四次握手协议(PUBLISH → PUBREC → PUBREL → PUBCOMP),开销最大,速度最慢。但像“电池过温保护”、“断路器跳闸”这种关键指令,必须用QoS 2。命只有一条,不能丢,也不能重。
你可能会问:那所有消息都用QoS 2不就行了?不行。你想想看,一个储能电站每秒可能有上千条遥测数据,如果都用QoS 2,Broker的CPU和内存直接拉满,延迟飙升。所以我的原则是:按数据价值分配QoS。
3.4 实际项目中的QoS选择策略
我整理了一份储能监控中常见数据的QoS配置表,供你参考。
| 数据类型 | 推荐QoS | 理由 |
|---|---|---|
| 遥测数据(电压、电流、温度) | 0 | 高频、可丢失、有冗余 |
| 状态数据(设备启停、模式) | 1 | 低频、需可靠、可容忍重复 |
| 告警数据(过压、过温、绝缘故障) | 2 | 关键、不可丢、不可重复 |
| 控制指令(充电、放电、停机) | 2 | 关键、需确认、需幂等 |
| 日志/事件记录 | 1 | 重要但允许少量重复 |
最后说一句:QoS是MQTT协议层面的保证,但应用层最好也做一层校验。比如每条消息带一个唯一ID,订阅者收到后检查ID是否重复。这叫“双重保险”。我在实际项目中就是这么干的,效果很好。
总结一下:发布/订阅模型解耦了生产者和消费者;主题用分层结构组织消息;QoS根据数据重要性选择。这三样东西,是你在储能监控里用好MQTT的基础。下一章咱们聊MQTT的会话和遗嘱机制,那才是真正让系统“健壮”的关键。