Code Monkey home page Code Monkey logo

h5.modbus's Introduction

h5.modbus

Implementation of the MODBUS IP/ASCII/RTU master and slave over TCP/UDP/Serial/WebSocket for Node.js.

TODO

  • Remaining messages
  • Tests
  • Documentation
  • npm publish

Requirements

Installation

npm install github:morkai/h5.modbus#master

Usage

'use strict';

const modbus = require('h5.modbus');

const slave = modbus.createSlave({requestHandler: handleRequest});
const master = modbus.createMaster();

master.once('open', () => master.readHoldingRegisters(0x0000, 10, handleResponse));

function handleRequest(unit, request, respond)
{
  respond(modbus.ExceptionCode.IllegalFunctionCode);
}

function handleResponse(err, res)
{
  if (err)
  {
    console.error(`[master#error] ${err.message}`);
  }
  else if (res.isException())
  {
    console.log(`[master#exception] ${res}`);
  }
  else
  {
    console.log(`[master#response] ${res}`);
  }
}

License

This project is released under the MIT License.

h5.modbus's People

Contributors

morkai 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

Watchers

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

h5.modbus's Issues

Error-events.js:141

hello,
I am using the your package for my project and its working fine but recently i got this error-

events.js:141
throw er; // Unhandled 'error' event
^
ResponseTimeoutError: No response was received from the slave in the specified time.
at Transaction.handleTimeout (/media/rathore/mydata/project/inspinia_test/.meteor/local/isopacks/jeremybyu_mmodbus/npm/node_modules1/h5.modbus/lib/Transaction.js:452:20)
at Timer.listOnTimeout (timers.js:92:15)

Can you help me with this error.

Thanks

Minor fixes on Modbus over Serial Port

I just did npm update to the latest h5.modbus from master branch and found some errors that need minor fixes as follow:

SerialListener.js:

class SerialListener extends Listener
{
  /**
   * @param {SerialListenerOptions} [options]
   */
  constructor(options)
  {
    super();
    //
    ...
    //
    /**
     * @private
     * @type {function(this:SerialListener, Buffer)}
     */
    //this.onSerialData = this.onSerialData.bind(this);
    this.onSerialReadable = this.onSerialReadable.bind(this);

    if (!options)
    {
      options = {};
    }
    //
    ...
    //
}

SerialConnection.js:

class SerialConnection extends Connection
{
  /**
   * @param {SerialConnectionOptions} options
   */
  constructor(options)
  {
    super();

    //
    ...
    //

  isOpen()
  {
    //return this.serialPort !== null && this.serialPort.isOpen();
    return this.serialPort !== null && this.serialPort.isOpen;
  }

  //
  ...
  //

  setUpSerialPort(serialPort)
  {
    if (!serialPort)
    {

      //
      ...
      //

      //serialPort = new SerialPort(this.serialPortOptions.path, this.serialPortOptions, false, null);
      serialPort = new SerialPort(this.serialPortOptions.path, this.serialPortOptions);
    }

    //
    ...
    //

  }
}

Slave Device IDs

I have some questions about connecting more than one slave devices to a master. Modbus protocol is RTU, so I have physical (and virtual) RS485 network for this. I took the example and modified the UNIT_TO_DATA object for slave ID=1 as this:

const UNIT_TO_DATA = {
  0x01: {
    coils: new Array(0xFFFF),
    discreteInputs: new Array(0xFFFF),
    holdingRegisters: new Buffer(0xFFFF * 2).fill(0),
    inputRegisters: new Buffer(0xFFFF * 2).fill(0)
  }
};

And slave ID=2 like this:

const UNIT_TO_DATA = {
  0x02: {
    coils: new Array(0xFFFF),
    discreteInputs: new Array(0xFFFF),
    holdingRegisters: new Buffer(0xFFFF * 2).fill(0),
    inputRegisters: new Buffer(0xFFFF * 2).fill(0)
  }
};

They both work just fine, but when the modbus request is sent to slave ID=1, slave ID=2 gets Illegal Data Address exception. And vice versa. In my opinion, any message comes with mismatched slave ID, it should just drop it and do not send any exception.

Another question, for master device, how to send a modbus request and pass the unit ID as parameter, so that it does not pick up the defaultUnit?

Documentation

I am very interested in your project, as it only meets my requirements.
Could you write a small documentation for me.
Thanks in advance.

Is this project alive yet?

This is a well structured project to implement modbus protocol, and hope it can be published in npm repository and enhance documents.

modbus tcp connection interrups

hi,
i testet the h5.modbus module.
i started a read connection to a wago 750-841 plc.
nearly after 3min i get always a disconnected event triggered.

the interuption takes 200ms. the pings during this timeperiod are constantly nearly at 6ms.
has somebody also have seen thhis phanomen?

Cheking ExceptionResponse

Could you explain how chek the response for exception.
There are isException() in ExceptionResponse, but not this in ReadHoldingRegistersResponse.
I chek existing data.
Thank you.

RTU over TCP

I want to use RTU over TCP, but thare are coalescing packets.
It may be 2 or 3 packets in receive buffer in RTUtransport.
Can you help me, please?

Example for slave

How to send request to the client?

I have following code:

listener.on('client', function(client){
    // how to send request?
});

const slave = new modbus.Slave({
    listener: listener,
    transport: transport,
    requestHandler: handleRequest
});

I'll be very thankful!

Release 1.0.0?

Hi,

Are you planning do remaining TODOs listed in readme and publish v1.0.0 to npm at some point?

I played around with it and it seems to be a perfet fit for my purposes. I can always install it from github, but it would be nice if latest version was in npm. I noticed apis have improved very nicely from 0.1.0.

about DTU ?MODBUS RTU

sensor (485) modbus RTU
Is there way to poll such system:
sensor (slave) <->4G modem <-> server(master)?

i want to use example/slave.js and master.js to setup server to listen so that i can write and receive on modbus RTU
but the master.js = client has to know the 4G modem IP

the code i changed like this
const slave = new modbus.Slave({
listener: listener,
transport: transport,
requestHandler: handleRequest
});
const master = new modbus.Master({
transport: transport,
connection: listener, //connection change to listener
maxConcurrentTransactions: CONCURRENT_TRANSACTIONS,
defaultUnit: 1,
defaultMaxRetries: 0
});
this will cause a problem at Master.js
start(requestId)
{
if (!this.frame || !this.transport.update(this.frame, requestId))
{
this.frame = this.transport.encode(requestId, this.transaction.unit, this.transaction.request.toBuffer());
}

this.requestId = requestId;
this.timeoutTimer = setTimeout(this.onTimeout.bind(this), this.transaction.timeout);

//console.log('this.connection.socket.remoteAddress ',this.connection.socket);

this.connection.write(this.frame); //this place is the problem
//this.connection.emit('write',this.frame);
// this.connection.onClientWrite(this.connection.socket,this.frame); //i modify this code like this
this.transaction.emit('request', requestId);
}

this.connection.write(this.frame) is not undefined i follow this error to Tcplistener.js
the Tcplistener.js do not have a funtion write,so i modify this code like this this.connection.onClientWrite(this.connection.socket,this.frame);
but i find the this.connection.socket is null .
is there way to send and receive the modbus RTU packet on server?
my english is not good , i hope above is clear.

TCP Connection to different than localhost

TCPConnection.js

this.socketOptions = Object.assign( {}, options.TcpConnection.socketOptions);
//this.socketOptions = Object.assign({port: 502, host: 'localhost'}, options.socketOptions);

I had to add this in my branch to connect to any other host than localhost.
Is this a bug or feature?

RTU Framing - Inter-frame delay/space

I have a question about the RTU framing. Which file should I look at to modify the 1.5 and 3.5 chars of inter-frame delay time? I was expecting to see in Transport.js or RtuTransport.js, but it was not there.

h5.modbus with 16bit floating point

HI,

has somebody used h5.modbus with 16bit floating point values?
at the moment i'm not sure if it's working, i only see 32bit floating point.

is 16bit possible?

Master Slave RTU over serial port

I am trying to write the code to talk Modbus RTU over the serial port with no success. I posted an issue here since I could not find any documentation somehow? Here are my master.js and slave.js code and the errors I got:

master.js:

var SerialPort = require('serialport');
var modbus = require('h5.modbus');

var serialPort = new SerialPort('/dev/tty.virtual1', {
  baudRate: 9600
});

const master = new modbus.Master({
  transport: {
    type: 'rtu',
    eofTimeout: 10, // End of frame timeout
  },
  connection: {
    type: 'serial',
    serialPort: serialPort
  }
});

master.once('open', function()
{
  console.log('Connected!');

  const t = master.readHoldingRegisters(0x0000, 10);

  t.on('error', err => console.error(err.message));
  t.on('response', res => console.log(res.toString()));
});

master.on('error', (err) => console.log('master#error: %s', err.message));

slave.js:

var SerialPort = require('serialport');
var modbus = require('h5.modbus');

var serialPort = new SerialPort('/dev/tty.virtual0', {
  baudRate: 9600
});

const slave = new modbus.Slave({
  requestHandler: handleRequest,
  transport: {
    type: 'rtu',
    eofTimeout: 10, // End of frame timeout
  },
  listener: {
    type: 'serial',
    serialPort: serialPort
  }
});

function handleRequest(unit, request, respond)
{
 respond(modbus.ExceptionCode.IllegalFunctionCode);
}

slave.on('error', (err) => console.log('slave#error: %s', err.message));
slave.on('data', () => console.log('slave#gotdata'));

These are the error I got on master:

node master.js 
master#error: connect ECONNREFUSED 127.0.0.1:502
master#error: connect ECONNREFUSED 127.0.0.1:502
master#error: connect ECONNREFUSED 127.0.0.1:502
master#error: connect ECONNREFUSED 127.0.0.1:502
master#error: connect ECONNREFUSED 127.0.0.1:502

These are the error I got on slave:

node slave.js 
listener#error: listen EACCES 0.0.0.0:502

Why would it try to create a local server if all it needs to do is to get connected through RS485 devices. What did I do wrong? Thank you.

Connecting over TCP even though I choose serial

I have been using 0.1.0 for a while but tried to bump to 1.0.0. However, now it seems to try to open a TCP connection even though I have specified a serial port.

This is how I create the master:

var port = new SerialPort(serialPath, { baudrate: baudrate, parity: parity }, false);
  this.modbus = library.createMaster({
    transport: {
      type: 'rtu',
      eofTimeout: 500,
      connection: {
        type: 'serial',
        serialPort: port
      }
    },
    suppressTransactionErrors: false,
    retryOnException: true,
    maxConcurrentRequests: 1,
    defaultUnit: 0,
    defaultMaxRetries: 1,
    defaultTimeout: 1000,
  });

And the log prints:

Master error { [Error: connect ECONNREFUSED 127.0.0.1:502]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 502 }

Am I missing something?

Interval Option - Write Values passed by reference

I am doing a write coils to a modbus slave through serial rtu. I am specifying the data to write through the variable "states". The writeMultipleCoils function I am calling takes advantage of your "interval" option.

I am changing the variable "states" periodically (as seen in the below code). I have verified that the variable is indeed changing. However, the modbus write command is still writing the original states value. Its as if it passed the variable state by value and not by reference. Is this truly the case, or am I missing something here?

var COIL_ADDRESS = 0x0000;
            states = [false];

            t2 = master.writeMultipleCoils(COIL_ADDRESS, states, {
                unit: 1,
                maxRetries: 10,
                timeout: 1000,
                interval: 3000,
                onComplete: function(err, response) {
                    console.log(states);
                    if (err) {
                        console.err(err.message);
                        console.err('I make the error here!');
                    } else {

                        console.log(response);
                        console.log(response.exceptionCode);
                        if (states[0] === true)
                        {
                            states = [false];
                        }
                        else
                        {
                            states = [true];
                        }

                        //console.log(response.values.readUInt16BE(0));
                    }


                }
            });

Handling Loss of Connection (Serial)

I'm having some trouble handling errors from disconnecting to the slave. I seem to have code working for modbus tcp error catching. For example I am using the master.on('error',...) and it seems to be working just fine as well as transaction errors or timeouts. I am only doing reads, and when the error is thrown a custom function is called to stop all scanning; it works well.

Then I tried out serial modbus rtu connection to '/dev/ttyACM0'. Everything works perfectly except for a hard disconnect when pulling the usb cable. The error is "thrown" (err message is "Error Input/Output error calling write()") and the function I created is called to stop scanning. Except that it is called many times (30+ rapidly) and crashes with "Segmentation Fault".

So I looked up segmentation fault and it said it has to do with improper memory writing. My guess is that the device /dev/ttyACM0 no longer exists and the memory associated with it is gone. However h5 modbus might be still trying to write to it causing these errors? Is there anything within this package that when the slave (serial) is disconnected or loss of connection that all communication is stopped and a callback is available.

EDIT:
Hmm.... might have to do with node serialport: serialport/node-serialport#302

Okay, looks like its the version of node-serial port. I think they fixed it in 1.4 something, but I'm using 1.3.1 for compatibility reasons.

Thanks!!

Writing negative value to PLC register

Hello. First of all, awesome library! Everything works really good! I have situation where i need to write negative value in to PLC register, but library throw me an error when i try to write any kind of negative value ...

throw new Error(util.format(
^
Error: Register value must be a number between 0 and 65535.

If i'm right, 0 to 65535, this is uint16 type. But i need to write int16 (-32,768 to 32,768)

Any suggestion how to solve this kind of situation?

Reason of 'data' event removal from h5.modbus

I am working on multiple Modbus devices using h5.modbus and virtual-serialport to form a virtual RS485 network on my computer. I found out that h5.modbus latest changes break data flow of virtual-serialport. Virtual-serialport expects to see 'data' event from h5.modbus in order to work. When I added back those 'data' event handler and binding within h5.modbus library, the virtual-serialport worked as expected. So, what was the reason for serialport 'data' event and binding removal in h5.modbus? Thank you.

The data address is not an allowable address for the server (or slave).

HI,

i want to read the following modbus address over TCP.

ID 2
Modbusaddress: 30775

But everytime i get the following errormessage.
can somebofy help me with that?

0x03 (RES) Exception (2): Illegal Data Address: The data address received in the query is not an allowable address for the server (or slave).

with qModMaster.exe i'm able to read the address.
can i adjust the max allowed value somewhere?

thanks for the feedback.

Greetings
Michael

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.