Git Product home page Git Product logo

node-modbus-serial's Introduction

modbus-serial

A pure JavaScript implementation of MODBUS-RTU (Serial and TCP) for NodeJS.

NPM download NPM version Build Status

Modbus is a serial communications protocol, first used in 1979. Modbus is simple and robust, openly published, royalty-free and easy to deploy and maintain.

This package makes Modbus calls and serve fun and easy.



Install

npm install modbus-serial

try these options on npm install to build, if you have problems to install

--unsafe-perm --build-from-source

What can I do with this module ?

This class makes it fun and easy to communicate with electronic devices such as irrigation controllers, protocol droids and robots. It talks with devices that use a serial line (e.g. RS485, RS232). Many industrial electronic devices implement modbus. Arduino can also talk modbus and you can control your projects and robots using modbus.

Arduino libraries for modbus slave:

Arduino sketch for irrigation timer with modbus support:

Node Modbus-WebSocket bridge:

Compatibility

Version of NodeJS:

This module has not been tested on every single version of NodeJS. For best results you should stick to LTS versions, which are denoted by even major version numbers e.g. 4.x, 6.x, 8.x.

These classes are implemented:
Class Function
FC1 "Read Coil Status" readCoils(coil, len)
FC2 "Read Input Status" readDiscreteInputs(addr, arg)
FC3 "Read Holding Registers" readHoldingRegisters(addr, len)
FC4 "Read Input Registers" readInputRegisters(addr, len)
FC5 "Force Single Coil" writeCoil(coil, binary) //NOT setCoil
FC6 "Preset Single Register" writeRegister(addr, value)
FC15 "Force Multiple Coil" writeCoils(addr, valueAry)
FC16 "Preset Multiple Registers" writeRegisters(addr, valueAry)
FC43/14 "Read Device Identification" (supported ports: TCP, RTU) readDeviceIdentification(id, obj)
Client Serial:
  • modbus-RTU (SerialPort): Over serial line [require node serialport].
  • modbus-RTU (RTUBufferedPort): Over buffered serial line [require node serialport].
  • modbus-ASCII (AsciiPort): Over serial line [require node serialport].
Client TCP:
  • modbus-TCP (TcpPort): Over TCP/IP line.
  • modbus-RTU (UdpPort): Over C701 server, commercial UDP to serial bridge.
  • modbus-RTU (TcpRTUBufferedPort): Over TCP/IP line, TCP/IP serial RTU buffered device.
  • modbus-RTU (TelnetPort): Over Telnet server, TCP/IP serial bridge.
Server
  • modbus-TCP (ServerTCP): Over TCP/IP line.

Examples

Read and Write
// 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);
}

Read on multiple slaves
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);

Logger Serial
// 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 });
client.setID(1);

// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(function() {
    client.readHoldingRegisters(0, 10, function(err, data) {
        console.log(data.data);
    });
}, 1000);

Logger TCP
// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();

// open connection to a tcp line
client.connectTCP("127.0.0.1", { port: 8502 });
client.setID(1);

// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(function() {
    client.readHoldingRegisters(0, 10, function(err, data) {
        console.log(data.data);
    });
}, 1000);

Logger UDP
// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();

// open connection to a udp line
client.connectUDP("127.0.0.1", { port: 8502 });
client.setID(1);

// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(function() {
    client.readHoldingRegisters(0, 10, function(err, data) {
        console.log(data.data);
    });
}, 1000);

ModbusTCP Server
// 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);
});

Read and Write Modbus ASCII
// create an empty modbus client
const Modbus = require("modbus-serial");
const client = new Modbus();

// open connection to a serial port
client.connectAsciiSerial(
    "/dev/ttyUSB0", 
    {
        baudRate: 9600,
        startOfSlaveFrameChar: 0x3A  // optional: slave frame delimiter
    }, 
    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);
}

"modbusdb" is an elegant wrapper over the Modbus protocol
Check modbusdb github repo at https://github.com/yarosdev/modbusdb for more information, feedback is welcome!

Here is an example of using modbusdb wrapper over modbus-serial:

import Modbus from 'modbus-serial';
import { Modbusdb, ModbusSerialDriver, Datamap, createRegisterKey, TypeEnum, ScopeEnum } from "modbusdb";

// create an empty modbus client
const client = new Modbus();

client.connectTcpRTUBuffered("127.0.0.1", { port: 8502 }, app) // or use any other available connection methods

function app() {

  // First you need to define a schema for a database:
  // createRegisterKey(UNIT_ADDRESS, MODBUS_TABLE, REGISTER_ADDRESS, BIT_INDEX)
  const schema = [
    { key: createRegisterKey(1, ScopeEnum.InternalRegister, 10),    type: TypeEnum.Int16 },
    { key: createRegisterKey(1, ScopeEnum.InternalRegister, 11),    type: TypeEnum.Int32 },
    { key: createRegisterKey(1, ScopeEnum.PhysicalRegister, 99),    type: TypeEnum.UInt16 },
    { key: createRegisterKey(1, ScopeEnum.InternalRegister, 15, 2), type: TypeEnum.Bit },
  ];
  
  // Define unit-scoped config if needed:
  const units = [
    {
      address: 1, // This is unit address
      forceWriteMany: true, // Use 15(0x0f) and 16(0x10) functions for single register, default: false
      bigEndian: true, // You can use BigEndian for byte order, default: false
      swapWords: false, // This is applicable only for multi-registers types such as int32, float etc, default: false
      requestWithGaps: true, // If you are requesting addresses 10 and 13, allow to send one request to the device, default: true
      maxRequestSize: 32, // How many registers to be requested in one round-trip with device, default: 1
    }
  ];
  
  // Let`s create an instance of a database:
  const db = new Modbusdb({
    driver: new ModbusSerialDriver(client),
    datamap: new Datamap(schema, units)
  });

  // Now we can request three registers:
  // NOTICE: Modbusdb under the hood will make all needed requests for you in using an optimal plan
  //         If registers can be requested using a single request, be sure it will
  db.mget([
    createRegisterKey(1, ScopeEnum.InternalRegister, 10),
    createRegisterKey(1, ScopeEnum.InternalRegister, 11),
    createRegisterKey(1, ScopeEnum.PhysicalRegister, 99)
  ]).then(result => {
    console.log('mget', result)
  })

  // You can store register`s key to be used later:
  const speedSetPoint = createRegisterKey(1, ScopeEnum.InternalRegister, 10);
  const workingMode = createRegisterKey(1, ScopeEnum.InternalRegister, 11);
  
  // Write values directly into modbus device as easy as possible:
  // NOTICE: Modbusdb under the hood will make all needed requests for you
  //         Write operations have higher priority over the read operations
  db.mset([
    [speedSetPoint, 60],
    [workingMode, 10],
  ]).then(result => {
    console.log('mset', result)
  })
}

Enums:

ScopeEnum: (Modbus Table)
  1 = PhysicalState = Discrete Input
  2 = InternalState = Coil Status
  3 = PhysicalRegister = Input Register
  4 = InternalRegister = Holding Register
  
TypeEnum: (Available Data Types)
  1 = Bit,
  4 = Int16,
  5 = UInt16,
  6 = Int32,
  7 = UInt32,
  8 = Float

to get more see Examples

Serial connection

node-modbus-serial use node-serialport for serial communication, for serial port options settings it passes to serial port the openOptions object, default serial port settings are 9600,8,n,1.

client.connectRTUBuffered("/dev/ttyUSB0", { baudRate: 9600, parity: 'even' });

node-modbus-serial's People

Contributors

1038642892 avatar adam-nielsen avatar alexweber200 avatar andremaz avatar auspexeu avatar bechterev avatar biancode avatar btotals avatar chaos2171053 avatar debevv avatar eeerin avatar everhardt avatar highwolf avatar johnnygrynbuj avatar mchakroun avatar meisterlampe avatar nicolasduran avatar nv4re avatar reinierh avatar robertslando avatar sigma-design avatar sjlongland avatar superjojo2001 avatar teddy1565 avatar thkls avatar turbo87 avatar uwburn avatar xinyifly avatar yaacov avatar yarosdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-modbus-serial's Issues

Error Handling on connectTCP broken

It is not possible to handle socket errors on a connectTCP call.

The suggested behavior of the example would be to print out "error handled".
Instead a Unhandled Error Event occurs.
Precondition: The port 4444 is closed!

// create an empty modbus client
var Modbus = require('./index.js')
var client = new Modbus();

// open connection to a tcp line
client.connectTCP("localhost", {port: 4444}, (error) => {
  if(error){
    console.log('error handled')
  }
  console.log('connected')
});

In my opinion the problem is the call of net.Socket.connect(port, ip, eventListener) in tcpport.js in line 57. The Docu of net.Socket expects a eventListener but not a callback!
The callback passed to connectTCP(...) will not be called in case of an error.

If I can do anything else to assist fixing this issue just respond. Thanks.

Modbus Serial Device Server

Hi,

now I've been testing a Modbus Serial Device Server (TCP to Serial NPort) and it has some errors.

a) if there is an internal restart/reset inside NPort (configuration), it raises no error about the lost TCP connection, but it crashes later see:

19 Feb 10:34:22 - TypeError: Cannot read property '_timeoutHandle' of undefined
    at TcpPort.<anonymous> (/.npm-global/lib/node_modules/node-red-contrib-modbus/node_modules/modbus-serial/index.js:211:43)
    at emitOne (events.js:96:13)
    at TcpPort.emit (events.js:188:7)
    at Socket.<anonymous> (/.npm-global/lib/node_modules/node-red-contrib-modbus/node_modules/modbus-serial/ports/tcpport.js:53:16)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:548:20) 

b) reading via TCP doesn't work, because of RTU buffered behavior - may it has to implemented in TCP buffered, too. It is possible to encapsulate RTU in TCP packages and in that case, may we got buffered behavior with split PDU data.

19 Feb 10:01:47 - [error] [modbus-getter:efaacce9.2a66d] Data length error, expected 7 got 8
19 Feb 10:01:47 - [error] [modbus-getter:efaacce9.2a66d] Data length error, expected 7 got 8
19 Feb 10:01:48 - [error] [modbus-getter:efaacce9.2a66d] Data length error, expected 7 got 8

c) it works very well in writing data to NPort ;)

cya
Klaus

Packet length check does not work when reading one coil

When trying to read a single coild value from modbus via tcp I receive a "Data length error" originating at the second length check (version 4.4.3 index.js: line 256).

It works as soon as I read multiple coils.

If I comment out the length check the package itself is decoded just fine.

I've tested this with a Codesys Runtime on a Raspberry Pi. Unfortunately I don't have this modbus slave here right now, so I can't paste the actual package content.

node-modbus

you're now able to take node-modbus npm see you're npm account

readCoils() only reading 8 bits

Hey-- I think there may be an issue with the readCoils() method.

Running this code below, I'm always getting the same length of coils read no matter if I change the passed count:

client.readCoils(start, count)
  .then(function (received) {
    console.log('---> asked/received length: ', count, '/', received.data.length, received.data)
  })

---> asked/received length: 1 / 8 [ false, false, false, false, false, false, false, false ]
---> asked/received length: 2 / 8 [ false, false, false, false, false, false, false, false ]
---> asked/received length: 20 / 8 [ false, false, false, false, false, false, false, false ]

Am I misusing this method? I assumed that data.length should be the same as count. Thanks!

connectTcpRTUBuffered always timeout

Hello,
I'm working with this library but when I use the server.js and then buffertcp.js it always give me timeout.
If I replace connectTcpRTUBuffered for connectTCP it works well, but I need the other function.
Any assistance would be greatly appreciated.

Problems with serial sequenical reads

I'm getting Data length error messages when trying to make multiple reads via serial.

I have a really simple setup, a rPi with a USB FTDI RS485 adapter linked to a single modbus slave.

It either fails on the second or third read, the first always works.

The code is pretty simple:

var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

client.connectRTU('/dev/ttyUSB0', {baudrate:38400, dataBits: 8, parity: 'none', stopBits: 1}, read1);
var i;

function read1() {
  if (!i) {
     client.setID(1);
     i = 1;
  }
  client.readHoldingRegisters(2009,2,function(err,d){
    console.log("read1");
    if (err) {
      console.log("read1 error");
      console.log(err);
    } else {
      console.log(d);
      read2();
    }
  });
}

function read2() {
  client.readHoldingRegisters(2010,1,function(err,d){
    console.log("read2");
    if (err) {
      console.log("read2 error");
      console.log(err);
    } else {
      console.log(d);
      read3();
    }
  });
}

function read3() {
  client.readHoldingRegisters(2011,1,function(err,d){
    console.log("read3");
    if (err) {
      console.log("read3 error");
      console.log(err);
    } else {
      console.log(d);
      setTimeout(read1,3000);
    }
  });
}

Any ideas what's going on?

Wiki instead README

We should clean up the README with most important information and refer to the Wiki for more details and examples.

implement transaction identifier for Modbus/TCP

Modbus/TCP messages contain a "transaction identifier". This field can be used to correlate a modbus response to the request message.

While sending multiple modbus/TCP requests to a client I faced some issues regarding the length of the expected modbus response ("Data length error, expected ..."). It seems like that you use one field to store the expected length of the answer when sending a new request. This field is overwritten each time a message is send. This leads to errors when sending multiple simultaneous requests with different lengths.

I was sending a readInputRegisters message directly after sending a writeRegisters message.

.writeFC6(undefined, 100, 1) writing to all addresses

So while using this I accidentally wrote to an undefined address and that caused everything on my network to receive that write. I checked with the below code and it happened again, I was wondering if this is supposed to be a feature of the library? it seems really dangerous, I looked and saw no documentation about this.

// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

// open connection to a serial port
client.connectRTU("/dev/mydevice", { baudrate: 19200 }, write);

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

// write the values 0, 0xffff to registers starting at address 5 
// on device number 1. 
client.writeFC6(undefined,100,1) //command to turn on light at address undefined turns on everything
    .then(read);

}

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

PortNotOpenError

Hi,
I am trying to connect an energy meter(modbus) to my ubuntu 16.04 machine. However, when I run the following node app, I run into the error mentioned.

Error:
PortNotOpenError {
name: 'PortNotOpenError',
message: 'Port Not Open',
errno: 'ECONNREFUSED'}

My code:
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

// open connection to a serial port
client.connectRTUBuffered("/dev/ttyUSB0", { baudrate: 9600 });
client.setID(1);
client.readHoldingRegisters(0136, 2, function(err, data) {
console.log(data.data);
});

Any leads to address the issue?
Thanks in advance.

Getting Crc Error in RTU

Ascii is working completely fine but RTU is not working .
When I tried to communicate with two different device in one im getting CRC error & in other im getting values but that also not true.
1

My Code

var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

// open connection to a serial port
client.connectRTU("/dev/ttyAMA0", {baudrate: 9600, dataBits: 8, parity: 'even', stopBits: 1}, read);

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

And The one which im using in ardunio. This code is working fine.
char pubdata1[2000];
String mn = "1";
String vrv = ""; //6
String vyv = ""; //7
String vbv = ""; //8
String freq = ""; //9
String pd = ""; //
String cavg = ""; //11
String cr = ""; //12
String cy = ""; //13
String cb = ""; //14
String pfavg = ""; //
String w = "";
String wh = "";
String v1thd = "";
String v2thd = "";
String v3thd = "";
String a1thd = "";
String a2thd = "";
String a3thd = "";
String pfr = ""; //16
String pfy= "" ; //17
String pfb = ""; //18
String fae = ""; //
String ap = ""; //
String meterdata = "";
static union
{
unsigned long a;
byte b[4];
float f;

}vr,vy,vb,ar,ay,ab,pfa,f;

unsigned int crcis(byte* buf,int len, int chk)
{
unsigned int crc = 0xffff;
unsigned int pos = 0;
byte crc0,crc1;
for(pos=0;pos<len;pos++)
{
crc^=(unsigned int)buf[pos];
for(int i=8;i!=0;i--)
{
if((crc & 0x0001)!=0)
{
crc>>=1;
crc ^=0xA001;
}
else
crc >>=1;
}
}

if (chk == 0)
{
buf[pos] = crc & 0x00ff;
buf[pos+1] = crc>>8;
return 1;
}
else
{
if (buf[pos] == (crc & 0x00ff))
{
if (buf[pos+1] == ((crc>>8) & (0x00FF)))
return 1;
}
else
{
return 0;
}

}
}

void readregister(unsigned int deviceid, unsigned int functioncode, unsigned int address)
{
byte rxbuf[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
address = address - 1 ;
byte data[] = {deviceid, functioncode, highByte(address),lowByte(address),0x00,0x02,0x00,0x00};
crcis(data,6,0);
Serial.flush();
for(int i=0;i<8;i++)
{
Serial.write(data[i]);
}
delay(250);
while(Serial.available()>0)
{
for(int v=0; v<=8;v++)
{
rxbuf[v]=Serial.read();

}

}
Serial.flush();

vr.b[3]=rxbuf[5];
vr.b[2]=rxbuf[6];
vr.b[1]=rxbuf[3];
vr.b[0]=rxbuf[4];
}
void setup_wifi()
{
//Serial.println();
//Serial.print("Connecting to Network...");
//Serial.println(ssid);
// WiFi.begin(ssid,password);

while(WiFi.status() != WL_CONNECTED)
{
  delay(500);
 // Serial.print(".");
}
//Serial.println("");
//Serial.println("WiFi connected");
//Serial.println("IP address: ");

// Serial.println(WiFi.localIP());
}

}
void callback(char* topic, byte* payload, unsigned int length) {
// Serial.print("Message arrived [");
//Serial.print(topic);
// Serial.print("] ");
for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
}
// Serial.println();

// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
DO1state = 1; // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
} else {
DO1state = 0;// Turn the LED off by making the voltage HIGH
}

}

void loop () {
reconnect();
client.loop();
DateTime nownow = rtc.now();

for(int k=1;k<=1;k++)

{
DI1state = digitalRead(DI1);
DI2state = digitalRead(DI2);
DI3state = digitalRead(DI3);
digitalWrite(DO1, DO1state);
delay(10);
/* readregister(1,3,3961); //Wh
wh = String(vr.f);
delay(10);
Serial.flush();
readregister(1,3,3959); //forward apparent energy kvah
fae = String(vr.f);
delay(10);*/

  readregister(k,3,143);  //vr
  vrv = String(vr.f);
  delay(10);
  readregister(k,3,145);  //vy
  vyv = String(vr.f);
  delay(10);
  readregister(k,3,147);  //vb
  vbv = String(vr.f);
  delay(10);
  readregister(k,3,151);  //cr
  cr = String(vr.f);
  delay(10);
  readregister(k,3,153);  //cy
  cy = String(vr.f);
  delay(10);
  readregister(k,3,155);  //cb
  cb = String(vr.f);
  delay(10);
  readregister(k,3,157);  //freq
  freq = String(vr.f);
  delay(10);
  readregister(k,3,117);  //pfavg
  pfavg = String(vr.f);
  delay(10);
  readregister(k,3,101);  //Watt total
  w = String(vr.f);
  delay(10);

// readregister(k,3,3861); //V1%
// v1thd = String(vr.f);
// delay(10);
// readregister(k,3,3863); //v2%
// v2thd = String(vr.f);
// delay(10);
// readregister(k,3,3865); //V3%
// v3thd = String(vr.f);
// delay(10);
// readregister(k,3,3867); //A1%
// a1thd = String(vr.f);
// delay(10);
// readregister(k,3,3869); //A2%
// a2thd = String(vr.f);
// delay(10);
// readregister(k,3,3871); //A3%
// a3thd = String(vr.f);
delay(10);
Serial.flush();
mn = k;
}
}

Missing writeCoils in apis/promise.js

Please, add the following line:

cl.writeCoils = convert(cl.writeFC15);

in the body of function addPromiseAPI,
looks like it was unintentionally forgotten.

Slave Modbus

Hello
does it work in Modbus Slave mode?
please write example?
thank you

pulling out crc16 has broken response check

The new single crc16 function works for appending to requests, but fails when checking responses as it no longer skips the last two bytes i.e. the crc of the response packet.

The crc version when checking repsonses included this extra line, then referenced 'length' for the for loop rather than buf.length

var length = buf.length - 2;

TCP reconnect doesn't work

Hi,

since v4.6.1 (also 5.1.3) there is no error on lost TCP connection. How can I get that info from modbus-serial? Error is empty in that case. ( err{} )

before it raises the err.code === 'ECONNRESET' - see with 4.5.1 it works

How to setup parity and even?

Hi
please tell , how to setup even and parity for serial connection?

client.connectRTU("/dev/ttyUSB0", {baudrate: 9600}, write);

like this?
client.connectRTU("/dev/ttyUSB0", {baudrate: 9600, 8e1}, write); - not works

Use semantic versioning

Currently it is not very obvious to me, how version numbers are set. E.g. with the latest commit, which simply added some tests, the major version number was increased.
I suggest to use semantic versioning (http://semver.org/).

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.

This will help users of this library to determine what happened between several versions. Especially for professional users this is important, as they need to know when breaking changes are made to the API.

As the current version is 4.0.0 I think this would be an excellent version to start with the new scheme.

Modbus-RTU via GPIO RPi3

Good day, I'm trying to connect Modbus Via GPIO ttyAMA0.
When I check with an oscilloscope the RX pin, the message return well. So I've made a few research and it seems that there is a glitch so we receive a <0> front of the message.

I don’t know if you can change something in your code for fixing that?

=> stephane/libmodbus#302

I don’t know how to test it… But seems basically after a ‘modbus connect’, it need to to be added :

if(value == 0)
{
modbus_flush(ctx);
}

best,

Inconsistent error handling

Hi Yaacov,
thanks for providing this module :)

While reading the code I wonder at how the error handling is done.

In index.js the on-data-handler checks if the emitted data matches the expectations (address, function code, length, ...). If any check fails, the callback is invoked with an error.

This works well for the TestPort and probably for the TcpPort as well (can't test it yet). But for the other ports the error handling is done inside the ports and thus only valid data is emitted to the index.js...
To me it feels correct to execute the data check inside the ports, as they are the only ones knowing how to process the specific messages (check and cut off headers, ...).

What's your opinion about this?

Best regards

FYI: I'm working on modbus exception handling.

about timeout

Hello, thanks for this module :)
and i'm using connectRTUBuffered, is there timeout for this api?

Thanks

Plans to support Report Slave ID (FC17) ?

Thanks for a great library.
Are there any plans to support Report Slave ID (FC17) ?
I think I will try implementing it in a local copy and then make a PR - but i may need your help if I run into some issues.
Also, some hardware implements completely custom FCs - is there any way to handle them without modbus-serial modifications?

TCP Server give differents responses each time

Hi,
I'm using version 5.2.9 and I've found another extrange think.
If I execute the example TCP server and execute another script using the function readCoils for example it give me differents results everytime. If I execute readHoldingRegisters as in your tests it answer me ok, but only that function works correctly.
I attach my code and screenshots:

Server.js:
test1

Client.js
test

Output with debug activated:
terminal

Modbus TCP

How to implement Modbus TCP protocol using modbus-serial?
Its has modbus over tcp, etc.

Modbus request in response

A feature request needs an enhancement of the response to have data, response and request buffer, please

response {
request: Buffer with CRC
data : []
buffer: Buffer
}

That is a good idea for debugging

No reconnection client after disabling Modbus Server

Hi,

Last week I post a message in the Node Red section of modbus. It seems that this issue is a problem in the node-modbus-serial. I have the following setup: One S7-1200 PLC and an IOT2000 device. On the IOT "Node Red" is installed and the node-red-modbus module. If I setup in the software a ModbusRead (function 3 read; read holding registers) then it seems to be working OK. Even if i disconnect (pull out the network connector) the connection is timedout and if connected the data is read again. BUT if I disable the software in the S7-1200 then the reconnection isn't working anymore. I get a CONNECTION REFUSED and then the Node Red will stop. I have contacted 'biancode' and he is pretty sure that the modbus-serial is maybe the problem. On his recommendation I tried to run the logger.js example. The results are:

Connected
Receive: [ 8856, 0, 0, 17 ]
Receive: [ 8858, 0, 0, 17 ]

Timed out
Timed out
Timed out
<connect the network physically)
Receive: [ 8870, 0, 0, 17 ]
Receive: [ 8871, 0, 0, 17 ]
Receive: [ 8872, 0, 0, 17 ]
Receive: [ 8879, 0, 0, 17 ]
^C

Started again the logger:
Connected
Receive: [ 9430, 0, 0, 17 ]
Receive: [ 9432, 0, 0, 17 ]
Receive: [ 9433, 0, 0, 17 ]

Port Not Open
Port Not Open
Port Not Open

Port Not Open
Port Not Open
Port Not Open
Port Not Open
Port Not Open
^C

The port won't be open again and will stay in this state. I did not get the REFUSED error...
Of course disabling the server is not likely to happen, but it can. My question is is there a solution to solve this problem. For example after a number of Port Not Open message, disconnect and try to connect again. Do this forever.

Thanks in advance!

Rene

Why port doesn't have method to close connection?

I want open tcp-connection, read some values and close connection.
Probably all ports in ./apis/connection.js must return "this._port" to implementation it, like below

cl.connectTCP = function (ip, options, next) {
    ... 
    this.open(next);
    return this._port;
};

Or it's no good?

'use strict';
let ModbusRTU = require('modbus-serial');
let client = new ModbusRTU();
let port = client.connectTCP('127.0.0.1', {port: 502}, function(){
    client.setID(1);
    client.readCoils(11, 1, function(err, data) {
        console.log(err, data);
        port.close(); // THIS
    });
});

DC error CRC error:data:undefined

SOURCE:
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();
client.connectRTU("/dev/ttyS1", {baudrate: 9600});
client.setID(1);
setInterval(function() {
client.readHoldingRegisters(1, 2, function(err, data) {
debugger;
console.log(err+':data:'+JSON.stringify(data) );
});

}, 7000);

ERR:
CRC error:data:undefined
Data length error, expected 9 got 1:data:undefined
CRC error:data:undefined
Data length error, expected 9 got 1:data:undefined

MODBUS RTU

Hi,
i want to implement loopback test for HEXIN RS232 - RS485 converter via MODBUS. I am newbie to modbus implementation and i read you repository for modbus serial communication. My requirement is to do callback test rs232 to raspberry pi via modbus just simple read and write. Simply send some message to port ttylS0 and get same packet. Please advise me how can i implement this. Also unable to compile your code read/write sample which you given using node JS.

Please help me out.

rohit

Parallel ModbusTCP

I created an expressjs route that when called does:

Simplified version:
`app.get('/modbus', function(req, res){
let client = new ModbusRTU();

// open connection to a tcp line
client.connectTCP("192.168.1.42", function() {
client.readHoldingRegisters(1, 1, function(err, data) {
if (err) {
res.send(err);
} else{
res.send(data);
}
});
});
}`

I have a frontend app that polls this service. Everything works perfectly until I open up two instances of the web page. When the service has multiple connections to it there seems to be an issue. The time to get the response goes up an order of magnitude.

Another way I noticed this issue is when using asyncjs and reading a bunch of modbus registers in parallel.

Wrte Only - Broad cast

Is there any way to configure RTU Buffered to have write only request (as in broadcast request)?

writeFC15 outputs wrong values

When writing several coils (count other than 8), the respecting byte is expected to be filled with zeros.

E.g. writing 5 coils (true, true, true, true, true) should result in 0x1F (0001 1111).

The current implementation does not explicitly write the zeros but stops after writing the 5 bits. This may result in unexpected values as the used byte may still contain bits (other than 0).

Which method should I use to response Master?

Master send "03 03 00 00 00 06 C4 2A" to my "js slaver" per 500ms .

But which method should I use to response the master?

I know i should response the data from "0000" , length = 6 which response code is :

 03                    0C                 01 02 03 04 05 06 07 08 09 0A 0B 0C      XX XX
slave address      byte count        [_________________data________________]       CRC

but how to send this message to master?

var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

client.connectRTUBuffered("com6", { baudrate: 9600 });
client.setID(3);

setInterval(function(){
        // Now what should i do to read a request from master? 
       //so that i can make a response to master.    
},1000);

Need to buffer serial data.

Hi,

I just tried running v3.2.5 of the package in ModbusRTU mode against this Modbus Simulator: http://www.plcsimulator.org/

When I try and run the simple logger example, I get loads of errors about the Data Length not being what is expected (See line 192 of index.js).

This is happening because the serialport module is passing you data as it gets it from the far end and not waiting.

One option would be to configure the serialport module to wait for a delimiter before triggering the 'data' event, but from a quick look at the modbus protocol I don't think that is possible. If that is the case then I think the correct solution is to buffer the data up until you have the expected length and then attempt to process it.

Multiple errors when running modified Modbus server example

Hello,
I'm trying this library. I choose it because seems easier to use and it's pure js, compared to another libraries. Congrats on your work!

However, I feel I'm missing something too obvious since almost every time something someone connects and ask for data, the programs crashes.

I added some parameters that changes over time to the modbus server example, in order to simulate a PLC.

I uploaded the snippet here: https://gist.github.com/checor/6217b145a6601f6aff81da1cd6df092d

I added some variables that need to change over time. I don't know if it's interferes with the Modbus library, I'm a js amateur 😞

Here are the error strings I encounter usually:

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: read ECONNRESET
    at exports._errnoException (util.js:1022:11)
    at TCP.onread (net.js:569:26)

Almost everytime a PLC disconnects/shuts down. From what I found about this error, I need to handle it myself, since it's a connection reset.

C:\modbus-sk\node_modules\modbus-serial\servers\servertcp.js:105
        responseBuffer: responseBuffer.toString("hex")
                                      ^

TypeError: Cannot read property 'toString' of undefined
    at _parseModbusBuffer (C:\modbus-sk\node_modules\modbus-serial\servers\servertcp.js:105:39)
    at Socket.<anonymous> (C:\modbus-sk\node_modules\modbus-serial\servers\servertcp.js:391:34)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:548:20)

When reading a coil. With this error I don't have a clue what is the cause.

Any assistance would be greatly appreciated.

Error: Cannot find module 'serialport'

I don't need ModbusRTU and I don't install serialport from devDependencies. When I include modbus-serial by require('modbus-serial') then my code failed with error Cannot find module 'serialport' because index.js try to use rtubufferedport who needs serialports.

Code below can fix that problem (imho it is not elegant way but it works)

// index.js:line 657

try {
  module.exports.RTUBufferedPort = require('./ports/rtubufferedport');
} catch(err) {}

New NPM version

Do you know when you are ready to deploy a new NPM package, please?

Modbus-serial buffered mode throws exception instead of data

Hello I am using Modbus-Serial along with "node-red-contrib-modbus" on an embedded intel platform. I must admit that the platform is that fast that it always return serial receive strings in chunks. This is why I am using buffered RTU mode. It works well except the following case:

I am sending a read multiple register command of 64 registers to a modbus RTU slave no with address 1.

Modbus serial sends out the hex string 010300000040443A which is absolutely correct.

My slave answers also correct with 133 bytes and in each of the 64 returned value it reports 0183hex = 387dec

010380018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018301830183018346e0

Now comes the point:

The first chunk received in the buffered function this._client.on('data', function onData(data) {...} are the first 9 bytes ...

010380018301830183

So just to set the values right during the first loop cycle as the code would do it:

expectedLength = 133;
bufferLength = 9;
maxoffset = 9 - 5 = 4;
unitid = 1
functioncode = 3

If you now walk through the for next loop you come to the point where i = 3 and then by mistake
unitId gets 01 and functioncode get 83 (cause it is part of my data) and the functions throws a
self._emitData(i, EXCEPTION_LENGTH);

This is a bug.

It is better to evaluate unitid and function by takeing it from the [0],[1] bytes of the chunk outisde the loop outside the loop

var unitId = self._buffer[0];
var functionCode = self._buffer[1];

Also I would check the buffer so long as the whole data stream with the calculated expected length is received and then I would evaluate the whole string.

Unable to close TCP connection

client.close(); for a TCP connection does not close the connection. The socket stays open on the slave and master. Is there a different method to close TCP connection?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.