基于纯JavaScript实现的MODBUS-RTU(串口和TCP) modbus-serial

modbus-serial

如果你需要使用JavaScript来操作一台RS458的设备,那么你一定不能错过这个库 modbus-serial

安装和使用

bash 复制代码
npm install modbus-serial

支持的功能码

功能码 函数
FC1 读取读线圈寄存器 readCoils(coil, len)
FC2 读离散输入寄存器 readDiscreteInputs(addr, arg)
FC3 读保持寄存器 readHoldingRegisters(addr, len)
FC4 读输入寄存器 readInputRegisters(addr, len)
FC5 写单个线圈寄存器 writeCoil(coil, binary)
FC6 写单个保持寄存器 writeRegister(addr, value)
FC15 写多个线圈寄存器 writeCoils(addr, valueAry)
FC16 写多个保持寄存器 writeRegisters(addr, valueAry)
FC43/14 读保持寄存器 readDeviceIdentification(id, obj)

客户端串行:

  • modbus-RTU (SerialPort):通过串行线路,需要node serialport。

  • modbus-RTU (RTUBufferedPort):通过缓冲串行线路,需要node serialport。

  • modbus-ASCII (AsciiPort):通过串行线路,需要node serialport。

客户端TCP:

  • modbus-TCP (TcpPort):通过TCP/IP线路。

  • modbus-RTU (UdpPort):通过C701服务器,商业UDP到串行桥。

  • modbus-RTU (TcpRTUBufferedPort):通过TCP/IP线路,TCP/IP串行RTU缓冲设备。

  • modbus-RTU (TelnetPort):通过Telnet服务器,TCP/IP串行桥。

服务器

  • modbus-TCP (ServerTCP):通过TCP/IP线路。

示例

读取和写入

js 复制代码
// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();

// open connection to a serial port
client.connectRTUBuffered("/dev/ttyUSB0", { baudRate: 9600 }, write);

function write() {
    client.setID(1);

    // write the values 0, 0xffff to registers starting at address 5
    // on device number 1.
    client.writeRegisters(5, [0 , 0xffff])
        .then(read);
}

function read() {
    // read the 2 registers starting at address 5
    // on device number 1.
    client.readHoldingRegisters(5, 2)
        .then(console.log);
}

读取多个从站

js 复制代码
const ModbusRTU = require("modbus-serial");
// create an empty modbus client
const client = new ModbusRTU();
// open connection to a serial port
client.connectRTUBuffered("/dev/ttyS0", { baudRate: 9600 });
// set timeout, if slave did not reply back
client.setTimeout(500);

// list of meter's id
const metersIdList = [10, 11, 12, 13, 14];

const getMetersValue = async (meters) => {
    try{
        // get value of all meters
        for(let meter of meters) {
            // output value to console
            console.log(await getMeterValue(meter));
            // wait 100ms before get another device
            await sleep(100);
	}
    } catch(e){
        // if error, handle them here (it should not)
        console.log(e)
    } finally {
        // after get all data from slave, repeat it again
        setImmediate(() => {
            getMetersValue(metersIdList);
        })
    }
}

const getMeterValue = async (id) => {
    try {
        // set ID of slave
        await client.setID(id);
        // read the 1 registers starting at address 0 (first register)
        let val =  await client.readInputRegisters(0, 1);
        // return the value
        return val.data[0];
    } catch(e){
        // if error return -1
        return -1
    }
}

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));


// start get value
getMetersValue(metersIdList);

ModbusTCP 服务

js 复制代码
// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const vector = {
    getInputRegister: function(addr, unitID) {
        // Synchronous handling
        return addr;
    },
    getHoldingRegister: function(addr, unitID, callback) {
        // Asynchronous handling (with callback)
        setTimeout(function() {
            // callback = function(err, value)
            callback(null, addr + 8000);
        }, 10);
    },
    getCoil: function(addr, unitID) {
        // Asynchronous handling (with Promises, async/await supported)
        return new Promise(function(resolve) {
            setTimeout(function() {
                resolve((addr % 2) === 0);
            }, 10);
        });
    },
    setRegister: function(addr, value, unitID) {
        // Asynchronous handling supported also here
        console.log("set register", addr, value, unitID);
        return;
    },
    setCoil: function(addr, value, unitID) {
        // Asynchronous handling supported also here
        console.log("set coil", addr, value, unitID);
        return;
    },
    readDeviceIdentification: function(addr) {
        return {
            0x00: "MyVendorName",
            0x01: "MyProductCode",
            0x02: "MyMajorMinorRevision",
            0x05: "MyModelName",
            0x97: "MyExtendedObject1",
            0xAB: "MyExtendedObject2"
        };
    }
};

// set the server to answer for modbus requests
console.log("ModbusTCP listening on modbus://0.0.0.0:8502");
const serverTCP = new ModbusRTU.ServerTCP(vector, { host: "0.0.0.0", port: 8502, debug: true, unitID: 1 });

serverTCP.on("socketError", function(err){
    // Handle socket error if needed, can be ignored
    console.error(err);
});

市面上有非常多的设备时 RS485,如果你之前是前端,并且想接触硬件,就学习一下它吧。

相关推荐
莫陌尛.10 分钟前
Java核心知识点:直接内存、CPU密集型线程池、并行流对比文档
java·开发语言
西峰u16 分钟前
Java多线程初阶完整总结|线程、锁、volatile、等待通知、常见案例
java·开发语言·jvm
集芯微电科技有限公司31 分钟前
700V/17A高频开关低导通阻GaN HEMT驱动器适用于快充,LLC,PFC功率校正
人工智能·嵌入式硬件·深度学习·神经网络·机器学习·生成对抗网络·计算机外设
夜雨声烦丿34 分钟前
从需求到页面:日期计算器应用的 ArkTS 原生实现
开发语言·javascript·华为·harmonyos
恒锐丰小瑞34 分钟前
率能SS6285M 33V/5.5A/单通道直流电机驱动IC,低待机功耗与多重保护,用于电子锁/玩具/机器人
stm32·单片机·嵌入式硬件·机器人
程序员雪球1 小时前
本地IDEA打断点debug容器
java·开发语言
老白干1 小时前
基于枚举 + 注解的 Java 数据脱敏实践(fastjson 序列化场景)
java·开发语言
半亩码田1 小时前
C#转Python第4.1篇:当 try-catch 遇上 try-except:异常处理的大不同
开发语言·python·c#
数据知道1 小时前
Java 安全审计实战:SSRF、反序列化、SpEL 注入
java·开发语言·安全·网络安全
陈年老古董1 小时前
矿物分类数据处理:缺失值填充方法详解
开发语言·python·机器学习·项目