为什么自建 MQTT Broker
PipeMonitor 的 STM32 设备通过 DTU(4G 透传模块)上云,DTU 将串口数据透明转发到指定的 MQTT Broker。自建 Mosquitto 而不是使用公有云 IoT 平台,原因很简单:
- DTU 只支持标准 MQTT:大部分 4G DTU 不支持阿里云/AWS IoT 的专有认证协议(如三元组、X.509 证书),只能连标准 MQTT Broker
- 控制链路简单:下行命令直接 publish 到对应 topic,设备 DTU 订阅后透传到串口,不需要额外的 RPC 通道
- 自主可控:数据不经过第三方平台,端到端都在自己的 VPS 上
Mosquitto 配置
# Pipe Monitor 独立 broker:公网 1883 明文入口,仍强制账号密码和 ACL。
listener 1883 0.0.0.0
allow_anonymous false
password_file /mosquitto/config/passwordfile
acl_file /mosquitto/config/aclfile
persistence true
persistence_location /mosquitto/data/
log_dest stdout
log_type error
log_type warning
log_type notice
log_type information
关注几个要点:
- 公网 1883 明文:DTU 设备通常不支持 TLS,所以用明文端口。安全性通过账号密码 + ACL 来保证,不依赖传输层加密
- 禁止匿名:
allow_anonymous false,所有连接必须提供用户名密码 - 持久化:开启 session 持久化,设备断线重连后能恢复订阅
Topic 设计
device/<deviceId>/up # 设备上行:tele / alarm / ack
device/<deviceId>/down # 云端下行:cmd JSON
up:设备通过 DTU 透传上来的 JSON 帧,每条以\n结尾。包含三种帧类型:tele(遥测)、alarm(告警)、ack(命令确认)down:云端下发的一行cmdJSON,设备收到后执行并回复 ack
这种设计的好处是:
- 一个设备两个 topic,上行和下行完全隔离
- 设备 ID 在 topic 路径中,ACL 可以精确控制每个设备的读写权限
- 多设备时只需增加
device/<deviceId>/*的通配规则
ACL 权限控制
ACL 文件定义了每个用户可以读写的 topic 范围:
# 设备用户:只能读写自己的 topic
user FM001
topic read device/FM001/down
topic write device/FM001/up
# API 服务用户:可以读写所有设备
user pipe-monitor-api
topic read device/+/up
topic write device/+/down
- 设备用户:只能订阅自己的
downtopic 和发布到自己的uptopic,无法访问其他设备的数据 - API 服务用户:使用 MQTT 通配符
+,可以接收所有设备的上行消息,也可以向任意设备下发命令
上行消息格式
设备通过 DTU 透传的 JSON 帧,每条以 \n 结尾。API 服务的 MQTT 客户端收到消息后按行分割,逐条解析:
{"t":"tele","ts":1712345678,"seq":123,"dev":"FM001","flow":12.3,...}
{"t":"alarm","ts":1712345679,"seq":124,"dev":"FM001","code":"OVER_FLOW",...}
{"t":"ack","ts":1712345680,"seq":125,"dev":"FM001","cmd_seq":42,...}
以 \n 分隔的好处是 DTU 透传时天然支持——串口数据本身就是按行发送的,不需要额外的帧定界协议。
下行命令格式
云端下发命令也是一行 JSON:
{"t":"cmd","seq":42,"cmd":"reboot"}
{"t":"cmd","seq":43,"cmd":"set_upload_period","seconds":10}
设备端的 uplink_decoder 手写极简 JSON 解析器提取 cmd 和 seq,执行后回复 ack。
安全性考量
- 密码文件通过 Docker volume 挂载,不入镜像
- ACL 文件按用户精确控制 topic 读写权限
- 设备用户和 API 用户使用不同的认证凭证
- API 密钥通过 Docker 环境变量注入,不在代码中硬编码
小结
- 自建 Mosquitto 适配标准 MQTT DTU,不依赖公有云 IoT 平台
- 双 topic 设计(up/down)隔离上下行通道
- ACL 按设备精确控制权限,设备之间数据隔离
- JSON 行分隔格式与 DTU 串口透传天然兼容
- 密码和密钥通过环境变量/volume 注入,不入镜像