2026实战:C#上位机对接LoRa/NB-IoT仪表构建工业能耗监测与预警系统

张开发
2026/6/30 4:47:01 15 分钟阅读
2026实战:C#上位机对接LoRa/NB-IoT仪表构建工业能耗监测与预警系统
上个月给一家做汽车配件的工厂做了套能耗监测系统折腾了两周踩了不少LoRa信号和时序数据库的坑今天把整个过程分享出来。这家工厂有30多台注塑机、5台空压机还有十几台数控机床电费占生产成本的18%之前全靠人工抄表月底才知道这个月又超支了而且根本不知道哪台设备在偷偷耗电。我们用「LoRaNB-IoT混合组网C#上位机」的方案实现了电、水、气的实时监测上线后第一个月就帮他们省了12%的电费。一、项目痛点与需求分析这家工厂的能耗管理问题非常典型数据滞后人工抄表每天一次周末没人管等发现电费超支已经晚了数据不准抄表员看错数字、漏记的情况时有发生财务对账总是对不上浪费严重有几台空压机常年漏气没人发现注塑机待机时加热圈还在全功率运行无法分析只有总表数据不知道每台设备的能耗情况想优化都无从下手。我们的核心需求很明确实时监测30台注塑机、5台空压机、3个总电表、2个水表、1个气表的数据每5分钟上报一次数据数据精度到0.1度支持日/月/年能耗报表同比环比分析当设备能耗超过阈值时立即弹窗邮件报警。二、系统整体架构设计考虑到工厂厂区大、设备分散我们采用了「LoRaNB-IoT混合组网」的方案车间内密集的设备用LoRa传输远、功耗低、免流量费厂区边缘的水表、气表用NB-IoT有运营商信号就能用不用自己布网关。系统架构图如下LoRa射频LoRa射频LoRa射频NB-IoT基站NB-IoT基站MQTTMQTT透传订阅数据注塑机LoRa电表30台LoRa网关RAK7258安装在车间楼顶空压机LoRa电表5台总电表LoRa模块3个水表NB-IoT模块2个运营商MQTT平台气表NB-IoT模块1个本地MQTT BrokerEMQXC#上位机监控系统时序数据库InfluxDB 2.0实时数据展示大屏客户端能耗分析报表RDLC超限预警弹窗邮件终端层LoRa电表杭州华立DDSU666LoRa模块、NB-IoT水表宁波水表NB-IoT款、气表重庆山城NB-IoT款传输层LoRa网关RAK7258支持8通道覆盖半径1公里、NB-IoT运营商网络选的电信信号稳定平台层EMQX作为MQTT BrokerInfluxDB 2.0存储时序数据应用层C# WinForms上位机实现数据采集、展示、分析和预警。三、硬件选型与部署3.1 LoRa设备选型与部署LoRa电表杭州华立DDSU666单相/三相可选精度1.0级自带Modbus RTU接口我们外接了一个RAK3172 LoRa模块STM32WLE5芯片低功耗LoRa网关RAK7258工业级IP65防护支持PoE供电安装在车间楼顶高度8米天线用的是5dBi全向天线部署要点LoRa网关尽量放在高处避开金属设备遮挡信道配置用470-510MHz的免授权频段扩频因子SF9带宽125kHz保证传输距离和可靠性。3.2 NB-IoT设备选型与部署NB-IoT水表宁波水表LXSY-NB内置移远BC95 NB-IoT模块支持电信/移动/联通IP68防水电池寿命8年NB-IoT气表重庆山城G4-NB同样内置BC95模块支持脉冲计数和直读部署要点先测信号厂区角落的水表信号弱加了个信号放大器APN配置成电信的“ctnb”上报周期设为15分钟电池寿命优先。四、软件实现4.1 终端数据格式定义LoRa和NB-IoT设备的数据格式不一样我们统一转成JSON格式发到MQTT BrokerLoRa电表数据格式Modbus RTU转JSON{device_type:meter,device_id:lora_meter_001,protocol:lora,data:{voltage:220.5,current:12.3,power:2712.15,energy:1234.56,factor:0.95},timestamp:1713072000}NB-IoT水表数据格式{device_type:water,device_id:nb_water_001,protocol:nbiot,data:{flow:123.45,pressure:0.32},timestamp:1713072000}4.2 C#上位机核心代码我们用了MQTTnet库订阅数据InfluxDB.Client库存储时序数据RDLC做报表System.Windows.Forms.DataVisualization画实时曲线。1MQTT订阅与数据解析usingMQTTnet;usingMQTTnet.Client;usingNewtonsoft.Json.Linq;usingSystem;usingSystem.Text;usingSystem.Windows.Forms;namespaceIndustrialEnergyMonitor{publicpartialclassMainForm:Form{privateIMqttClient_mqttClient;publicMainForm(){InitializeComponent();InitializeMqttClient();InitializeInfluxDb();}privateasyncvoidInitializeMqttClient(){varfactorynewMqttFactory();_mqttClientfactory.CreateMqttClient();varoptionsnewMqttClientOptionsBuilder().WithTcpServer(192.168.1.200,1883).WithClientId(C#_Energy_Monitor).Build();_mqttClient.ApplicationMessageReceivedAsyncMqttClient_ApplicationMessageReceivedAsync;await_mqttClient.ConnectAsync(options);await_mqttClient.SubscribeAsync(industrial/energy/#);}privateTaskMqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgsarg){varpayloadEncoding.UTF8.GetString(arg.ApplicationMessage.Payload);varjsonJObject.Parse(payload);this.Invoke((MethodInvoker)delegate{// 更新实时UIUpdateRealtimeUI(json);// 存储到InfluxDBSaveToInfluxDb(json);// 检查是否超限CheckAlarm(json);});returnTask.CompletedTask;}privatevoidUpdateRealtimeUI(JObjectjson){vardeviceIdjson[device_id].ToString();vardatajson[data];// 简单示例根据device_id找到对应的控件并更新if(deviceIdlora_meter_001){lblVoltage.Textdata[voltage].ToString() V;lblCurrent.Textdata[current].ToString() A;lblPower.Textdata[power].ToString() W;// 添加到实时曲线chartRealtime.Series[Power].Points.AddY(Convert.ToDouble(data[power]));}}}}2InfluxDB 2.0数据存储usingInfluxDB.Client;usingInfluxDB.Client.Api.Domain;usingInfluxDB.Client.Writes;namespaceIndustrialEnergyMonitor{publicpartialclassMainForm:Form{privateInfluxDBClient_influxDbClient;privateWriteApi_writeApi;privatevoidInitializeInfluxDb(){_influxDbClientInfluxDBClientFactory.Create(http://192.168.1.200:8086,your_token);_writeApi_influxDbClient.GetWriteApi();}privatevoidSaveToInfluxDb(JObjectjson){vardeviceTypejson[device_type].ToString();vardeviceIdjson[device_id].ToString();vartimestampDateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(json[timestamp]));vardatajson[data];varpointPointData.Measurement(energy_data).Tag(device_type,deviceType).Tag(device_id,deviceId);// 动态添加字段foreach(varitemindata){pointpoint.Field(item.Key,Convert.ToDouble(item.Value));}pointpoint.Timestamp(timestamp,WritePrecision.S);_writeApi.WritePoint(point,industrial_energy,org_name);}}}3能耗报表与预警报表用RDLC做直接从InfluxDB查询日/月/年数据绑定到ReportViewer上。预警功能更简单设置好每个设备的阈值比如空压机功率超过100kW报警收到数据时对比一下超限就弹窗发邮件用System.Net.Mail。五、部署踩坑总结5.1 LoRa信号问题一开始LoRa网关装在车间二楼被几台大型注塑机挡住了信号最远的节点丢包率达30%。后来把网关移到车间楼顶高度升到8米换了5dBi全向天线丢包率降到0.1%以下。5.2 InfluxDB查询性能问题刚上线时查询一个月的能耗数据要10秒后来优化了InfluxDB的保留策略原始数据保留30天降采样1小时平均值保留1年降采样1天平均值永久保留给device_id和device_type加了索引查询速度提升到1秒以内。5.3 NB-IoT数据上报延迟NB-IoT水表有时候会延迟1-2分钟上报数据后来查了文档是因为NB-IoT的PSM模式省电模式模块大部分时间在休眠我们把上报周期从10分钟改成15分钟关闭了PSM模式牺牲一点电池寿命换实时性延迟就稳定在10秒以内了。六、总结与扩展这套系统上线一个月效果很明显实时发现了3台空压机漏气的问题修复后每天省200度电给注塑机设置了待机功率阈值工人下班忘记关机就会报警每月省1500度电财务对账再也不用人工抄表直接导出报表就行。后续可以扩展的功能接入ERP系统把能耗数据和生产数据结合计算单位产品能耗用机器学习算法预测能耗高峰提前安排生产计划避峰填谷做个手机APP老板随时随地能看能耗数据。如果你也在做工业能耗监测欢迎一起交流踩坑经验。

更多文章