ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

不改WinCC和PLC,用Node-RED边缘网关加报警的完整方案

不改WinCC和PLC,用Node-RED边缘网关加报警的完整方案 1. 为什么说“不改系统加报警”这件事能成立做工业现场的都知道WinCC和PLC这套组合一旦稳定跑起来就是“祖宗级”待遇——轻易没人敢动。改PLC程序要停机、要重新调试还得担心逻辑改动后影响原有工艺改WinCC画面和脚本同样麻烦版本授权、编译下载、上位机重启每一步都可能惹出新问题。但现场需求往往不会等你准备好设备报警要推送到手机、第三方系统要拿数据、现场要加一路声音报警、某个关键参数超限得有人马上知道。这个“又不想动老系统、又必须加报警”的矛盾我见到太多了。方案其实就一句话在PLC和WinCC之间或者WinCC的上位链路里旁路一个Node-RED边缘计算网关通过OPC UA把数据读出来报警判断和通知分发全部放在网关侧完成。它不写PLC不改WinCC甚至WinCC重启、画面操作都跟它没关系。项目标题里那句“不改WinCC和PLC加报警功能”并不是噱头。Node-RED作为一个开源的低代码流式编程工具对工控人来说门槛不算高。它跑在一台小主机上可以是工控机、瘦客户机、树莓派甚至虚拟机通过OPC UA协议和西门子S7系列PLC通讯也支持Modbus、三菱、欧姆龙等各类协议把采集到的数据在本地完成滤波、判断、锁存然后通过MQTT、HTTP、邮件、企业微信机器人等方式把报警送出去。这套方案的核心思路是让“报警”这件事从控制系统里解耦出来。原来的PLC和WinCC继续干它们的老本行——控制逻辑、工艺画面、历史归档报警检测变成一种“旁挂”能力由边缘网关独立承载。谁也不会干扰谁谁也不用停机配合谁。我最早接触这个思路是接手一个改造项目现场是S7-300配WinCC 7.4要加三个模拟量高位报警和一个设备状态监控但客户的生产计划排得很满停机窗口只有到一个多月以后才有。当时我就用一台旧工控机跑了Node-RED从PLC侧把数据读出来做报警推送一周不到就上线试运行完全没碰过原系统。这个经历让我确信这套思路在很多存量项目里都值得复制。2. 先搞明白数据从哪来往哪去2.1 数据采集链路的确定要在不动PLC程序的前提下拿到数据最常见也最稳的路径就是通过OPC UA服务器走西门子S7协议或者通过S7-300/400的以太网口直接读取。实际情况里又有两种接法方案接法优点缺点ANode-RED通过S7协议直接读PLC不依赖额外软件接法最简节点库较杂需注意通讯负载对S7-1200/1500需要设“允许来自远程对象的PUT/GET通讯访问”可能被安全策略卡住BNode-RED通过OPC UA读WinCC或独立OPC UA服务器数据点管理集中WinCC自带OPC UA服务从V7.2起支持依赖WinCC服务的稳定性和授权WinCC侧OPC UA服务需要单独配置部分版本有连接数限制我在大多数项目里推荐方案B——利用WinCC自带的OPC UA服务器功能。原因很简单WinCC本来就要连接PLC数据点、变量名都已经配置好了直接在WinCC的OPC UA配置里把需要暴露的变量放出来Node-RED这边只需要按变量节点ID去订阅就行。这样连PLC的变量表都不用翻。但如果你用的是S7-1200/1500这类自带OPC UA服务器的PLC那就更简单了。PLC本身就是OPC UA ServerNode-RED直接去连PLC的IP地址加端口4840不需要WinCC参与。这种方式我一般推荐给“现场没有WinCC、只有触摸屏”的场景——同样能实现“不动HMI、不改PLC”的报警旁挂。2.2 报警消息最终送到哪采集侧定了发送侧也得先想清楚。报警不止是“屏幕上弹一条消息”不同场景对送达渠道的要求完全不一样操作工在车间现场需要现场声光报警器动作这类可以走Node-RED输出Modbus TCP或直接驱动一个继电器模块维护人员在办公室桌面弹窗、浏览器看板最方便走Node-RED的HTTP接口推送页面或者WebSocket实时刷新管理层不在现场需要微信、钉钉、邮件推送Node-RED自带丰富的通知节点或者通过HTTP方式调用企业微信机器人、钉钉自定义机器人系统间集成把报警写入另一个系统的数据库、通过MQTT转发给上层平台Node-RED的MQTT节点可以轻松接入EMQX、VerneMQ等消息中间件。这个“先定出口再定入口”的顺序很重要。很多人一上来就急着连PLC读数据结果数据读上来了发给谁、用什么发还没想好流写到一半就卡住了。我建议第一步先梳理一张表报警事件名称、触发条件、恢复条件、通知对象、通知方式、是否记录历史。这张表就是你后面写流的需求说明书。3. Node-RED边缘网关的落地硬件与运行环境3.1 硬件的选择逻辑边缘计算网关听起来高大上落到硬件上其实就是一个“能联网、能跑Linux、能稳定长时间运行”的小主机。我列一下几个层次的选项大家按项目预算和对可靠性的要求来选硬件方案参考配置适用场景注意点工控机/瘦客户机4核CPU, 8GB内存, 2个千兆网口, SSD生产现场正式部署选无风扇机型注意DC供电稳定性树莓派4B/54核ARM, 4~8GB内存, 千兆网口测试验证、非关键场景SD卡容易损坏建议用SSD启动软路由盒子/x86小主机N100/J4125级别, 8GB内存性价比高的现场方案要选支持长时间运行的工业级电源Docker部署在现有工控机上复用现场服务器资源不适合单独加硬件的场合注意资源隔离避免影响WinCC所在服务器性能我做现场项目时功耗、散热、供电稳定这三个因素往往比绝对性能更重要。Node-RED单体运行所需资源并不高一般设备跑几十个流CPU占用率也就百分之几到十几。真正吃资源的是历史数据存储和看板渲染这一块我通常会把数据转发给独立的时序数据库主节点只保留队列缓存避免因为自身故障丢数据。3.2 运行环境的安装与基础加固系统层面我用Debian或者Ubuntu Server的占比最多也有用Windows宿主机跑Docker的——如果现场IT团队只会管Windows用Windows也未尝不可。但你要是问我的个人倾向纯Linux Docker Compose是最省心的组合升级、备份、迁移都方便。安装Node-RED在Linux下只需要一行命令# 安装Node-RED官方脚本主要用于本地/边缘节点 npm install -g --unsafe-perm node-red如果用Docker部署我更推荐这样跑# 创建持久化目录 mkdir -p /opt/node-red/data # 启动容器映射1880端口用于编辑器映射1881端口用于HTTP API接收 docker run -d \ --name node-red \ --restartalways \ -p 1880:1880 \ -p 1881:1881 \ -v /opt/node-red/data:/data \ -e TZAsia/Shanghai \ nodered/node-red:latest装完第一件事不是急着连PLC而是先把两件事做了打开设置文件 settings.js修改 adminAuth 配置为编辑器设置用户名密码。Node-RED默认不设密码只要网络可达任何人都能打开1880端口改你的流这在工厂内网里是高危漏洞。设置httpNodeRoot和路径安全。如果HTTP接口要对外提供数据建议放在单独的端口、子路径下并在前面加一层反向代理做访问控制。我在现场见过不少工程师在调试机上把Node-RED跑起来以后就长期不设密码放在那里后面被不知情的人改乱了流排查起来非常痛苦。这个坑一定要提前避开。4. OPC UA接入的几种节点选型与关键配置4.1 节点库选择Node-RED连OPC UA常用的是node-red-contrib-opcua这个节点包。它在工业场景里算是社区活跃度最高、维护比较频繁的了。安装方式# 在Node-RED安装目录下执行或者通过编辑器右上角菜单的“管理面板”搜索安装 npm install node-red-contrib-opcua除了OPC UA如果你走S7协议直连西门子PLC也有一个很关键的节点node-red-contrib-s7是老牌的S7通讯节点支持S7-200/300/400/1200/1500但S7-1200/1500需要PLC侧打开“允许来自远程对象的PUT/GET通讯访问”。这个设置对很多安全要求高的项目不开放所以我在大多数场景下还是优先OPC UA。4.2 OPC UA Endpoint 的填写细节说一个我见过最多人填错的地方。在node-red-contrib-opcua的Server节点里Endpoint URL大多数人直接填opc.tcp://192.168.0.10:4840但实际连接时经常报BadCertificateUntrusted或者BadSecurityModeRejected。原因一般是安全策略不匹配。西门子PLC侧的OPC UA服务器默认的安全策略是Basic256Sha256签名加密而Node-RED端默认会用None来尝试连接。解决办法是在节点的 Security Policy 下拉框里选Basic256Sha256并设置对应的Security Mode如果是连接WinCC的OPC UA服务器还要注意WinCC侧配置的用户名密码认证如果开了也要一并填进去。配置项建议取值说明Endpoint URLopc.tcp://IP:4840端口以实际服务器为准Security PolicyBasic256Sha256兼容S7-1500默认策略Security ModeSign and EncryptWinCC/R uw rz大多支持Username / Password按服务器设置如开启用户认证则必须填连接超时10~15秒不要设太短PLC重启后会恢复重连4.3 变量节点ID的获取方式这一步是新手最容易卡住的地方OPC UA的节点ID不是简单填个“DB1.0”就能读它的格式是类似ns2;sDeviceSet.Device1.Temperature或者ns3;s“DB1”.TagName这种命名空间加标识符的组合。我的建议是先用Node-RED OPC UA节点里的Browse功能去浏览一下服务器地址空间。具体操作是在opcua-client节点的配置界面里先配置好Server连接然后点开Browser页签就能看到服务器上可访问的节点树。从树里找到你要读的量右键复制NodeId或者直接用Browse测通以后再填写到订阅列表里。这个方法比翻手册猜ID要快得多。如果把PLC侧配置了符号名西门子S7-1500的OPC UA节点结构里往往能直接看到带设备名的变量非常直观。如果用WinCC注意WinCC的OPC UA服务里暴露的变量路径跟WinCC内部变量管理器的结构有关最好在WinCC侧先建一个专门的“报警数据导出”变量组把需要报警判断的量集中挂进去后续维护会省很多事。5. 一步步搭出“报警判断去抖锁存通知”完整流5.1 流的整体骨架这是一个我实际项目里用过的报警流结构思路非常通用。Node-RED里用OpC UA节点订阅过来的数据会经过下面这几个环节OPC UA数据流 ↓ 功能函数处理状态解析、报警条件判断 ↓ 去抖与锁存逻辑 ↓ 报警事件分发新报警、恢复、持续 ↓ 通知输出MQTT / HTTP / 邮件 / 微信5.2 报警条件判断的Function节点新建一个Function节点把每个变量的报警上下限、报警级别做一张配置表类似下面这样变量单位报警低限报警高限恢复低限通知级别空压机温度℃无8575高冷却水压力MPa0.15无0.25高料位%209025/85中注意“报警低限/高限”和“恢复低限/恢复高限”并不相同这就是上面提到过的报警回差死区。如果报警值和恢复值设成同一个数现场信号在临界点来回抖动时系统就会反复触发“报警-恢复-报警”不仅烦人还会造成通知轰炸。所以好的报警逻辑一定要带回差。Function节点里写的核心逻辑大致是这样// 假设msg.payload为当前读取到的数据包含多个属性值 const temp msg.payload.CompressorTemp; let alarmState false; let alarmDesc ; // 高温报警85度触发75度恢复这里用lastTemp做状态记忆 if (context.get(tempAlarm) true) { // 处于报警中检查是否恢复 if (temp 75) { context.set(tempAlarm, false); alarmState false; alarmDesc 空压机温度已恢复; } else { alarmState true; alarmDesc 空压机温度高报警持续中; } } else { // 正常状态检查是否触发 if (temp 85) { context.set(tempAlarm, true); alarmState true; alarmDesc 空压机温度高报警触发; } } // 组合成报警事件 if (alarmState || alarmDesc.indexOf(已恢复) 0) { msg.payload { event: alarmState ? alarm : recover, tag: CompressorTemp, value: temp, desc: alarmDesc, time: new Date().toISOString() }; return msg; } else { return null; // 没有事件产生丢弃 }这个结构就是报警状态机的最小实现用context记住每个报警变量当前是否处于报警态输入一个新值后先判是“报警中”还是“正常态”再决定是触发新报警、维持报警还是发出恢复事件。这样比每次拿到数据都粗暴比较大小要可靠得多。5.3 去抖与防抖的必要性工业现场的模拟量信号尤其是温度、压力、液位这些天然带有噪声。哪怕用OPC UA接到了数据也经常出现某个扫描周期瞬时值越限、下个周期又恢复正常的情况。如果不做滤波一天能推几百条假报警出去没人受得了。我习惯在OPC UA订阅和报警判断之间加一个滑动窗口均值滤波或者在报警判断之后加一个持续时间确认。比如温度连续3个采样周期每周期1秒都超过85℃才确认报警恢复也一样连续3个周期都低于75℃才发“恢复”事件。用Function节点实现“连续确认”很简单记录一个类似以下结构的计数器// 初始为0越限1正常则清零 let cnt context.get(cnt) || 0; if (msg.payload.CompressorTemp 85) { cnt cnt 1; if (cnt 3) { cnt 0; // 确认报警后交给状态机处理 msg.payload { event: preAlarm, tag: CompressorTemp }; return msg; } } return null;这个去抖环节看着不起眼但对报警质量的影响是决定性的。我在很多项目里把报警推送从“一天几十条无效推送”降到“一天几条有效推送”靠的就是这两个小改进。5.4 将报警事件发送到通知渠道状态判断和去抖做完以后后面就是纯粹的输出部分了。我用过的组合大致有这几种MQTT转发Node-RED的mqtt out节点配置一个本地或云端的Broker地址上层系统订阅Topic是一种非常适合系统间异步解耦的方式。Topic建议按层级规划如factory/site1/line2/alarm。企业微信/钉钉机器人用HTTP Request节点POST到机器人Webhook地址注意企业微信有每分钟20条的频率限制如果报警量大要做合并发送把多条报警拼成一条消息发。邮件发送配置SMTP服务后用email节点发出这个适合不需要实时提醒的日报汇总。HTTP API给第三方系统提供一个POST接口Node-RED作为HTTP Server收到报警事件转推给别的平台。提醒一句通知渠道的失败要兜底。邮件发失败、机器人Webhook失效、网络抖动导致MQTT断开这些情况在工业现场一定会遇到。我通常在消息输出前加一个delay节点的重试机制或者在通知下游加一个失败分支把失败的消息重新放进一个队列后续错峰再发避免报警静默丢失。6. 历史数据的就地留存与轻量看板6.1 为什么边缘节点要自带历史很多人在设计报警系统时只关注“当前的报警推出去”忽略了“历史报警要可追溯”这个硬需求。尤其是现场出现设备事故后业主第一个问题一定是刚才报警了吗报警信息在哪当时的工艺参数是多少如果把所有历史都只放在WinCC或第三方平台里那么“旁路报警”方案就失去了意义——既然还是要靠WinCC查历史那不如直接在WinCC里写报警脚本。所以边缘网关一定要自带一套轻量级的数据留存方案。常用做法是Node-RED把报警事件和周期采样数据写入SQLite或者InfluxDB。这两个都够轻跑在边缘主机上毫无压力数据库类型适合的场景Node-RED节点SQLite关系型报警事件表、操作日志表node-red-node-sqliteInfluxDB时序型模拟量趋势、长时间历史曲线influxdata/influxdb-client我一般把报警事件存SQLite——每条记录有事件时间、Tag名、报警值、描述、是否恢复、恢复时间这个结构用关系型查起来最顺手把周期采样的模拟量存InfluxDB——测点、时间、数值的模型天然匹配时序库查询趋势曲线也简单。6.2 一张免开发的报警查询看板数据有了给人看还得有界面。很多团队一想到看板就以为要开发Web前端其实Node-RED的HTTP API配合一小段HTML就够用了。最简单的做法是Node-RED里建一个HTTP In节点监听GET /alarm/list在Function节点里执行SQLite查询把最近N条报警查出来用template节点拼一个HTML表格页面返回。这段页面代码不需要复杂框架纯原生HTML简单CSS就能实现一个支持按时间筛选、按报警级别筛选的列表页面。如果还想看趋势ECharts的折线图组件也可以直接在前端页面里引入后端用Node-RED提供JSON数据接口。我做过一个项目现场维护人员就是用这样一个页面配合手机浏览器直接打开网关地址随时能看上一天的报警记录和参数曲线连专门的App都省了。对于很多中小型产线这就是成本最低的“报警管理系统”。7. 部署上线时的几个边界问题与排查经验7.1 网关IP规划与防火墙规则边缘网关要接入现场控制网络第一件事就是网络规划。我建议网关至少配两个网口一个口接PLC/控制网一个口接办公网或者上层数据网。控制网段和办公网段物理隔离,网关做数据单向或者按需双向转发这样即使办公网里的电脑中毒也不至于直接打到PLC上。如果现场只有一张网也要在网关上用防火墙规则限制访问来源。Ubuntu上UFW开启后只放行必要端口# 开放Node-RED编辑器端口只给内网管理IP sudo ufw allow from 192.168.1.100 to any port 1880 proto tcp # 开放OPC UA客户端出站连接S7-1500默认4840 sudo ufw allow out to 192.168.0.10 port 4840 proto tcp7.2 无线/4G场景下的断线重连有些项目把边缘网关部署在无固定IP的站点通过4G/5G上云。这个时候OPC UA、MQTT这类TCP长连接都需要重点考虑“连接断了能不能自动恢复”。Node-RED自带的一些节点如MQTT Out节点本身有自动重连机制但要设置好Keep Alive周期和Clean Session。OPC UA的客户端节点也支持断线重连但我在实际测试中发现如果网线被拔掉超过几分钟OPC UA通道可能需要手动重启才能恢复。所以有个技巧在Node-RED里加一个定时器流每隔几十秒ping一次PLC地址一旦ping不通就触发一条通知同时通过Node-RED的API重新部署OPC UA相关流程强制重新建立连接。7.3 网关自身的“看门狗”边缘网关承担了报警推送职责它自己反而不能死掉。所以我通常会做三层防护系统级看门狗systemd里设置服务崩溃自动重启容器级守护Docker的--restartalways保证容器异常退出后自动拉起业务级心跳Node-RED里定时发一条心跳消息到MQTT Broker或者企业微信群里如果上层的监控平台连续几个周期收不到心跳就说明边缘网关挂了自动通知IT/OT管理员。后两点很多人容易忽略。尤其第三点——报警系统的故障要能被感知。网关自己断了报警全都不发现场还以为一切正常这是最危险的情况。7.4 最麻烦的一类问题OPC UA连接“时而能连时而不能连”我在排查这类问题时最终定位到的原因五花八门这里把最常遇到的几种列出来排查方向常见原因解决办法安全策略Endpoint和安全模式不匹配用UA Expert这类工具先连一次查看服务器支持的安全策略列表证书信任客户端证书不被服务器信任在PLC或WinCC侧导入Node-RED生成的证书/指纹连接数限制WinCC的OPC UA服务有Session数上限检查服务器端配置限制单Session订阅量网络MTU大包被交换机分片丢弃把扫描周期调长单次采集的点数不要太多防火墙状态端口被办公网防火墙拦截在网关上tcpdump抓包确认连接建立情况遇到OPC UA连接问题不要直接猜先在网关上抓包# 抓取到PLC 4840端口的包确认TLS握手是否完成 sudo tcpdump -i eth0 host 192.168.0.10 and port 4840 -w opcua.pcap再用Wireshark打开pcap文件看TLS层有没有报错、Server侧的Hello消息有没有返回基本就能定位是策略还是网络层的问题了。8. 报警流上线后我建议补充的几个增强功能基础报警跑通以后如果你还有余力下面这几个增强方向是实际使用效果最好的按性价比排序第一个是报警等级分级与值班规则。把报警分成“提示”“一般”“严重”三级提示级只在看板里显示不发通知一般级推送给当班人员严重级在一般级之外还要额外电话或短信通知值班经理。实现上不难报警判断时带上等级信息输出端根据等级分流到不同通知节点就行。第二个是报警汇总日报。用一个Cron定时器比如每天早上8点查询前一天所有报警事件生成一张汇总表发到管理群或者邮箱。这个功能上线后很多管理者反而觉得比实时报警更有价值它能让管理层对设备运行状态有一个全景式的判断。第三个是报警与工单系统的对接。如果现场运维已经用了工单系统Node-RED可以把报警事件作为自动创建工单的触发源通过HTTP API调用工单系统的创建接口。这样一来报警不再只是“一条消息”而是进入了实际处理流转的闭环里。这三个功能的实现都在Node-RED的流层面完成不需要动PLC和WinCC。这也是边缘网关方案最有魅力的地方——系统的能力扩展从原来的“改上位机程序”变成了“加流、接API”工程效率完全不在一个量级。9. 回看这个方案的得失说几句实在话折腾了这么多项目我对“不改WinCC和PLC加报警功能”这套做法最大的体会是它把“约束”变成了“设计边界”。因为不能动老系统你被迫把所有新能力全部外置这反而让系统边界越来越清晰——控制归控制信息归信息后期的维护责任划分也省了很多扯皮。每个项目能不能用这套方案我建议先自评三个条件一是现场有没有可用的OPC UA接口或者至少是支持S7协议的以太网连接二是能否接受报警逻辑放在边缘侧而不是PLC里三是有没有人能维护这台边缘网关。三个条件如果都满足那这个方案几乎可以闭眼选。至于那些问我“PLC和WinCC迟早要换代升级这套网关到时候怎么办”的人我的回答是网关本身就是中立的PLC换成别的品牌、WinCC升级成别的SCADA只要OPC UA这个标准还在Node-RED这边的流只需要改一下服务器地址和节点ID就能接着用。这份“可迁移性”是我当初选OPC UA而不是走私有协议的根本原因。最后再分享一个纯个人经验真到现场调试那几天不要盯着Node-RED编辑器里那条绿线发呆要盯的是PLC扫描周期里那几十毫秒的变化。你把采样周期调到1秒PLC侧基本无感但如果把OPC UA的采样周期调到100毫秒以下又订阅了几百个节点老款PLC的通讯负载可能会明显升高这时候手摸PLC的CPU模块面板温度都能感觉出来。工业现场的“温柔”就在这些细节里——数据能用就行别把它榨干。
返回列表