ARTICLE DETAIL

资讯详情

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

PLC+智能网关+MQTT+Node.js构建Web SCADA实时监控系统

PLC+智能网关+MQTT+Node.js构建Web SCADA实时监控系统 1. 为什么我最终选了 PLC 智能网关 MQTT Node.js 这条路线先交代一下背景我是做产线设备集成的以前接过不少客户需求都是“要把车间里几台 PLC 的数据弄到办公室大屏上”但等到真正实施的时候问题一个接一个PLC 品牌不同、通讯协议不开放、IT 那边又不允许直接碰上位机、领导还要求“以后最好能用手机看”。坦白讲早期做这类项目我第一反应通常是组态软件 专用采集卡但后来发现这套方案在跨品牌、跨网络、轻量化展示这三个维度上非常难受。直到一次改造项目里我尝试了“PLC 工业智能网关 MQTT Node.js”的组合才算真正找到了一个比较稳妥的落地路径。这套方案的本质是用工业智能网关把 PLC 的私有协议转成标准 MQTT 报文再用 Node.js 做一个轻量级的 Web SCADA 服务把实时数据推到浏览器端。它解决的问题很直接一是破除 PLC 品牌壁垒二是让数据能穿越车间网络到办公网甚至公网三是把 HMI 的展示从工控屏扩展到任意浏览器和手机。适合谁来参考如果你是做设备自动化的工程师、软件开发出身但想切入工业数据采集的开发者或者正在做 PLC 毕业设计且想加一个物联网上报功能的学生这篇文章应该能帮你少走不少弯路。我当时踩坑最深的地方恰恰是最容易被人忽略的“网络拓扑设计”和“QoS 等级选择”。在项目实施到一半的时候因为 MQTT 的 QoS 设置不当现场出现过数据丢包而另一台设备又因为主题订阅层级过深导致频繁断连。这些经验如果只看官方文档根本体会不到。所以这篇文章不是单纯罗列步骤而是把我真实调试过程中遇到的坑、验证过的参数、以及最终能稳定跑上几个月的配置都整理出来你可以直接当成一份实施笔记来用。2. 项目整体架构与关键技术选型2.1 整套数据链路是怎么走通的在动手接线和写代码之前我建议你先在脑子里把数据流向画清楚。我最后采用的链路是这样的PLC现场设备层→ 工业智能网关协议转换层→ MQTT Broker消息中枢层→ Node.js Web 服务应用逻辑层→ 浏览器/手机大屏展示层每一层解决的事情都不一样。PLC 负责把设备状态、温度、压力、电流这些数据写到指定的寄存器地址里它本身不关心数据要发到哪里。智能网关负责去读这些寄存器然后把数值打包成 JSON 格式通过 MQTT 协议发布到 Broker 上。Broker 就相当于一个邮局它不生产数据只负责转发。Node.js 服务一方面订阅 Broker 上的主题拿到实时数据另一方面通过 WebSocket 把数据推送给前端页面顺便还要把历史数据存进数据库。这个架构最巧妙的地方在于PLC 和 Web 服务之间是彻底解耦的。PLC 不用关心 Web 服务用的是什么语言、部署在哪台机器上Web 服务也不用关心 PLC 是什么品牌、寄存器怎么映射。中间只要遵守 MQTT 协议大家就能对话。比如现场有一台西门子 S7-200 SMART网关走 PPI 协议去读数据另一台汇川 PLC网关走 Modbus TCP 去读数据但在 Node.js 服务看来它们都只是两个不同的 MQTT 主题处理逻辑完全一样。2.2 为什么是“工业智能网关”而不是“DTU”或者“自研采集器”很多初学者会纠结一个问题既然 Node.js 都能写 Modbus TCP 客户端那我直接用电脑插网线连 PLC 不就行了理论上确实可以但实际现场很难这么干。首先是 PLC 通讯协议的兼容性问题西门子的 PPI、三菱的 FX 编程口、OMRON 的 HostLink这些私有协议你在 Node.js 里自己实现每一个都要花不少功夫而且协议文档不一定好找。其次是电气隔离问题工业现场电机启停、变频器干扰浪涌和共模电压很容易把普通串口或者网口打坏工业智能网关在硬件设计上做了隔离和防护比普通工控机稳定得多。至于 DTU数据传输单元它主要面向纯串口透传和 GPRS/4G 传输场景协议转换能力很弱。智能网关和 DTU 最大的区别在于智能网关本身就是一个边缘计算节点它能在本地完成协议解析、数据过滤、甚至边缘报警判断而不是把所有原始字节流都丢到云端。选择网关的时候你要重点看三个参数支持的 PLC 协议种类、是否支持 MQTT 客户端、以及是否有 Web 配置界面。我实际用的是一款支持西门子、三菱、汇川、Modbus 等常见协议的网关配置界面里直接填 MQTT Broker 的 IP、端口、用户名密码和发布主题即可上手成本很低。2.3 为什么 MQTT 适合工业数据上报而不是 HTTP 轮询我之前也考虑过用 HTTP POST 定期上报数据比如每秒把 PLC 数据 POST 到 Node.js 接口。但仔细想想这个方案有几个硬伤首先是实时性差PLC 的数据变化是毫秒级的HTTP 轮询要么频率高导致服务器压力大要么频率低导致数据滞后明显。其次是网络开销大HTTP 的 Header 本身就有几百字节每次上报都是一次完整的 TCP 连接在车间这类大量设备并发上报的场景下很容易把带宽和服务器连接数打满。MQTT 基于发布/订阅模式客户端和 Broker 之间保持一条长连接报文头部可以压缩到 2 字节左右而且 Broker 自带主题过滤能力每个客户端只订阅自己关心的主题不需要服务器为每台设备建立独立连接。另外 MQTT 的 QoS 机制提供了消息可靠性保障QoS 0 是尽力而为QoS 1 保证至少送达一次QoS 2 保证恰好送达一次。对工业数据来说QoS 1 通常是最合适的既不会像 QoS 0 那样可能丢消息也不会像 QoS 2 那样因为握手太多导致吞吐量下降。至于为什么最后用 Node.js 而不用 Java 或者 C#纯粹是团队技术栈和开发效率的考虑。Web SCADA 的核心诉求是实时展示和灵活定制界面Node.js 的异步非阻塞模型天然适合处理大量 WebSocket 长连接而且前端用 Vue 或 React 的话前后端都是 JavaScript沟通成本低。3. 工业智能网关配置从接线到 MQTT 联通的完整过程3.1 硬件连接和通讯参数设置网关到手之后第一步不是马上打开配置软件而是先把线接对。以我常用的某款网关为例它有 2 个串口和 2 个网口其中串口 COM1 支持 RS485/RS232 切换。接西门子 S7-200 SMART 的时候我用的是 RS485 口三根线A 接 3 号端子、B 接 8 号端子、GND 接公共地这里最容易犯的错就是 A/B 接反导致通讯超时而且奇怪的是仪表上会有微弱的数据灯闪容易误导你以为是程序问题。如果接反了把 A/B 对调一下就能解决。通讯参数方面PLC 的波特率、数据位、校验位、停止位必须和网关的串口参数完全一致。西门子 S7-200 SMART 默认是 96008 数据位偶校验1 停止位。如果改了 PLC 的通讯参数网关这边也要跟着改。我当时遇到过一台老设备PLC 程序和组态软件都是 19200 波特率但网关默认配置是 9600结果轮询超时。这个参数对齐的问题是最隐蔽的坑一定要先确认 PLC 侧的通信设置再填网关的参数。3.2 在网关里配置 MQTT 客户端网关的 MQTT 配置页面通常分为几个部分Broker 地址与端口、Client ID、用户名密码、发布主题、QoS 和上报周期。我建议 Broker 地址先填内网 IP因为调试阶段不需要考虑跨网段和域名 DNS 的问题。端口默认 1883如果你的 Broker 开了 TLS 就要换 8883同时在网关里开启 TLS 证书验证。Client ID 一定要保证唯一性。我当时犯过一个低级错误两台网关用了相同的 Client ID 去连同一个 Broker结果就是两台设备互相踢下线现象是网关指示灯一会亮一会灭日志里频繁报“Connection lost”。后来才想起来 MQTT 协议中 Broker 会强制断开相同 Client ID 的旧连接。正确的做法是用网关的 MAC 地址或者设备序列号作为 Client ID。发布主题我习惯按照设备层级来组织比如factory/line1/plc1/status主题里带上车间、产线、设备编号这样在 Node.js 端做权限管理和数据分流非常方便。如果你有多台 PLC 要采集网关一般支持在采集点表里给每个变量指定单独的“上报标识符”最终生成的 JSON 消息里会带上设备名和值。这里要注意不同品牌的网关配置方式差异挺大的有的叫“采集点表”有的叫“数据字典”核心原理其实都一样把 PLC 寄存器地址映射到一个有意义的变量名上。下面是我在网关里配置的典型参数可以直接拿来参考配置项推荐值说明MQTT Broker 地址192.168.1.100内网调试阶段用 IPMQTT Broker 端口1883未启用 TLS 时使用Client IDGW_MAC_001A2B3C保证全局唯一用户名/密码scada_user/xxxxBroker 侧创建发布主题factory/line1/plc1/data可按车间/产线划分QoS1至少一次上报周期1000ms实时性要求高可设 500ms3.3 用 MQTT 客户端工具验证数据是否发布成功网关配置完之后不要急着写 Node.js 代码先用一个现成的 MQTT 客户端工具订阅一下主题确认数据已经正确到达 Broker。我平时用得最多的是 MQTT Explorer 和 MQTT X 这两个工具前者适合图形化查看主题树和历史消息后者支持脚本模拟发布订阅调试起来更灵活。打开 MQTT Explorer填上 Broker 地址和端口如果 Broker 设置了鉴权就填用户名密码然后点击连接。连接成功后找到你网关发布的那个主题展开就能看到实时数据。正常的 JSON 消息长这样{ deviceId: PLC1, timestamp: 1712652345012, values: { temperature: 36.5, pressure: 0.68, runningSpeed: 1200, alarmCode: 0 } }看到有规律的 JSON 数据刷出来说明整个链路已经通了接下来才进入 Node.js 服务端的开发。如果在 MQTT Explorer 里订阅不到数据先查三件事网关上的采集点表是否配置正确有没有读到 PLC 的值网关到 Broker 的网络是否通在网关页面看连接状态Broker 的用户名密码是否验证通过。大概率是这三个原因之一。4. MQTT Broker 的部署与调优我在 CentOS 7.9 上的实测4.1 为什么选 EMQX 而不是 MosquittoMQTT Broker 的选择上我用过 Mosquitto也用过 EMQX最后长期稳定跑的是 EMQX。Mosquitto 非常轻量适合资源受限的单机场景和教学演示但到了生产环境它的功能就比较受限了没有内置的 Web 管理界面鉴权配置要手动改配置文件集群能力也比较弱。EMQX 是一个基于 Erlang/OTP 开发的高性能 MQTT Broker支持百万级并发连接自带 Dashboard 管理界面还能通过插件扩展各种认证方式最重要的是它对 WebSocket 接入支持得非常好这正好能配合后端的 Web SCADA 需求。我部署 EMQX 用的是一台 CentOS 7.9 服务器4 核 8G 配置跑了几十台网关设备CPU 占用率一直很低。安装方式我选了 RPM 包离线安装因为现场服务器有时候不具备外网访问条件。去 EMQX 官网下载对应 CentOS 7 版本的 RPM 包然后用rpm -ivh安装即可。装完启动服务systemctl start emqx systemctl enable emqx启动后打开浏览器访问http://服务器IP:18083默认用户名是admin密码也是admin登录后第一件事是改密码。Dashboard 上能看到当前连接数、订阅数、消息流入流出速率这些数据对排查问题非常有价值。4.2 鉴权配置别把自己的数据裸奔在网络上我见过不少项目直接把 MQTT Broker 暴露在局域网里不设任何密码图省事。这在隔离的车间网络里问题不大但如果你的链路要经过办公网甚至公网就非常危险了。别人只要扫到 1883 端口就能用任意客户端订阅你的主题整个产线的运行数据等于直接公开了。推荐做法是开启 EMQX 的“用户名密码”认证同时配合 ACL 做主题级别的权限控制。用户名密码可以在 EMQX Dashboard 的“访问控制 → 认证”里配置选择 HTTP 认证或者内置数据库认证都可以。我实验室用的是内置数据库认证直接在 Dashboard 里添加用户指定允许发布的主题和允许订阅的主题。ACL 配置的规则我建议遵循最小权限原则网关用户只能发布以它对应主题为前缀的消息Web 后端用户只能订阅所有主题但发布权限可以关掉。这样即使某一个客户端被攻破攻击者能造成的影响也被限制在对应的主题范围内。4.3 消息保留与遗嘱消息两个容易忽略的特性MQTT 的 Retain保留消息机制和 Last Will遗嘱消息是我在项目里经常用到的两个高级特性但很多教程根本不会提。Retain 消息的作用是当客户端发布消息时设置 retain 标志位为 1Broker 会保存这条消息的最新值之后任何新订阅该主题的客户端都能立刻收到这条消息而不是等待下一次发布。这个特性在 Web SCADA 场景下非常实用。我做过一个需求前端页面刷新后要立刻显示 PLC 当前的最新值不能等 1 秒后网关的下一次上报。方案就是让网关在发布数据时设置 retain 标志Node.js 端订阅主题时Broker 会立刻推送最新的保留消息这样页面加载完成时数据就已经在了体验比空白等待好得多。遗嘱消息则是这样网关设备意外断线时Broker 会自动发布一条你预先设定好的离线消息。比如设置遗嘱主题为factory/line1/plc1/status遗嘱内容为{online: false}那么当网关断电或者断网时Broker 会替它宣布“我离线了”。Node.js 端订阅这个主题后就能在 Web 界面上实时显示设备在线状态。这个功能对工业监控来说太重要了操作人员需要第一时间知道某台设备通讯中断了。在 EMQX 的 Dashboard 里你可以在客户端认证配置中给每个网关用户绑定遗嘱主题和遗嘱消息如果网关本身支持配置遗嘱也可以直接在网关里设置。5. Node.js Web SCADA 后端实现实时数据订阅与历史数据落库5.1 环境准备和项目初始化Node.js 的安装有两种方式一种是用官方安装包另一种是用 nvm 做版本管理。我建议用 nvm因为不同项目有时候需要不同版本的 Node.jsnvm 可以随时切换非常方便。安装 nvm 之后执行nvm install 18.20.4 nvm use 18.20.4为什么要强调 18.20.4 这个版本我之前在 Windows 上试过 Node.js 22 的某个版本遇到过一个原生模块编译兼容性问题换成 18 LTS 版本就一切正常了。如果是生产服务器我更推荐直接安装官方的 18 LTS 安装包以 root 用户跑的话记得配置好环境变量。安装完成后执行node -v和npm -v确认版本正常再创建项目目录mkdir web-scada cd web-scada npm init -y接下来需要安装几个核心依赖包。连接 MQTT Broker 用的是mqtt这个包写 WebSocket 服务我用的是ws为了简化 HTTP 服务和静态文件托管装了express数据库选了操作简单的 SQLite通过better-sqlite3访问。这样一个最小化的项目依赖就够了不需要引入重型框架更符合边缘服务器轻量化部署的思路。npm install mqtt ws express better-sqlite35.2 编写 MQTT 订阅服务解析 PLC 上报数据在src/mqttClient.js中核心逻辑就是创建 MQTT 客户端订阅前文配置的主题然后解析 JSON 数据。关键代码如下const mqtt require(mqtt); const brokerUrl mqtt://192.168.1.100:1883; const options { clientId: web_scada_server, username: scada_user, password: your_password, clean: true, }; const client mqtt.connect(brokerUrl, options); client.on(connect, () { console.log(MQTT Broker connected.); client.subscribe(factory/line1//data, { qos: 1 }, (err) { if (err) console.error(Subscribe error:, err); }); }); client.on(message, (topic, payload) { const data JSON.parse(payload.toString()); // 这里把 data 交给实时缓存和数据库模块处理 handlePlcData(topic, data); });需要说明的是通配符的用法。主题factory/line1//data可以匹配所有中间层级不同的数据主题比如factory/line1/plc1/data和factory/line1/plc2/data。这样订阅一个模式就能收到整条产线所有 PLC 的数据非常方便。如果你想订阅多级匹配可以用#比如factory/#但订阅层级越深收到的无用消息也越多不建议在生产环境滥用。5.3 内存缓存与实时推送机制的设计数据进来之后我们不能直接全部塞给前端因为前端页面多的时候每个页面每秒收到几十条消息渲染压力会很大。合理的做法是维护一个内存中的“最新值”缓存用设备 ID 做 key。每当收到新数据就更新缓存同时通过 WebSocket 推送给所有连接的前端。缓存模块我用了一个简单的 Map 结构const latestData new Map(); function handlePlcData(topic, data) { const deviceId data.deviceId; latestData.set(deviceId, { ...data, updatedAt: Date.now(), }); // 广播给所有 WebSocket 客户端 broadcast(JSON.stringify({ type: plc_data, deviceId, data: latestData.get(deviceId), })); }WebSocket 服务用ws库实现启动一个独立端口或者和 HTTP 服务共用同一个端口都行。我这里是分了两个端口9000 端口跑 WebSocket8080 端口跑 HTTP 静态页面。这样结构更清晰排查问题的时候也方便。const WebSocket require(ws); const wss new WebSocket.Server({ port: 9000 }); function broadcast(message) { wss.clients.forEach((client) { if (client.readyState WebSocket.OPEN) { client.send(message); } }); }前端页面的逻辑很简单页面加载时建立 WebSocket 连接收到消息后更新界面上的仪表盘和实时曲线。如果你用的是 Vue 或 React可以把onmessage里的数据直接交给响应式变量界面会自动更新。我实测下来局域网环境下 WebSocket 的消息延迟在几十毫秒以内完全满足工业监控的实时性要求。5.4 历史数据写入 SQLite查询最近曲线实时数据看板只是 Web SCADA 的一半另一半是历史数据查询。没有历史曲线操作人员只能看到当前值出了问题很难回溯。SQLite 这种嵌入式数据库非常适合单机部署的轻量级场景不需要额外安装数据库服务一个文件就搞定了。建表语句如下CREATE TABLE IF NOT EXISTS plc_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT NOT NULL, tag_name TEXT NOT NULL, value REAL NOT NULL, timestamp INTEGER NOT NULL ); CREATE INDEX idx_device_time ON plc_history(device_id, timestamp);每次收到 MQTT 消息时把数据插入这张表。注意不要为了贪图方便把所有值塞进一条 JSON 字段里那样查询单个变量曲线的时候会非常痛苦。每个 tag 一行数据配合 device_id 和 timestamp 索引查某台设备某一时间段的数据非常快。插入的时候用better-sqlite3的 prepared statement批量插入可以有效提升写入效率。查询最近 1 小时温度曲线的 SQL 如下SELECT timestamp, value FROM plc_history WHERE device_id PLC1 AND tag_name temperature AND timestamp ? ORDER BY timestamp ASC;我遇到的一个实际问题是如果网关上报频率是 1 秒一次一天一个设备就会产生 86400 条记录如果设备多、tag 多SQLite 文件会快速增长。所以我会在 Node.js 服务里做一个简单的数据压缩策略数据点入库前先判断是否和上一条记录的值差异超过阈值如果完全没变化就只更新时间戳不重复插入。这样温度和压力这类缓慢变化的变量存储量能减少 70% 以上。6. Web 前端展示从零实现一个简洁的实时 SCADA 页面6.1 整体页面规划和实时连接逻辑前端页面我建议一开始不要搞太重以“能看、能查、能报警”为核心目标。我实现了一个单页应用左侧是设备列表右侧是当前设备的实时参数卡片下面是一个 Canvas 绘制的时间曲线图。所有数据都通过 WebSocket 实时推送不依赖任何轮询接口。页面加载时先连接 WebSocket连接成功后会触发后端发送一次当前缓存的全量数据快照。这一步就是靠前文提到的 MQTT Retain 机制实现的后端订阅主题时收到了保留消息把这些数据存进缓存等 WebSocket 连接建立后再主动推给前端。所以你在页面上看到的是“秒开”的数据不用等下一次上报周期。const ws new WebSocket(ws://192.168.1.100:9000); ws.onmessage (event) { const msg JSON.parse(event.data); if (msg.type plc_data) { updateDashboard(msg.deviceId, msg.data); updateChart(msg.deviceId, msg.data); } };6.2 参数卡片和状态指示参数卡片是最直观的展示方式。每张卡片显示一个 tag 名称、实时数值和单位并根据数值范围自动变色。温度超过 40 度时卡片变红压力低于设定值时变橙这是完全在前端脚本里实现的逻辑不需要额外请求后端接口。只要 PLC 数据里带有这些 tag 的值判断逻辑立刻生效。设备在线状态则来自 MQTT 遗嘱消息。后端收到遗嘱主题的离线消息时会把该设备标记为 offline并广播给前端前端页面上的设备状态灯从绿色变成灰色。这个联动效果对值班人员来说非常友好毕竟“数据不更新”有很多原因但“设备离线”是明明确确的一条故障信息。6.3 实时曲线绘制用 Canvas 而不是图表库很多初学者一上来就引入 ECharts 或者 Chart.js画出来的曲线确实好看但在嵌入式和轻量化 SCADA 场景里这些库动辄几百 KB加载速度慢而且定制不够灵活。我用原生 Canvas 实现了一个极简实时曲线核心思路是维护一个环形缓冲区保存最近 600 个数据点每次收到新数据就把旧点往左移一格然后重绘路径。function updateChart(deviceId, data) { const buffer chartBuffers.get(deviceId); buffer.push({ value: data.values.temperature, time: Date.now() }); if (buffer.length 600) buffer.shift(); // 清空画布并重绘 ctx.clearRect(0, 0, canvas.width, canvas.height); // 坐标转换和绘制逻辑省略 }如果你不会 Canvas 也没关系先用 ECharts 的 dataZoom 和实时追加模式也行。我这里选择原生 Canvas主要是为了让你知道底层原理同时也省去依赖管理。7. 常见问题与排查技巧实录7.1 MQTT 消息丢失QoS 等级和订阅时机如何调优我在现场遇到过数据偶发丢失的问题。后来排查发现网关发布消息的 QoS 设置的是 0而 Broker 在高并发场景下可能因为网络拥塞直接丢弃消息。把 QoS 改成 1 后消息基本不再丢失代价是每条消息 Broker 会多一次 PUBACK 确认整体吞吐量下降一些但工业设备数量不多时完全可接受。另外订阅时机也有讲究。如果你在网关还没上线时就启动 Node.js 服务那订阅是成功的。但如果 Node.js 服务启动在后网关已经上线很久那么订阅主题时如果消息没有设置 Retain你只能等待下一周期的上报数据。所以前文强调在网关端配置 Retain 标志就是为了解决这个问题。7.2 客户端反复掉线Client ID 冲突如何定位有一次客户反馈 Web 界面上的设备状态不断在“在线”和“离线”之间跳我远程登录 EMQX Dashboard 一看发现同一个 Client ID 有两个连接在互相踢。原因是有两块网关都是恢复出厂设置后重新配置的序列号没改Client ID 都以默认的 MAC 前 6 位生成结果后面几位一模一样。后来我在网关配置页强制改了 Client ID问题立刻解决。定位这类问题最快的方式是在 EMQX Dashboard 的“客户端”页面查看当前在线连接如果发现某个 Client ID 对应的 IP 地址不是你预期的那台设备基本就是冲突了。7.3 PLC 数据一直不变检查寄存器地址和数据类型还有一类问题很隐蔽网关能连上 PLC也能上报数据但数据值永远是 0 或者不变。这通常是寄存器地址映射错误导致的。西门子 S7-200 SMART 的 V 区地址在网关里填的是 VD100但 VD100 是 32 位浮点数你如果把它配置成 16 位整数去读读出来的值自然不对。我的经验是先在 PLC 编程软件里确认变量存储在哪个地址、是什么数据类型再到网关配置里逐一对齐。特别是浮点数还要注意字节顺序有的 PLC 是大端有的是小端配置错位后数值会非常离谱。拿一个已知值对比一下马上就能暴露问题。7.4 Node.js 服务崩溃如何做到开机自启和自动重启工业现场要求服务 7×24 小时稳定运行不能老指望人去手工重启。我建议用 PM2 来做进程守护npm install -g pm2 pm2 start src/server.js --name web-scada pm2 save pm2 startup执行完pm2 startup后会生成一条系统服务命令按提示执行一下服务器重启后 PM2 就会自动拉起 Node.js 服务。另外 PM2 自带日志管理能看到 MQTT 连接日志和 WebSocket 广播记录排查问题非常有用。8. 在真实项目里总结出的几条经验这套方案我前后实施过三四个项目从单台 PLC 的小规模演示到包含九台 PLC 的整条产线监控稳定性都还不错。唯一一次出大事是在某个高温车间网关放在配电柜里散热不良导致网关偶尔重启。后来我把网关换到了通风良好的柜壁位置同时加了浪涌保护器问题就消失了。所以硬件安装位置和现场环境往往比软件代码更容易成为隐形瓶颈。从开发成本来看从零到跑通整个链路基础版本大概需要两到三天。如果你对 Node.js 不熟前端部分可以先用 HTML 加简单 JavaScript 凑合实现核心要把 MQTT 与 WebSocket 这条数据通道打通展示层后续随时可以美化升级。还想提醒一点这个架构完全可以平移到云服务器场景。若需要外部访问把 EMQX 部署在云主机上网关通过 4G 或宽带上报到云端Node.js 服务在云端运行彻底摆脱车间物理网络的限制。我最近还在尝试给这个架构加上简单的权限系统用 JWT 给大屏访问和普通员工访问分配不同权限方向可行。后续大家可以在这个基础之上按自己的业务需求继续生长出报警推送、报表统计、甚至轻量级设备控制等功能。
返回列表