主题
5.6 设备之间互相发布订阅
除了「设备上报、云端查看」,内置 Broker 也可以当设备之间的消息中转用:A 设备 publish,B 设备 subscribe,不需要经过任何业务代码。
5.6.1 服务器同时做两件事
一条 publish 消息到达后,服务器会并行做两件互不影响的事:
这意味着:
- 设备间通信顺带就有了云端可视化,不用额外上报一遍
- 反之,只做设备间互传而不写入数据点列表目前不支持,落库是无条件的。这种场景建议用
$开头的主题(仍会落库,但不参与通配符匹配),或约定统一前缀便于筛选
5.6.2 隔离范围
| 层级 | 是否隔离 | 说明 |
|---|---|---|
| 不同主账号之间 | 完全隔离 | 各自独立的数据库,互相订阅不到,主题重名也不冲突 |
| 同主账号下不同项目 | 隔离 | 转发和订阅都带项目范围,不同项目的同名主题互不干扰 |
| 同主账号下的子账号之间 | 不隔离 | 子账号共用主账号的库,可以互相收发 |
所以:
- 要让两台设备互通,它们必须登录同一个主账号(用各自的子账号也行),且属于同一个项目
- 要让两个客户的设备彻底隔开,必须用不同的主账号,不能只靠子账号
子账号之间没有主题权限隔离
同一主账号下的任意子账号,都能订阅到该账号下所有主题的数据。若项目中不同子账号代表不同的最终客户,不要依赖 MQTT 层做数据隔离,应给每个客户开独立主账号。
5.6.3 retain(保留消息)
publish 时带 retain=1,服务器会把这条消息存下来。之后任何新订阅该主题的客户端,连上的瞬间立刻收到最后一条保留消息,不用等下一次上报。
用途:
- 设备刚上线就需要知道当前设定值,而设定值可能几天才变一次
- 上位机/网关重启后需要快速恢复现场画面
服务器把实时数据库的变化推到 MQTT 侧时,默认就是 QoS0 + retain,所以订阅设定值类主题的设备重连后能立刻拿到最新值。
5.6.4 通配符
| 通配符 | 含义 | 限制 |
|---|---|---|
+ | 单层匹配 | 可以出现在任意层,如 车间1/+/温度 |
# | 多层匹配 | 只能放在末尾,如 车间1/# |
$ 开头的主题被视为系统主题,不参与通配符匹配。用 # 订阅全部也收不到它们。
5.6.5 典型用法
一台设备的数据给多台屏/网关用
PLC A publish 产线1/产量 (落库 + 转发)
触摸屏 B subscribe 产线1/产量
边缘网关 C subscribe 产线1/#
云组态 项目变量 产线1/产量一次上报,三个消费者都拿到,云端还自动留了历史。
设备间联动(不经过云端逻辑)
称重仪 A publish 包装线/重量超标 1
分拣机 B subscribe 包装线/重量超标 → 收到 1 立刻动作比「设备 → 云端事件触发 → 下发设备」少一次往返,延迟更低。缺点是断网时联动直接失效,安全相关的互锁不要放在这里,应该做在 PLC 梯形图里。
5.6.6 客户端 ID 与消息堆积
- Client ID 必须全局唯一。重复登录会挤断前一个连接,两台设备用同一个 ID 会表现为「双方都在反复掉线重连」
- 服务器对单个客户端的待发消息有上限(超过 100 条会做丢弃处理)。订阅方处理慢、或用了
#订阅高频主题时容易触发,表现为收到的消息不连续 - 高频主题不要用
#大范围订阅,按需订阅具体主题
5.6.7 QoS 与落库时机的关系
| QoS | 转发行为 | 落库时机 |
|---|---|---|
| 0 | 立即转发,不确认 | 到达即写 |
| 1 | 转发 + 回 PUBACK | 到达即写 |
| 2 | 走完 PUBREC / PUBREL 四次握手 | 收到 PUBREL 后才写 |
QoS2 下数据点的更新会比 QoS0/1 晚一个往返,对时效敏感的量不要用 QoS2。