主题
5.3 设备接入流程
任何支持 MQTT 3.1 / 3.1.1 的设备或程序都能接入,不限品牌和语言。整个流程只有三步:连接、发布、(可选)订阅。
5.3.1 第一步:连接参数
| 参数 | 值 | 说明 |
|---|---|---|
| Broker 地址 | 服务器 IP 或域名 | |
| 端口 | 1883 | 唯一的 MQTT 端口,不支持 TLS,没有 8883 |
| 用户名 | 云平台账号 | 主账号或子账号都可以 |
| 密码 | 对应密码 | |
| Client ID | 设备唯一标识 | 每台设备必须不同,重复会互相挤断连接 |
| 协议版本 | 3.1.1(推荐)或 3.1 | 不支持 MQTT 5.0 |
用户名决定数据落到哪个账号的实时数据库里。子账号登录时会绑定到其所属主账号,数据和主账号共用一个库。
给每台设备开独立子账号
虽然所有设备共用一个账号也能跑,但建议在云平台给每台设备开一个子账号。这样掉线排查、权限收回都有依据,也避免改一次密码所有设备一起掉线。
5.3.2 第二步:发布数据
主题名就是数据点名,payload 直接放值:
topic: 车间1/1号机/温度
payload: 25.6发布成功后,云平台「数据管理 → 实时数据库」里立刻就能看到名为 车间1/1号机/温度 的数据点。不需要提前在服务器上创建数据点,第一次上报时自动创建。
一次上报多个值用 JSON 对象:
topic: 车间1/1号机
payload: {"温度":25.6,"湿度":60,"运行":1}
得到三个数据点: 车间1/1号机/温度、车间1/1号机/湿度、车间1/1号机/运行完整的 payload 映射规则见 5.5 消息格式规范,接入前应先阅读,否则容易上报出多余的数据点。
5.3.3 第三步:订阅下发(需要远程控制时)
要接收云端下发的指令,订阅对应主题即可:
subscribe: 车间1/1号机/启停云端(云组态点按钮、事件触发、HTTP API)修改这个数据点时,服务器会把新值推到该主题,默认 payload 为 {"value":新值}。
5.3.4 QoS 怎么选
| QoS | 落库时机 | 建议 |
|---|---|---|
| 0 | 消息到达即写库 | 高频遥测量,允许偶尔丢一帧 |
| 1 | 消息到达即写库,服务器回 PUBACK | 默认推荐,可靠且开销可控 |
| 2 | 收到 PUBREL 后才写库 | 只在绝对不能重复的场景用,往返多、延迟高 |
不要用 QoS2 上报高频数据
QoS2 要四次握手,且要等 PUBREL 才落库。另外服务器对单个客户端的待发消息有上限(超过 100 条会做丢弃处理),高频 + QoS2 很容易堆积。
5.3.5 在线状态
设备连上后,服务器会自动写一个在线状态点:
server/online/MQTT/<ClientID> 1 = 在线,0 = 离线这个点可以直接在云组态里绑定显示,也可以配置事件触发做离线报警,不需要设备自行上报心跳。
5.3.6 先用命令行验证通路
接入前先用工具确认通路,避免和设备代码的问题混在一起:
bash
# 上报一个值
mosquitto_pub -h 服务器IP -p 1883 -u 账号 -P 密码 -i test_dev_01 \
-t "测试/温度" -m "25.6" -q 1
# 订阅看下发
mosquitto_sub -h 服务器IP -p 1883 -u 账号 -P 密码 -i test_dev_02 \
-t "测试/启停" -q 1发完立刻去实时数据库页搜 测试/温度,能看到值就说明通路没问题。
5.3.7 自检清单
- [ ] 服务器 MQTT 服务已启动,端口 1883 在监听
- [ ] 防火墙已放行 TCP 1883(详见 2.2 端口与防火墙配置)
- [ ] 云平台已创建账号(建议每设备一个子账号)
- [ ] 每台设备的 Client ID 唯一
- [ ] 客户端没有开 TLS,协议版本不是 5.0
- [ ] payload 用裸值或按 5.5 的规则组织,请勿直接套用其它平台的
{value,timestamp,quality} - [ ] 已确认实时数据库里出现了对应数据点
5.3.8 接不上的排查顺序
| 现象 | 原因 |
|---|---|
| 连接被拒绝 / 立刻断开 | 账号密码错;或客户端开了 TLS;或协议版本选了 5.0 |
| 连上但反复掉线 | 多台设备用了同一个 Client ID,互相挤断连接 |
| 连上了但实时数据库没有点 | 主题名为空;或 payload 是 JSON 数组等非对象结构且主题也为空 |
| 数据点名多了一堆后缀 | payload 用了多字段 JSON,见 5.5 规则三 |
| 值一直是旧的 | 客户端 publish 失败但代码没检查返回值;先用 mosquitto_pub 验证通路 |