Cloud-Automation / node-modbus

Modbus TCP Client/Server implementation for Node.JS
471 stars 175 forks source link

Question: How to create proxy server? #101

Closed OlegDokuka closed 7 years ago

OlegDokuka commented 7 years ago

Question

How to create modbus proxy server using node-modbus?

I have tried to create modbus proxy server that looks like next:

'use strict'

var stampit = require('stampit')
var modbus = require('jsmodbus')
var client = modbus.client.tcp.complete({
  'host': "46.219.99.34",
  'port': 502,
  'autoReconnect': true,
  'reconnectTimeout': 1000,
  'timeout': 5000,
  'unitId': 1
});

client.connect();
var server = stampit()
  .refs({
    'logEnabled': true,
    'logLevel': 'debug',
    'port': 8080,
    'responseDelay': 100,
    'coils': new Buffer(100000),
    'holding': new Buffer(100000)
  }).compose(modbus.server.tcp.complete)
  .init(function () {
    var init = function () {

      this.on('readHoldingRegistersRequest', function (start, quantity) {
        console.log('readHoldingRegisters', start, quantity)
        console.log(this.getCoils().readUInt8(start));

        var that = this;
        // reconnect with client.reconnect()
        client.readHoldingRegisters(start, quantity).then(function (resp) {

          // resp will look like { fc: 1, byteCount: 20, coils: [ values 0 - 13 ], payload: <Buffer> } 
          console.log(resp);

          that.getHolding().writeUInt8(resp.register[0], start);
        }, console.error);
      });
    }.bind(this)

    init()
  })

server()

but it works unexpected. From my point of view it a bit unclear how to do this according to pure documentation for this project.

Could you advice me how to create proper proxy server for all supported methods?

stefanpoeter commented 7 years ago

What do you mean by a proxy server?

Wikipedia says the following

In computer networks, a proxy server is a server (a computer system or an application) that acts as an intermediary for requests from clients seeking resources from other servers.

The code above just demonstrates a simple client server connection.

OlegDokuka commented 7 years ago

Yes, but It is unclear how to convert received data to data that are suitable for modbus client. In other word - how to adapt/convert/apply received data to modbus-tcp-client

stefanpoeter commented 7 years ago

You can read received data at any time from the buffers (coils, holding or input). If you want to act on new transmitted data directly you can listen for some of the handlers.

For example:

    var customServer = stampit()
        .refs({
            'logEnabled'        : true,
            'port'              : 8888,
            'responseDelay'     : 10, // so we do not fry anything when someone is polling this server

            // specify coils, holding and input register here as buffer or leave it for them to be new Buffer(1024)
            coils               : new Buffer(1024),
            holding             : new Buffer(1024),
            input               : new Buffer(1024)
        })
        .compose(modbus.server.tcp.complete)
        .init(function () {

            var init = function () {

                this.on('postReadCoilsRequest', function (start, quantity) {

                    if (start !== 0) {
                        return
                    }

                    /* a request has been made to set the first bit of the coils register,
                       here you can act on that new value */

                });

               /* Another method would be to periodically check buffers */

               setInterval(function () {
                   if (!(this.coils.getUInt8(0) & 0x01)) {
                       return
                   }
                   /* First bit of the coils buffer is true, do something with it */
               }.bind(this), 100);

            }.bind(this);    

            init();

        });

    customServer();
OlegDokuka commented 7 years ago

Yeah, we received for example postReadCoilsRequest. And now How can I redirect this request, with this data from buffer to another endpoint using the same client method?

stefanpoeter commented 7 years ago

You want to read from another server on the postReadCoilsRequest? Why don't you just read from that server directly?

Requests on the server side are executed immediately. There is no way to postpone a request to, lets say, wait for a client to return results. You can of course write your own ReadCoilsRequest handler (see the src/handler/server folder) and compose your own stampit object with that specific handler. This way you can do whatever you want.