modbus-serial
如果你需要使用JavaScript来操作一台RS458的设备,那么你一定不能错过这个库 modbus-serial。
安装和使用
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线路。
示例
读取和写入
// 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);
}
读取多个从站
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 服务
// 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,如果你之前是前端,并且想接触硬件,就学习一下它吧。