使用modbus-serial连接PLC遇PortNotOpenError,求排查方案
Modbus TCP连接报错PortNotOpenError的解决方法
问题描述
使用modbus-serial节点库通过Node.js连接PLC时,核心代码如下:
const modbusClient = new ModbusRTU(); modbusClient.connectTCP("192.168.0.10", { port: 502 }); modbusClient.setTimeout(5000); modbusClient.setID(1); modbusClient.readHoldingRegisters(2, 1) .then(function(data) { console.log(data); });
始终收到错误:
PortNotOpenError { name: 'PortNotOpenError', message: 'Port Not Open', errno: 'ECONNREFUSED' }
同一电脑上Node-RED的modbus-tcp节点可正常轮询数据,端口已确认开放。
核心问题
modbusClient.connectTCP()是异步操作,返回Promise对象。原代码没有等待连接建立完成,就直接调用readHoldingRegisters(),此时连接尚未就绪,因此抛出端口未打开的错误。Node-RED的modbus节点内部已封装了连接就绪的等待逻辑,所以可以正常工作。
修正后的代码
方法1:使用async/await(推荐)
const ModbusRTU = require("modbus-serial"); const modbusClient = new ModbusRTU(); async function fetchPLCData() { try { // 等待TCP连接建立完成 await modbusClient.connectTCP("192.168.0.10", { port: 502 }); modbusClient.setTimeout(5000); modbusClient.setID(1); // 连接就绪后读取寄存器 const data = await modbusClient.readHoldingRegisters(2, 1); console.log(data); // 按需关闭连接,若需保持长连接可省略此步骤 modbusClient.close(); } catch (err) { console.error("操作失败:", err); } } fetchPLCData();
方法2:使用Promise链式调用
const ModbusRTU = require("modbus-serial"); const modbusClient = new ModbusRTU(); modbusClient.connectTCP("192.168.0.10", { port: 502 }) .then(() => { modbusClient.setTimeout(5000); modbusClient.setID(1); // 连接就绪后执行读取操作 return modbusClient.readHoldingRegisters(2, 1); }) .then(data => { console.log(data); modbusClient.close(); }) .catch(err => { console.error("操作失败:", err); });
额外检查项(若修正后仍报错)
- 确认PLC的Modbus TCP从站地址与代码中
setID(1)的参数一致 - 检查是否存在进程占用本地端口的情况(可通过
netstat命令排查) - 确认PLC的Modbus TCP功能已启用,且寄存器地址、数量配置正确
内容的提问来源于stack exchange,提问作者user3742046
相关产品推荐
相关产品推荐

