为什么自建 MQTT Broker

PipeMonitor 的 STM32 设备通过 DTU(4G 透传模块)上云,DTU 将串口数据透明转发到指定的 MQTT Broker。自建 Mosquitto 而不是使用公有云 IoT 平台,原因很简单:

  1. DTU 只支持标准 MQTT:大部分 4G DTU 不支持阿里云/AWS IoT 的专有认证协议(如三元组、X.509 证书),只能连标准 MQTT Broker
  2. 控制链路简单:下行命令直接 publish 到对应 topic,设备 DTU 订阅后透传到串口,不需要额外的 RPC 通道
  3. 自主可控:数据不经过第三方平台,端到端都在自己的 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:云端下发的一行 cmd JSON,设备收到后执行并回复 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
  • 设备用户:只能订阅自己的 down topic 和发布到自己的 up topic,无法访问其他设备的数据
  • 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 解析器提取 cmdseq,执行后回复 ack。

安全性考量

  • 密码文件通过 Docker volume 挂载,不入镜像
  • ACL 文件按用户精确控制 topic 读写权限
  • 设备用户和 API 用户使用不同的认证凭证
  • API 密钥通过 Docker 环境变量注入,不在代码中硬编码

小结

  • 自建 Mosquitto 适配标准 MQTT DTU,不依赖公有云 IoT 平台
  • 双 topic 设计(up/down)隔离上下行通道
  • ACL 按设备精确控制权限,设备之间数据隔离
  • JSON 行分隔格式与 DTU 串口透传天然兼容
  • 密码和密钥通过环境变量/volume 注入,不入镜像

后续阅读