主题
1.3 MQTT
「MQTT」子标签把寄存器的值按 JSON 模板上报到 MQTT Broker,同时可以订阅平台下发的命令把收到的 JSON 按字段映射到目标寄存器。全程不需要写一行 Lua,平台是 EMQX / Mosquitto / 阿里云 IoT / 华为云 IoT / ThingsBoard / 自建 Broker 都行。
机型支持:ESP32-S3 已放开
MQTT 是配置式 DTU 第一期的两个新标签之一,第一期放出 LP6666 软 PLC 模拟器,2026 年 9 月二期已放开 ESP32-S3 机型(LP3232 / LP3288);普通 ESP32 机型后续放开。 看不到这个标签说明当前固件还没编进 MQTT 模块,对照 支持哪些设备与能力。老固件「配了不生效也不报错」的说明也写在那张表下面。
这一页在做什么
MQTT 是长连接:上行和下行中间隔着一条保持着的连接。下行通过订阅一帧 JSON 落寄存器实现,上行通过定时器按 JSON 模板发到平台。这就是这一页两个分组:
- 上行组(设备 → 平台):把寄存器的当前值渲染成 JSON 定时发布出去
- 下行组(平台 → 设备):订阅一个 topic,收到一帧 JSON 就按点位表把字段值落到寄存器
一条连接把这两组连起来:上线成功后上行照常发、下行照常收,链路中断后自动重连。连接是否处于活动状态,写到 link_flag 指定的线圈里,梯形图据此判断链路通断。
怎么配
路径:上位机 → 设备详情页 → DTU 功能 → MQTT 子标签 → 打开「启用 MQTT DTU」。
打开后出现两块:连接参数(共用一份)和 上行组 / 下行组。
连接参数(必填)
| 字段 | 填什么 | 备注 |
|---|---|---|
| Broker 地址 | broker.emqx.io / 192.168.1.100:1883 这种域名或 IP | 默认值仅用于快速连通测试,正式项目必须改成自己的地址 |
| 端口 | 1883 常见;TLS 用 8883 | 第一期不支持 TLS,加密场景改用本页下方的提示 |
| 用户名 / 密码 | Broker 要求认证时填 | MQTT 密码明文传输,不要用重要账号 |
| Client ID | 设备在 Broker 的唯一标识,建议带设备序列号 | 写 {id} 占位符会被替换成设备序列号,保证每台不重复 |
| 心跳间隔 | 默认 60 秒 | 网络差可调小,但不要低于 10 秒 |
| 清除会话 | 通常勾选(不留离线消息) | 保留会话能让 Broker 帮设备存离线消息,前提 QoS ≥ 1 |
| Topic 前缀 | 所有 topic 自动拼的前缀 | 写 {id} 会替换成序列号,留空则不拼前缀 |
| 连接标志线圈 | 默认 M200 | 连上置 1、断开置 0,梯形图可据此判断 |
点 「连接参数」 卡里的 「展开高级选项」 能看到协议版本、客户端 ID、Topic 前缀、连接标志线圈这一批字段。
第一期不支持 TLS
自研 MQTT 客户端走裸 socket,没有 TLS 实现,8883 / mqtts:// 的连接会失败。要加密请走 1.4 HTTP 的反向代理,或换支持 TLS 的 MQTT Broker。
上行组(设备 → 平台)
点「添加上行组」或顶部「选择预设模板」一键填入,界面会展开一组卡片:
| 字段 | 填什么 |
|---|---|
| 名称 | 卡片标题,仅用于本地识别 |
| Topic | 默认 lpplc/{id}/telemetry;以 / 开头视为绝对 topic 不拼前缀 |
| 发送间隔 | 默认 5000ms,最小 100ms |
| QoS | 0 / 1 / 2,按需选 |
| Retain | Broker 是否为这个 topic 保留最后一条消息 |
| 仅变化时发送 | 勾上后渲染结果和上次相同就不发 |
| 报文模板 | 关键字段,写法见下文 |
上限 8 个上行组,每组占一个定时器。
报文模板怎么写
模板是 JSON 字符串,里面用 {地址:类型} 占位符替换寄存器的当前值:
| 占位符 | 含义 |
|---|---|
{id} | 设备序列号 |
{ts} | 当前 Unix 时间戳(秒) |
{ms} | 毫秒时间戳 |
{datetime} | YYYY-MM-DD HH:MM:SS |
{D200} | 读 D200 的 16 位整型 |
{D210:int32} | 读 D210(占 D210/D211)的 32 位整型 |
{D200:float} | 读 D200(占 D200/D201)的浮点 |
{M0} | 读线圈 M0(0 / 1) |
输入框下面是实时样例预览:浮点用 25.5、线圈用 true、整数用 1234。改一个字符就能看到设备将要发的字节,不用下到设备再抓包。
最常用的预设(顶部「选择预设模板 ▾」):
- 标准遥测(推荐) ——
device / timestamp / data:{温度、湿度、压力、运行}大多数平台都能直接消费 - 简单键值对 ——
{temp, humi, status}三行 JSON - ThingsBoard 遥测 —— 主题
v1/devices/me/telemetry,配合「仅变化时发送」最省流量 - 阿里云 IoT 物模型 —— 主题
thing/event/property/post,按物模型格式上报 - CSV 纯文本 —— 不是 JSON,逗号分隔,适合低带宽日志
- 心跳 / 状态包 ——
device / ts / online,配合「仅变化时发送」省流量 - 报警上报 ——
device / ts / type / level / code / message,状态变化才发
下行组(平台 → 设备)
点「添加下行组」或对应的「选择预设模板」一键填入:
| 字段 | 填什么 |
|---|---|
| 名称 | 卡片标题 |
| Topic | 订阅主题;可以含通配符 + / #(只在订阅里允许) |
| QoS | 0 / 1 / 2 |
| 收到一帧的标志位 | 默认 M201,处理完自动清零 |
| 点位列表 | 关键字段,5 个属性见下表 |
上限 8 个下行组 / 每组最多 32 条点位。
点位的 5 个属性
| 字段 | 填什么 |
|---|---|
| 启用 | 勾选才生效 |
| JSON 路径 | 从响应 JSON 取值的路径,如 data.temperature,数组用 values.1(从 1 起) |
| 目标寄存器 | D400 / M10 等;建议后续在梯形图里读它 |
| 类型 | int16 / int32 / float / bit;int32 / float 占两个连续 D |
| 缩放 | 值乘以这个系数再写入;scale=100 表示平台发 25.5 实际写 2550 |
| 最小值 / 最大值 | 都填 0 表示不钳位;只填下限(上限 0)会把值再钳一次到 0,小心恒 0 |
预设的下行模板已经替您配好了常用点位的 JSON 样例,点卡片标题旁边的 「解析」 输入 {"setpoint":25.5,...} 一键解析出字段、再点 「+ 添加」 写入点位表,无需手工抄写路径。
写入并重启
配完点 💾 写入配置 → 🔄 重启生效。不重启,MQTT 客户端还在按旧配置跑。
{id} 是写入时替换
模板里的 {id} 不是您自己写死的字符串 —— 写入时上位机会替成当前选中设备的序列号,同一份配置可以批量下发到几十台上百台设备。
怎么算成功
按顺序检查三处,任一处不通就在那一处停:
| 检查点 | 看到什么算成功 |
|---|---|
| 配置没被拒 | 面板顶部红色 错误清单 为空(broker 地址、端口、topic、占位符语法都过校验) |
| 设备连上 Broker | 「运行状态」色块显示绿色「已连接」;M200 通 |
| 上行报上了 | 「上行报文数」> 0,间隔到了就 +1 |
| 下行收到 | 给订阅的 topic publish 一帧 JSON,看「下行报文数」+1,标志线圈 M201 通,对应寄存器被改写 |
运行状态每 2 秒刷新一次,且仅在 MQTT 子页可见时轮询,离开本页面就停。
常见误区
本节列出最常见的几类错配,详细排查见 A. 常见问题与排查。
| 看到的现象 | 通常原因 |
|---|---|
| 配置一点就报红 | 错误清单有提示,多半是 Broker 端口 / 用户名密码 / topic 字符不合法 |
| Broker 看不到设备 | link_flag 永远 0;先在设备端确认能不能 ping 通 Broker 域名 / IP |
报文内容是 {ts,1234,...} 原样发出 | 占位符大小写错或花括号没闭合;改完看实时预览是不是变了 |
| 上行流量很大 | 模板里带了 ts / ms / datetime 又同时开了「仅变化时发送」 —— 每次渲染结果都不同,相当于未启用 |
| 订阅了一帧 JSON 寄存器没变 | 点位的 path 写错(大小写或层级错);先在「解析」处粘贴回放的 JSON 看能不能列出字段 |
| 收到命令但梯形图拿不到 | recv_flag 写成了 D 区而不是位软元件(M / S / X / Y / TS / CS) |
相关文档
- 数据上到平台后怎么用:WEB 云组态
- 服务器侧 MQTT Broker 配置:服务器数据对接 · MQTT Broker 配置
- 写 Lua 做更灵活的上报 / 订阅