如何通过OPC UA读取PLC信号?node-opcua环境下的实操指导请求
如何用node-opcua读取PLC数据
嘿,作为IoT和OPC UA领域的新手,能自己部署node-opcua服务器、跟着教程搭好客户端和服务器已经超棒了!不过这里你可能混淆了一个核心逻辑:你自己用node-opcua搭建的服务器,并不是直接用来连接PLC的——它是一个独立的OPC UA节点;要读取PLC信号,咱们得用node-opcua客户端去连接PLC侧的OPC UA服务器(或者网关提供的OPC UA服务)。下面一步步给你讲清楚:
第一步:确认PLC的OPC UA接入方式
首先得搞清楚你的PLC怎么提供OPC UA服务:
- 原生支持OPC UA的PLC:比如西门子S7-1200/1500、AB CompactLogix、三菱FX5U这类现代PLC,本身自带OPC UA服务器功能。你需要在PLC的编程软件(比如TIA Portal、Studio 5000)里开启这个功能,配置好端点URL(格式一般是
opc.tcp://<PLC_IP>:4840)、安全策略(比如None、Sign)和用户权限。 - 不支持原生OPC UA的PLC:就得用OPC UA网关(比如KEPServerEX、Matrikon网关),把PLC的原生协议(比如Modbus RTU/TCP、S7协议)转换成OPC UA协议。网关会模拟一个OPC UA服务器,你只需要配置网关连接PLC的参数,就能得到可连接的OPC UA端点。
第二步:用node-opcua客户端连接PLC的OPC UA服务器
这是核心步骤,直接上代码示例(你可以直接修改后运行):
const opcua = require("node-opcua"); // 替换成你的PLC/网关的OPC UA端点URL const endpointUrl = "opc.tcp://192.168.1.100:4840"; // 创建客户端实例,安全配置要和PLC/网关的设置匹配 const client = opcua.OPCUAClient.create({ securityMode: opcua.MessageSecurityMode.None, // 可选:None/Sign/SignAndEncrypt securityPolicy: opcua.SecurityPolicy.None // 可选:None/Basic128Rsa15等 }); async function readPLCData() { try { // 1. 连接到PLC的OPC UA服务器 await client.connect(endpointUrl); console.log("✅ 成功连接到PLC的OPC UA服务器"); // 2. 创建会话(如果PLC需要认证,这里要加用户名密码) const session = await client.createSession(); // 如果需要用户名密码,改成下面这样: // const session = await client.createSession({ userName: "admin", password: "123456" }); console.log("✅ 会话创建成功"); // 3. 读取指定变量的值(关键:你需要知道变量的NodeId) // 比如西门子PLC中DB1.DBW0的NodeId可能是「ns=4;s=DB1.DBW0」,不同PLC格式不同 const targetNodeId = "ns=4;s=DB1.DBW0"; const dataValue = await session.read({ nodeId: targetNodeId, attributeId: opcua.AttributeIds.Value // 指定读取变量的「值」属性 }); console.log("📊 读取到的PLC数据:", dataValue.value.value); // 4. 关闭会话和连接 await session.close(); await client.disconnect(); console.log("🔌 连接已关闭"); } catch (err) { console.error("❌ 读取数据出错:", err.message); } } // 执行读取函数 readPLCData();
第三步:找到PLC变量的NodeId
这是新手最容易卡壳的地方——怎么知道要读取的变量对应的NodeId?给你三个实用方法:
- 方法1:从PLC编程软件导出:大部分PLC编程软件可以导出变量列表,里面会包含每个变量对应的OPC UA NodeId,直接复制用就行。
- 方法2:用OPC UA可视化工具浏览:比如免费的UA Expert软件,连接到PLC的OPC UA服务器后,可以可视化浏览整个节点树,找到你要的变量后直接复制NodeId,非常直观。
- 方法3:用node-opcua代码浏览节点:如果不想装工具,可以在会话创建成功后加一段浏览代码,遍历服务器节点找变量:
// 在session创建成功后添加这段代码 async function browseNodes(nodeId) { const browseResult = await session.browse(nodeId); console.log(`📂 节点${nodeId}的子节点:`, browseResult.references); // 递归浏览子节点,直到找到目标变量 for (const ref of browseResult.references) { if (ref.nodeClass === opcua.NodeClass.Variable) { console.log(`找到变量:${ref.browseName},NodeId:${ref.nodeId}`); } else if (ref.nodeClass === opcua.NodeClass.Object) { await browseNodes(ref.nodeId); } } } // 从根节点开始浏览 await browseNodes("RootFolder");
额外说明:你自己的node-opcua服务器能做什么?
你之前搭建的node-opcua服务器不是没用哦!它可以作为一个中间层:比如把从PLC读取到的数据做处理(过滤、聚合、转换),然后把处理后的数据暴露成新的OPC UA节点,这样其他系统(比如SCADA、IoT平台)可以直接连接你的node-opcua服务器获取数据,不用直接访问PLC,既安全又灵活。
内容的提问来源于stack exchange,提问作者ARULJOTHI PARTHIBAN




