前几天有人问我,地磅房里那台托利多地磅的仪表串口,能不能直接连到MQTT服务上,让过磅数据实时跑到办公室看板里。我说能,而且这种活现在已经算工业数采里的固定套路了:仪表串口出来,接一台有人串口网关,网关把串口字节转成MQTT报文,服务端订阅后解析入库。听起来就三个环节,但真正动手的时候,卡住你的往往不是某个环节本身,而是参数没对齐、数据看不懂、上线之后乱码满天飞。
这篇文章就把我经手这类需求时的完整思路写出来。从串口参数理解、仪表数据帧解析,到网关的每一项配置细节,再到服务端怎么把一堆连续刷屏的数据变成一条能用的过磅记录,最后附上现场常见的坑和长期运行的扩展方案。做工业物联网、地磅改造、设备数据上云的朋友,可以直接拿这份流程去对照操作,能少走不少弯路。
1. 地磅数据上云这件事,卡点从来不在“上云”
1.1 仪表屏幕上的数字,不等于系统里的数字
很多地磅房里的设备并不旧,仪表屏幕亮得清清楚楚,打印小票也正常,就是不会联网。过磅员每天把毛重、皮重抄在纸上,或者拿对讲机报给办公室里的人,再手动敲进Excel。到了月底对账的时候,纸上的数字和仓库台账对不上,谁也说不出是哪一笔出了问题。更麻烦的是夜间无人值守的时段,没有人在仪表旁边盯着,磅房进没进车、过了多少吨,全靠第二天回看记录。
这类问题不在设备本身,而在信息链路。仪表明明已经把重量算出来了,通过串口线也在往外发数据,但没有人去接。只要有一个装置把这串字节变成网络消息,后面的系统就能自动记录、自动汇总。串口网关就是干这个的。
1.2 为什么串口网关加MQTT是最划算的一跳
给旧地磅加联网能力,市面上有三条路:换一块带网口的智能仪表、在旁边加一台工控机、加一台串口网关。我基本都试过,说下感受。
换仪表成本最高,动不动几千上万,而且涉及计量检定的设备,换完还得重新过检,很多现场根本批不下来。加工控机能干活,但工控机要装系统、要防病毒、要远程维护,盘算下来维护成本远比一次性采购高。串口网关就简单了——两三百块的设备,一头接仪表的RS232或RS485,另一头通过有线、Wi-Fi或4G联网,上电自动连MQTT,断电重启自己恢复,几乎不用人管。
至于传输层为什么选MQTT,而不是直接写个TCP客户端连服务器,是因为工业现场的网络条件太不稳定:公网IP不可控、网络会抖动、设备会断线重连。MQTT基于TCP,但它的发布订阅模型、QoS等级、心跳保活机制,天生适合这种无人值守的采集场景。Broker端还能做离线消息缓存,断线期间的数据不至于完全丢光,这点对计重业务很重要。
1.3 这条链路上到底有哪几个角色
把整条链路拆开看,大概是这样的:
- 地磅仪表负责采集传感器信号并计算重量,通过串口按固定格式往外发数据。
- 串口网关负责把串口的字节流原封不动地搬到网络上,相当于一根“数字延长线”,同时作为MQTT客户端连到Broker。
- MQTT Broker负责消息中转,接收网关发布的称重主题,同时把消息推给所有订阅者。
- 服务端程序订阅主题,解析数据帧,提取重量值,落库并触发后续业务逻辑。
串口网关在这里的角色,可以理解成一个翻译加邮差。翻译负责看懂仪表串口出来的字节,邮差负责把字节包装成MQTT消息送出去。只要翻译的“词典”(也就是串口参数)和仪表保持一致,它就能一直安静地工作。
2. 动手前必须吃透的两个底层细节:串口参数和数据帧
2.1 先和仪表“对齐暗号”:波特率这些参数一个都不能错
串口通信看起来是插根线就能用,其实讲究两边参数完全一致,就像两个对讲机必须调到同一个频道才能通话。网关和仪表对接之前,必须先确认四组参数:波特率、数据位、停止位、校验位。这一步没做对,后面收到的一定全是乱码。
我列一个常见参数表,地磅仪表基本都在这个范围内:
| 参数 | 常见值 | 说明 |
|---|---|---|
| 波特率 | 1200、2400、4800、9600 | 地磅仪表常见2400或9600,必须与仪表菜单里的设置完全一致 |
| 数据位 | 7 或 8 | 多数是8 |
| 停止位 | 1 或 2 | 多数是1 |
| 校验位 | 无、偶校验、奇校验 | 多数为无 |
这些参数在哪看?仪表背后的铭牌和设置菜单里通常会有一项“串口设置”或“通讯参数”,说明书丢了也没关系,仪表菜单里翻一圈基本能找到。真要到了找不到参数的情况,也有笨办法:用USB转串口模块接上仪表,拿串口助手把常见波特率都扫一遍,哪个波特率下能抓出可读的ASCII字符,哪个就是对的。这个土办法我试过好多次,很有效。
2.2 仪表常见的三种数据输出方式
地磅仪表向外发数据,我遇到过的主要有三种方式:连续输出、Modbus RTU、打印协议。搞明白自己仪表用的是哪一种,比急着配网关重要得多。
连续输出是最常见的模式,仪表上电后按固定周期主动往串口发当前重量,比如每200毫秒发一帧。这种模式的帧格式一般是ASCII字符串,像这样:
+0000170 kg中间带不带控制符、带不带回车换行,不同仪表略有差异,但核心内容都是“符号 + 数值 + 单位”。这也是我刚才说选“串口透传到MQTT”最省事的原因,网关不需要理解内容,把原始字节原样搬走就行。
Modbus RTU则是问答式的,主机发一段寄存器读取指令,仪表作为从站回一段数据帧。这种模式的好处是能主动读取特定寄存器,坏处是网关得具备Modbus轮询能力,纯透传模式下需要服务端主动下发请求,地磅场景用起来别扭。
打印协议本质上模拟的是仪表连打印机时的行为,一般是在称重稳定后输出一条带完整信息的记录,包括重量、流水号、时间,内容更结构化,但触发条件比较严格。如果现场要用小票审计,这类协议很合适;如果只是要实时重量,连续输出更直接。
2.3 接线方案与电平转换
串口层面还有一个容易被忽略的点:电平标准。仪表背后的串口可能是RS232,也可能是RS485,这两个不能直接混接。
RS232是点对点通信,三根线就能跑,但传输距离别超过15米;RS485是差分信号,两线A/B可以跑上百米,支持多设备挂总线。有些串口网关自带RS232和RS485双接口,买设备的时候确认一下型号就行;如果仪表是RS232、网关只有RS485口,中间加一个几十块的232转485模块就能解决。
地磅现场的环境比较恶劣,附近常有变频器、电机这类强干扰源。我一般要求现场布线用屏蔽双绞线,屏蔽层在网关这一端单点接地,别图省事拿普通网线代替。还有个小细节:RS232的GND线一定要接,不接的话数据会时断时续,排查半天找不到原因。RS485的A/B接反也会出现“能收到但全是乱码”的现象,这时候把两根线对调一下就能验证。
3. 有人串口网关联调全过程:按这个顺序做不返工
3.1 先把网关和电脑拉到同一个网段
配置有人这款串口网关,第一步永远是让电脑能访问它的Web管理页面。网关出厂默认有个局域网IP,说明书上会标,一般是192.168.x.x这种。我的习惯是拿到设备先恢复出厂设置,再通过网线直连电脑,手动给电脑配一个同网段IP,浏览器打开网关后台。
这个步骤看起来没什么技术含量,但很多人会跳过去直接填MQTT服务器地址。填完发现连不上,又怀疑网线坏了、怀疑网关坏了,折腾半天。先做基础连通性验证,后面的问题才有排查的起点。网关后台一般有几个菜单:串口设置、网络设置、MQTT设置、透传参数,逻辑很清楚,按顺序配就行。
3.2 MQTT参数的每一项到底怎么填
MQTT设置是整个配置过程的核心,我逐个讲一下。先看表格:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| 服务器地址 | 内网Broker的IP或公网域名 | 先内网调通再上公网,不要把两步混在一起 |
| 服务器端口 | 1883 | MQTT默认端口,开了TLS要换8883并配证书 |
| Client ID | gw_scale_01 | 必须在Broker上全局唯一,重复会导致互踢 |
| 用户名/密码 | 按Broker实际设置 | 生产环境务必开启认证,别裸奔 |
| 发布Topic | meter/scale01/weight | 建议Topic带上站点和设备标识 |
| QoS | 1 | 不丢消息,应用层做去重,性价比最高 |
| KeepAlive | 60秒 | 网络环境差可以调到30秒 |
| 注册包 | gw_scale_01 | 设备上线自报家门,多设备时极其重要 |
关于Topic的设计,建议从一开始就带上一级设备标识,不要只用裸的weight。因为后面很可能不止一台磅秤,如果都发到同一个Topic,服务端就得靠网关注册包里带的设备ID去区分,增加了解析复杂度。直接每个磅独立Topic,比如meter/scale01/weight、meter/scale02/weight,一下就能分清。
注册包这个功能值得一提,它相当于门卫登记:网关一连接上Broker,就自动往固定主题发一条设备标识消息。服务端可以根据注册包里的设备ID和发布Topic的对应关系,快速判断这台网关是不是接对了仪表。
3.3 串口参数必须和仪表完全一致
串口设置菜单里要填的就是前面说的那四项:波特率、数据位、停止位、校验位。这里只有一个原则:仪表那边是什么,网关这边就填什么,不能有“大概一样”的想法。
我见过一个返工案例,有人觉得仪表波特率是9600,网关也填了9600,数据却还是乱码,最后发现仪表的数据位是7,网关默认是8。这俩参数不匹配,出来的字节流自然对不上。配置完后,很多网关后台都带一个串口调试窗口,可以看到串口收到的原始数据,这一步建议利用起来。如果能看到类似+0000170 kg这种可读ASCII,说明串口链路已经通了,直接进入下一步验证。
3.4 用MQTTX做一次独立验证
私以为,配置完不要直接上生产,先找一个独立客户端验证整条链路。我惯用的办法是开一台EMQX做本地Broker:
docker run -d --name emqx -p 1883:1883 -p 18083:18083 emqx/emqx:5.8.0然后本机再装一个MQTTX客户端,新建连接填127.0.0.1、端口1883,订阅meter/scale01/weight。接下来在网关的串口调试工具里发一条测试帧,或者直接接上真实仪表看数据。MQTTX里能实时刷出消息,就说明从仪表到网关再到Broker这一段是通的。
这个环节要重点检查三件事:服务器地址有没有填错、端口是不是1883、Topic是否区分大小写。MQTT的Topic是严格区分大小写的,我之前就有一次订阅了Scale01,网关发的是scale01,结果怎么也收不到,排查了半天。
3.5 一个容易卡住的细节:透传模式别选错
有人的网管在MQTT模式下,有的固件版本会给你几个选项:透明传输、自定义报文、Modbus采集。我的建议是刚开始一律选透明传输,也就是网关把串口收到的原始字节原封不动作为MQTT的payload发出去。
为什么这么做?因为自定义报文模式会在payload外面再包一层JSON,把网关的IMEI、设备属性、时间戳都带上,看起来方便,但它会让应用层的解析多一层解包逻辑。而且出了问题很难判断是原始数据的问题还是网关包装的问题。先把透明传输跑通,确认原始帧格式后再考虑要不要用模板模式,这是最稳的顺序。
4. 数据上了MQTT,真正的工作才开始:解析与清洗
4.1 主题上躺着的,往往不是一行一个干净数字
把网关配通只是第一步。打开订阅端你会看到,Topic里刷出来的东西根本不像想象中那么规整。按我的经验,串口流里什么都有:仪表上电时的自检文字比如--CAL--、半截帧、重量变化过程中的中间值、偶尔冒出来的中英文单位、甚至因为现场干扰出现的一两个乱码字符。如果直接把每一帧都当成有效重量存进数据库,那数据库很快就会被垃圾数据塞满。
所以要有一个思想准备:能收到数据不等于能直接用。真正要做的,是把这里面有价值的信息挑出来,剩下的全部丢弃。这也是为什么我一直建议保留原始帧字段,出了争议还能回头核对。
4.2 Python解析连续输出帧的骨架代码
服务端的解析逻辑,我习惯用Python写一个MQTT订阅脚本来验证,逻辑清晰、迭代快。先安装依赖:
pip install paho-mqtt然后写一个最基础的解析脚本:
import re import json import time import paho.mqtt.client as mqtt # 匹配常见连续输出帧里的 "数值 + 单位",例如 +0000170 kg、12580 t WEIGHT_RE = re.compile(r"([+-]?\d+(?:\.\d+)?)\s*(kg|t)", re.IGNORECASE) def parse_frame(text: str): m = WEIGHT_RE.search(text) if not m: return None value = float(m.group(1)) unit = m.group(2).lower() # 统一换算成吨,后续业务也好比较 weight_t = value / 1000.0 if unit == "kg" else value return weight_t def on_message(client, userdata, msg): try: text = msg.payload.decode("ascii", errors="ignore") except Exception: return weight_t = parse_frame(text) if weight_t is None: return record = { "topic": msg.topic, "weight_t": weight_t, "ts": time.time(), "raw": text.strip(), } print(json.dumps(record, ensure_ascii=False)) client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) client.on_message = on_message client.connect("127.0.0.1", 1883, 60) client.subscribe("meter/scale01/weight", qos=1) client.loop_forever()这段代码里我特别留了一个raw字段,存的是原始消息文本。很多人会把这个字段省掉,但真正上了生产你就知道它的价值——当业务部门质疑某条重量数据时,你翻出原始帧一看就知道是仪表发的还是程序算错了,一句话就能说清。解析用的正则不一定通用,因为不同仪表输出格式有差异,但思路是一致的:用“数字 + 单位”这两个特征去抓重量,其他字符不用管。
4.3 从“一条重量数据”到“一条过磅记录”的处理策略
解析单帧只是地基,真正让业务满意的是输出“某年某月某日某时,车牌某号,毛重多少吨”这种完整记录。这需要一个简单的状态机逻辑。
车辆过磅时,仪表输出的重量会经历一个典型过程:从零开始上升,中间可能跳动,数值稳定在一个平台,然后车辆驶离,重量归零。所以收到数据时可以这样做:
- 每帧都解析出重量值,解析失败的直接丢弃。
- 过滤掉超过量程或者明显不合理的数值,比如负得离谱的、超载好几倍的。
- 做稳定判定:连续收到三到五帧,重量完全一致或者误差小于仪表分度值,才认为这是一个稳定值。
- 稳定值出现变化时,如果比上一档更高,就记成“当前毛重”的候选值。
- 当重量从高位跳回接近零,判定这一次过磅结束,把刚才记录到的最高稳定值作为毛重,连同起止时间一起写入记录表。
这套逻辑写起来不复杂,但能过滤掉绝大部分中间态和干扰帧。如果要自动算皮重和净重,就得再配合业务规则,比如“第一次过磅记为毛重,第二次过磅记为皮重,两次之间间隔不超过多长时间”这种逻辑,按现场流程去配。
4.4 落库与告警联动
数据整理干净之后,落到哪个存储就看现场条件了。简单项目直接写SQLite,单文件零运维,量大了换MySQL。核心字段建议至少保留这几个:id、gateway_id、weight_t、event_time、raw_data。其中raw_data保存原始帧字符串,前面说过,未来对账和排查全靠它。
告警联动也是地磅项目里经常要的:车辆毛重超过设定阈值,自动通知调度室;或者同一台网关连续半小时没有任何消息,说明可能断线了,要发一个离线告警。这些判断逻辑都很直接,服务端订阅心跳主题做超时检测就行。做到这一步,原来那台只会亮数字的仪表,才算真正变成了生产系统的一部分。
5. 稳定运行半年的一些总结与扩展玩法
5.1 现场高频故障清单和排查顺序
项目上线后不可能一直风平浪静,我总结了一份高频故障清单,按出现概率排个序:
| 现象 | 大概率原因 | 排查动作 |
|---|---|---|
| 完全收不到数据 | 串口线没接对、网关没连上Broker | 看网关LED状态,用串口助手抓仪表原始输出,看Broker在线客户端列表 |
| 收到但全是乱码 | 波特率或数据位和仪表不一致 | 进仪表菜单核对串口参数,网关侧同步修改 |
| 时断时续 | RS485 A/B接反、干扰、线缆过长 | 对调A/B,换屏蔽双绞线,检查屏蔽层接地 |
| 重量一直为0 | 仪表没开启连续发送模式 | 在仪表设置里把输出模式切到连续发送 |
| 断网重连后不推数据 | 网关掉线后没有重新订阅,或者QoS设太低 | 设QoS 1,开启注册包,检查Broker日志 |
排查顺序有一个原则:先查物理层,再查参数层,最后才查应用层。很多人一上来就怀疑代码逻辑,结果折腾一圈发现是A/B线接反了。先把“有没有数据到Broker”这个问题确认了,后面的一切才有意义。
5.2 一台网关管两台磅秤的扩展办法
现场通常不止一台秤,这时候就有几种扩展思路。最省事的方案是每台磅配一台独立网关,各自上报独立Topic,服务端按Topic分支处理。这个方案我推荐优先考虑,虽然多花几百块硬件钱,但每台设备互相隔离,坏了哪台排查哪台,不用动代码。
如果网关本身支持双串口或者可以挂多台RS485从站,那可以在同一台设备上管理多台仪表。前提是仪表支持Modbus RTU协议,且从站地址不一样,这样网关可以轮询多台表,把不同地址的寄存器值分开发到不同Topic。这个方案省网关,但配置复杂,轮询时序还要考虑每台仪表的响应时间。
还有一种是很多项目会碰到的“云端平台统一管理”模式:所有网关都连到同一台Broker,靠注册包里的设备ID区分来源。这种模式下Topic可以统一成一个入口,服务端根据设备ID映射到对应的磅秤编号,然后落到不同表。多站点、多磅秤的场景用这种更清晰。
5.3 防止篡改与数据核对的审计思路
地磅数据涉及计量,业务部门最担心的就是数据被改。我的建议是设计上做几道防线:第一,原始帧raw字段入库后不允许修改,服务端解析出来的重量不管对错,都保留原文备查;第二,事件时间戳由服务端接收那一刻打,不要信任设备侧的时钟,防止时间被改;第三,做数据连续性校验——正常过磅一定有从零上升到峰值再回零的曲线,如果收到的数据里出现重量从零直接跳到20吨然后一直不变,大概率是有人在模拟器灌数据,直接触发告警。
这几道防线做下来,至少能在技术上保证“数据可追溯、异常可发现”。现场对这个东西的看重程度,往往比我们想象的更高。
5.4 几个想说给后来人的心里话
做了这么多地磅数据上云项目,我最大的感受是:硬件和软件都不是最难的,最难的是把仪表那头的细节和云端这边的逻辑对齐。仪表输出什么格式、波特率多少、单位是公斤还是吨、稳定后才发还是一直发,这些决定了解析代码怎么写、告警阈值怎么设。如果不先去抓一帧原始数据看一眼,再好的架构也白搭。
所以我建议所有做这类改造的朋友,拿到项目第一件事,不是选网关也不是写代码,而是拿串口助手去仪表背后抓几帧数据,把协议吃透。这个习惯能让你少踩一半的坑。链路通了之后,你会发现这台几百块的串口网关可以一直安静地跑下去,偶尔翻一翻日志,确认它还在那里,就已经很够用了。