
1. 商用热水工程为什么必须上IoT监控做过商用热水工程的人都有一个共同的痛项目交付那天才是麻烦的开始。一栋酒店、一个学校宿舍、一座工厂澡堂热水系统里少则几台空气源热泵多则十几台机组加上循环泵、补水阀、水箱、电辅热分散在楼顶、地下室、设备间。以前的做法是派个师傅每周巡检一次抄表、看压力、听异响运气好提前发现水泵卡死运气不好就是整栋楼没热水客诉电话打爆甲方扣质保金。我手上有个真实的项目某园区宿舍楼六台10匹空气源热泵并联配两个5吨保温水箱。交付后第三个月一台机组的化霜传感器漂移导致这台机器频繁进入化霜保护制热量掉了一半。巡检师傅一周来一次每次来都是白天用水低谷水温看着正常愣是拖了二十多天才被发现那段时间宿舍楼晚上洗澡水温只有38度投诉不断。后来我们给这套系统加了IoT监控同样的传感器漂移系统在4小时内就通过回水温度异常和机组运行时长偏差报了出来。这就是商用热水工程IoT监控的核心价值把人找问题变成问题找人。整套方案的技术骨架其实不复杂用一句话概括就是——现场设备通过Modbus协议把数据吐出来网关把Modbus转成MQTT发到服务器服务器用InfluxDB存时序数据最后Grafana把图画出来异常触发告警。这条链路里的每一个环节都有坑下面我按实战顺序拆开讲。这套内容适合三类人看一是做暖通、热水工程的施工方和运维方想给自己的项目加远程监控二是刚接触工业IoT的开发者想找一个完整的、能落地的练手项目三是甲方设备管理员想搞明白乙方报上来的智能监控到底是怎么回事。不管你是哪一类读完应该都能自己搭一套出来。2. 整体架构设计与选型思路2.1 从现场到云端的数据链路拆解先看整体架构我把它分成四层从下往上依次是设备层、采集层、传输层、应用层。设备层就是热水系统里的实际硬件空气源热泵机组、循环水泵、补水电磁阀、水温传感器、压力变送器、流量计、电表。这些设备里热泵机组和变频水泵通常自带RS485接口支持Modbus RTU水温传感器如果是PT100或者NTC需要一个采集模块把它转成Modbus信号电表一般也带Modbus。所以设备层的核心任务就是确认每个设备能不能说Modbus。采集层是网关或者边缘计算盒子。它的活儿是轮询设备层的Modbus寄存器把原始数据读上来做初步的解析和单位换算然后打包成MQTT消息发出去。这一层是整个方案的关键选型选错了后面全是麻烦。传输层就是MQTT Broker负责消息的接收和分发。可以部署在云服务器上也可以部署在项目本地的工控机上。对于商用热水这种单点项目我一般建议Broker和数据库部署在同一台服务器上减少网络环节。应用层是InfluxDB加Grafana。InfluxDB存时序数据Grafana负责可视化。告警可以在Grafana里配也可以用单独的告警服务。2.2 为什么选Modbus而不是别的协议有人会问现在这么多协议为什么还用Modbus这个老古董。原因很实在商用热水设备里Modbus的覆盖率是压倒性的。空气源热泵厂家不管大小品牌RS485接口基本都支持Modbus RTU寄存器表虽然各家不一样但协议本身是通的。你换任何其他协议设备端都不认。Modbus的本质非常简单就是主站问、从站答。主站发一帧我要读从站地址1的保持寄存器从40001开始读10个从站回一帧数据。就这么朴素。它的优点是简单、稳定、几乎所有工控设备都支持缺点是慢、没有安全机制、寄存器地址各家定义混乱。在热水工程里我们主要用两个功能码03读保持寄存器读温度、压力、运行状态这些模拟量和01读线圈读开关状态。偶尔用06写单个寄存器做远程控制比如远程开关机、设定温度。这里要特别注意远程控制功能一定要谨慎开放后面避坑部分会细说。2.3 MQTT为什么适合这种场景MQTT是发布订阅模型网关作为客户端把数据publish到某个topic服务器订阅这个topic就能收到。相比HTTP轮询MQTT的优势在于长连接、低开销、支持断线重连、天然适合多设备上报。在热水工程里一个网关可能要管几十上百个数据点如果每个点都发一次HTTP请求开销大且容易丢。MQTT可以一次发一个JSON包把所有数据点打包上报效率高很多。而且MQTT的QoS机制可以保证消息至少送达一次对于温度这种数据偶尔丢一两个点无所谓但对于告警消息QoS设成1就很有必要。Topic设计我一般用这样的结构hotwater/{项目编号}/{网关编号}/{设备类型}/{设备编号}。比如hotwater/park01/gw01/heatpump/hp03。这样在服务器端订阅hotwater/park01/#就能收到整个项目的所有数据订阅hotwater/park01/gw01/heatpump/#就只看热泵。层级清晰后期扩展方便。2.4 存储和可视化选型InfluxDB是专门存时序数据的写入性能好自带降采样和保留策略。热水工程的数据特点是高频写入、按时间查询、老数据价值递减。比如温度每30秒采一次一天就是2880个点一年上百万个点。用MySQL存也能存但查询和聚合会越来越慢。InfluxDB的连续查询Continuous Query可以自动把原始数据降采样成小时均值、日均值老数据自动清理这是关系型数据库做起来很别扭的事。Grafana不用多说画图神器支持InfluxDB数据源配置告警也方便。它的面板可以做成大屏挂在运维办公室谁路过都能看一眼整个项目的运行状态。3. 核心细节解析与实操要点3.1 Modbus寄存器地址的坑40001到底对应哪个地址这是新手最容易栽的地方。Modbus协议文档里经常写保持寄存器40001但实际编程时你要填的地址是0。为什么因为Modbus有协议地址和文档地址两套编号。文档地址40001里的4表示保持寄存器后面的0001是序号从1开始协议地址从0开始所以40001对应协议地址040002对应1以此类推。更坑的是有些厂家文档写的是寄存器地址0x0000有些写40001有些写寄存器1。你在配置网关的时候一定要先确认厂家给的是哪种编号。我的经验是拿到寄存器表后先用Modbus Poll连上设备实测一遍读出来的值跟实际对得上再往网关里配。别信文档信实测。还有一个坑是数据类型和字节序。温度这种值厂家可能用16位有符号整数表示比如实际温度25.5度寄存器里存的是255需要除以10。也可能是32位浮点数占两个寄存器这时候就涉及字节序问题——高字节在前还是低字节在前。不同厂家不一样实测的时候如果读出来是个离谱的大数八成是字节序反了把两个寄存器的顺序调一下试试。3.2 网关轮询策略别把设备问死Modbus是主从轮询主站不问从站不答。网关作为主站要不停地轮询各个从站。这里有个度的问题轮询太快设备响应不过来会超时轮询太慢数据实时性差。我的经验值是对于热泵机组轮询周期设5到10秒比较合适。因为热泵的温度变化本身很慢5秒一次完全够用。对于电表这种需要算功率的可以设1到2秒。但要注意同一个RS485总线上挂的设备越多单次轮询一圈的时间越长。如果一条总线上挂了10台设备每台读20个寄存器波特率9600算下来一圈可能要好几秒。这时候要么提高波特率到19200或38400要么分多条总线。还有个细节是超时和重试。Modbus RTU在9600波特率下一个字符传输时间约1毫秒一帧报文几十个字符正常响应在几十毫秒内。超时时间设500毫秒到1秒比较稳妥。重试次数设2到3次超过就标记该设备离线别死等否则会拖垮整条总线的轮询。3.3 MQTT消息格式设计JSON怎么组织网关读上来的数据打包成JSON发MQTT。格式设计要考虑两点服务器端好解析人看着也明白。我一般用这样的结构{ gw: gw01, ts: 1718000000, devices: [ { type: heatpump, id: hp03, online: true, data: { inlet_temp: 42.5, outlet_temp: 47.2, ambient_temp: 18.3, run_status: 1, fault_code: 0 } } ] }ts是网关本地时间戳单位秒。为什么要带时间戳因为网络可能延迟服务器收到消息的时间不等于数据产生的时间。InfluxDB写入时用这个时间戳曲线才准确。online字段标记设备是否在线这个很重要。如果某台设备轮询超时网关应该发一条online: false的消息而不是干脆不发。否则服务器端看到的是数据停了但不知道是设备坏了还是网关坏了。3.4 InfluxDB数据模型measurement、tag、field怎么分InfluxDB的数据模型跟关系型数据库不一样它没有表只有measurement。每个数据点由measurement tag set field set timestamp组成。tag是带索引的用来查询过滤field是实际数值不带索引。在热水工程里我这样设计measurementhotwatertagproject项目编号、gw网关编号、device_type设备类型、device_id设备编号、point数据点名称fieldvalue数值这样一条数据就是hotwater,projectpark01,gwgw01,device_typeheatpump,device_idhp03,pointoutlet_temp value47.2 1718000000。为什么把point也做成tag因为这样查询某个具体数据点的历史曲线时直接WHERE pointoutlet_temp就能过滤效率高。如果做成field就得全表扫描。代价是tag的基数会变大但热水工程的数据点数量有限一台热泵也就二三十个点整个项目几百个点完全扛得住。注意InfluxDB的tag值不要用会频繁变化的东西比如时间戳、随机数。tag基数爆炸是InfluxDB性能杀手。设备编号、数据点名称这种相对固定的值做tag是合适的。4. 实操过程与核心环节实现4.1 现场设备接线与Modbus调试第一步永远是现场调试。拿一台笔记本电脑装Modbus Poll加一个USB转RS485转换器直接接到热泵机组的RS485口上。A接AB接B注意有些厂家标的是A、B-别接反接反了读不到数据。打开Modbus Poll设置串口参数波特率、数据位、停止位、校验位。热泵厂家常用的是9600、8、N、19600波特率8数据位无校验1停止位也有用19200的。这些参数在机组说明书里都有找不到就问厂家技术支持。然后设置从站地址和功能码。从站地址一般是1如果一条总线上有多台地址会依次是1、2、3……功能码选03。起始地址填0对应文档地址40001数量填10先读10个寄存器看看。读出来之后对照厂家的寄存器表逐个确认。比如寄存器0是进水温度寄存器1是出水温度。如果读出来的值跟实际差10倍说明需要除以10。如果读出来是65535这种可能是传感器没接或者故障。这一步千万别偷懒。我见过太多项目网关配置好了发到现场结果数据全是错的远程排查半天最后发现是寄存器地址填错了一位。现场花两小时调通比远程折腾两天强。4.2 网关配置以常见边缘网关为例网关的配置逻辑各家产品不一样但核心步骤是相通的。我用过一个比较典型的边缘网关配置流程是这样的首先配置串口参数跟现场调试时一致。然后添加从站设备填从站地址、功能码、起始地址、寄存器数量、数据类型、单位换算系数。比如出水温度起始地址0数量1数据类型int16系数0.1。接着配置MQTT连接。填Broker地址、端口1883或8883、客户端ID、用户名密码。客户端ID要唯一建议用网关编号。然后配置发布topic填hotwater/park01/gw01/data。最后配置轮询策略设置轮询周期、超时时间、重试次数。保存后重启网关看MQTT Broker那边有没有收到消息。这里有个实操技巧先用MQTT客户端工具订阅topic确认网关在发数据再去配InfluxDB。这样能把问题隔离如果没数据是网关的问题如果有数据但InfluxDB里没有是写入配置的问题。4.3 服务器端搭建InfluxDB和Grafana安装服务器我一般用Ubuntu 22.04稳定且软件源全。InfluxDB用1.8版本虽然2.x出来了但1.8的InfluxQL查询语言更成熟Grafana支持也更好。安装InfluxDBwget https://dl.influxdata.com/influxdb/releases/influxdb_1.8.10_amd64.deb sudo dpkg -i influxdb_1.8.10_amd64.deb sudo systemctl start influxdb sudo systemctl enable influxdb启动后进influx命令行创建数据库和用户CREATE DATABASE hotwater CREATE USER hotwater WITH PASSWORD your_password GRANT ALL ON hotwater TO hotwater然后配置数据写入。网关发的是MQTT消息需要一个服务把MQTT消息转成InfluxDB写入。可以用Telegraf也可以用自己写的小程序。Telegraf配置简单在telegraf.conf里加MQTT consumer和InfluxDB output就行。但Telegraf的JSON解析有时候不够灵活如果消息格式复杂我建议用Python写个订阅程序用paho-mqtt订阅解析JSON后调influxdb-client写入。这样可控性最强。Grafana安装sudo apt-get install -y software-properties-common sudo add-apt-repository deb https://packages.grafana.com/oss/deb stable main sudo apt-get update sudo apt-get install grafana sudo systemctl start grafana-server sudo systemctl enable grafana-server默认端口3000浏览器打开http://服务器IP:3000初始账号密码都是admin。进去后添加InfluxDB数据源填数据库名、用户名密码保存测试。4.4 Grafana面板配置从单点到全局面板配置是门手艺。我的做法是先做单设备详情面板再做全局总览面板。单设备详情面板比如一台热泵放这几个图进水温度、出水温度、环境温度三条曲线叠在一起运行状态用状态图故障码用表格。时间范围默认最近6小时可以切换24小时、7天。全局总览面板放所有热泵的出水温度曲线用不同颜色区分所有水泵的运行状态水箱液位当日能耗。这个面板适合挂大屏。告警配置在Grafana里做比如出水温度低于40度持续5分钟就告警。告警通道可以配邮件、Webhook。Webhook可以对接企业微信或者钉钉的机器人这样告警直接推到运维群。提示Grafana的告警评估周期和持续时间要配合好。评估周期设1分钟持续时间设5分钟意思是每分钟检查一次连续5次都满足条件才告警。这样能过滤掉传感器抖动造成的误报。5. 常见问题与排查技巧实录5.1 Modbus读不到数据怎么排查这是最高频的问题。排查顺序我总结成一张表现象可能原因排查方法完全无响应接线反了交换A、B线完全无响应串口参数不对核对波特率、校验位完全无响应从站地址不对试1到247逐个扫返回异常码寄存器地址越界核对寄存器表返回异常码功能码不支持换03或04试试数据乱码字节序不对调换高低字节数据乱码数据类型不对确认是int16还是float32时好时坏总线干扰加终端电阻、屏蔽线接地其中接线反了是最常见的尤其是现场施工的师傅不熟悉RS485A、B随便接。RS485的A、B在不同厂家文档里叫法还不一样有的叫A、B-有的叫D、D-有的叫T/R、T/R-。记住一个原则所有设备的A接在一起B接在一起如果不行就全部反过来。总线干扰也很常见尤其是RS485线跟动力线走同一个桥架。解决办法是RS485用屏蔽双绞线屏蔽层单端接地远离变频器、接触器这些干扰源总线两端加120欧姆终端电阻。5.2 MQTT消息丢失或延迟MQTT消息丢失先看QoS等级。QoS 0是发了不管网络抖动就丢QoS 1是至少一次会重发QoS 2是恰好一次开销大。热水工程的数据上报用QoS 1就够了告警消息也用QoS 1。如果QoS 1还丢检查Broker的连接数限制和消息队列大小。有些轻量Broker默认队列很小消息一多就丢。另外检查网关的网络4G信号弱的地方MQTT长连接会断断了要能自动重连。好的网关都有断线重连和消息缓存机制断网期间的数据存在本地恢复后补发。延迟问题一般是网络问题或者Broker负载太高。可以在网关端打时间戳服务器端收到时对比算出端到端延迟。正常应该在1秒以内。5.3 InfluxDB写入失败或查询慢写入失败先看权限数据库用户有没有写权限。再看时间戳如果时间戳是未来时间InfluxDB会拒绝。网关的时间要同步最好用NTP。查询慢一般是tag设计问题。如果tag基数太大比如把时间戳做成tag那每个点都是唯一的tag组合索引会爆炸。检查方法是SHOW SERIES看序列数量如果几十万上百万就要优化tag设计。另一个原因是查询范围太大。查一年的原始数据肯定慢应该用降采样。InfluxDB的连续查询可以自动生成小时均值、日均值查询时查降采样后的measurement。5.4 远程控制的禁忌最后说一个最重要的避坑点远程控制功能一定要慎之又慎。我见过一个项目运维人员在Grafana上点了个按钮把某台热泵远程关机了结果那台机器是主控机一关整个系统都停了宿舍楼当晚没热水。远程控制的原则能自动的不要手动能只读的不要写。如果非要远程控制必须满足几个条件一是控制指令要有二次确认二是要有权限分级普通运维只能看高级管理员才能控三是要有操作日志谁在什么时候控了什么全部记录四是关键设备比如主控热泵、总循环泵禁止远程关机只能远程改设定温度这种温和的操作。还有Modbus写寄存器是盲写写完不知道成没成功。所以写完要回读确认读回来的值跟写入的一致才算成功。这个逻辑要在网关或者服务器端实现。6. 几个提升运维效率的实战技巧6.1 用运行时长偏差发现隐性故障热泵机组有个特点多台并联时如果负荷分配均匀各台机组的累计运行时长应该差不多。如果某台机组的运行时长明显低于其他台说明它可能有问题比如制热能力下降、频繁保护停机。这个指标在Grafana里用一个简单的查询就能算出来比等故障码报出来早得多。6.2 用回水温度变化率判断系统效率热水系统的能效看回水温度的变化率最直观。正常加热时回水温度应该稳定上升。如果上升很慢可能是热泵结霜、冷媒不足、或者水泵流量不够。如果回水温度忽高忽低可能是水箱分层或者传感器位置不对。把这个变化率做成曲线异常一眼就能看出来。6.3 告警分级别让狼来了告警最怕的是天天报报到最后没人看。所以告警一定要分级紧急比如出水温度低于35度、设备离线超过30分钟直接打电话重要比如单台设备故障、能耗异常偏高推企业微信提示比如滤网需要清洗、运行时长接近保养阈值每天汇总一次发邮件。分级之后运维人员对紧急告警的响应速度会明显提高。6.4 数据保留策略要提前规划InfluxDB的数据保留策略Retention Policy要提前设好。原始数据保留30天小时均值保留1年日均值保留3年。这样既不会把磁盘撑爆又能满足长期趋势分析的需求。磁盘空间估算一个项目500个数据点30秒采一次一天约144万个点每个点约20字节一天约28MB30天约840MB。加上降采样数据一年也就几个GB普通云服务器完全够用。7. 写在最后的一点个人体会这套方案我从第一个项目到现在前后迭代了四五版。最早用组态软件后来换成网关加云平台再后来自己搭InfluxDB加Grafana。踩过的坑包括但不限于寄存器地址填错、字节序搞反、MQTT消息格式改来改去、InfluxDB tag设计不合理导致查询卡死、Grafana告警配得太敏感天天误报。如果让我给刚入行的人一句建议那就是先把一个设备的数据完整跑通再复制到整个项目。别一上来就想着把所有设备都接进来先把一台热泵的Modbus读通、MQTT发通、InfluxDB存通、Grafana画通这条链路走一遍后面就是体力活了。还有现场调试的时候多拍照片接线照片、设备铭牌照片、寄存器表照片全部存档。后期远程排查的时候这些照片能救命。我现在的习惯是每个项目建一个文件夹按设备编号存照片和配置找起来很快。这套东西不难但细节多。耐心一点一个项目做下来你就摸透了。