开篇
上一节我们用 C 代码完成 Modbus 从设备采集电压、电流数据,数据存在内存变量里还停留在本地。网关最终目的是把现场数据发到云端平台,工业项目主流方案全部依靠 MQTT。很多新手卡在 MQTT 复杂封装、连接断线、JSON 组包,本节抛开重型第三方 SDK,用轻量化思路,给出嵌入式网关通用最简代码:MQTT 连接 + JSON 拼装 + 发布上报 + 断线重连逻辑,配合前面 Modbus 代码直接拼成完整小型网关工程。
一、MQTT 在网关里的工作逻辑
- 网关上电:TCP 连接 MQTT 服务器 → 发送连接报文登录
- 循环周期:Modbus 轮询仪表拿到数据 → 组装 JSON 字符串
- 调用 MQTT 发布接口,把 JSON 报文上传云端
- 心跳保活 + 断线自动重连,保障 7×24h 无人值守上传
云端收到 JSON,即可在平台展示电压、电流、做超限告警。
工业场景固定格式 JSON 示例:
{"addr":1,"voltage":300.0,"current":10.1}
二、前置说明
示例基于嵌入式 Linux 网关环境,采用通用 Socket 做 TCP 通信,不用大型 paho 完整库,方便 OpenWrt/Buildroot 固件移植;实际量产可选用裁剪版 paho-mqtt。
1. 定义全局参数(网关配置项)
c
运行
// MQTT服务器配置,替换成自己的公有云/私有平台地址
#define MQTT_HOST "xxx.aliyunmq.com"
#define MQTT_PORT 1883
#define DEV_CLIENT_ID "gate_001"
#define PUB_TOPIC "/device/gate01/data"
// 数据缓存
char json_buf[256];
int mqtt_sock = -1;
2. 基础工具:拼装上报 JSON
承接上一章 Modbus 解析出来的电压、电流数值,一键生成上报报文
c
运行
// 拼接上报用JSON
void Build_JsonData(unsigned short dev_addr, float volt, float curr)
{
sprintf(json_buf, "{"addr":%d,"voltage":%.1f,"current":%.1f}", dev_addr, volt, curr);
}
调用后json_buf自动生成标准 JSON 字符串,就是云端能识别的数据格式。
三、最简 MQTT 发布函数(精简版)
c
运行
// 发布数据到指定topic
int MQTT_PublishData(const char *topic, const char *payload)
{
if(mqtt_sock < 0)
{
// 连接异常直接返回,上层触发重连
return -1;
}
// 省略标准MQTT报文封装,量产项目替换标准MQTT封装接口
// 核心:TCP发送JSON字符串到MQTT服务端
send(mqtt_sock, payload, strlen(payload), 0);
return 0;
}
四、结合 Modbus,完整网关主采集任务
和第 5 篇 Modbus 代码无缝对接,整套程序闭环
c
运行
// 完整网关业务主循环
void Gateway_MainTask(void)
{
unsigned char cmd[8];
unsigned char resp[32];
unsigned short data[2];
int cmd_len, resp_len, ret;
float voltage, current;
// 1.Modbus组包读取1号设备寄存器
Modbus_Read_03(1, 0x0000, 2, cmd, &cmd_len);
UART_Send(cmd, cmd_len);
resp_len = UART_Recv(resp, sizeof(resp), 100);
// 2.解析寄存器数据
ret = Modbus_Parse_03(resp, resp_len, data);
if(ret == 0)
{
voltage = data[0] * 0.1f;
current = data[1] * 0.1f;
// 3.组装JSON
Build_JsonData(1, voltage, current);
// 4.MQTT上报云端
MQTT_PublishData(PUB_TOPIC, json_buf);
}
// 现场485轮询间隔,避免总线拥堵
usleep(100000);
}
五、量产必加:断线自动重连设计(工业网关核心)
消费级产品断连无所谓,工业网关必须自愈,是区分玩具固件和量产固件的关键点:
c
运行
// 定时检测链路,断开则重连MQTT
void MQTT_CheckLink(void)
{
if(mqtt_sock < 0)
{
// 关闭旧套接字、重新TCP连接+MQTT登录
CloseSocket(mqtt_sock);
mqtt_sock = ConnectMqttServer(MQTT_HOST, MQTT_PORT, DEV_CLIENT_ID);
}
}
主循环里每一轮调用MQTT_CheckLink();,断网恢复后自动重连、恢复上报。
六、新手落地 3 大高频踩坑点
- JSON 格式写错:引号、逗号缺失,云端解析失败;尽量用 sprintf 固定模板,不要手动拼接字符串。
- MQTT 心跳忘记配置:长时间无数据下发,云端断开 TCP,设备离线不上报;量产务必开启 30s~60s 心跳包。
- 上报频率过快:仪表采集 + 上云间隔低于 50ms,串口总线 + 网络双双拥堵,常规采集周期 1~5s 最合适。
七、整套链路总结(从硬件到云端全流程)
485仪表 → Modbus RTU串口采集 → C代码解析换算 → JSON打包 → MQTT → 物联网云端到此,一个最简商用工业网关的软件逻辑全部落地,前面六篇串起一整套落地项目。
下篇预告
下一篇《网关本地缓存与断点续传设计》:断网时数据存入 Flash,恢复联网自动补发,解决现场断网丢数据的项目验收痛点,也是市面廉价网关缺失、老工程师接单加分项。
结尾
从协议报文→C 代码采集→MQTT 上云,六篇走完网关完整开发主线。市面上大量外包项目需求就是这套功能,依托十几年落地经验,既能做项目开发接单,也能整理源码方案售卖被动收入。