Skip to content

Latest commit

 

History

History
167 lines (126 loc) · 7.88 KB

README.md

File metadata and controls

167 lines (126 loc) · 7.88 KB

node-modbus-stack

A StreamStack implementation of the MODBUS protocol for Node.

This module exposes two concrete StreamStack implementations: ModbusRequestStack can be used as a MODBUS client (i.e. Master), and can write MODBUS compliant requests and listen for the response. ModbusResponseStack can be used to create a MODBUS server (i.e. Slave), by listening for requests and providing a convenient API to respond with.

MODBUS is an open building automation protocol that is widely used in various monitoring and controlling equipment. It's used with a variety of different transports, including TCP.

Currently only communication through the TCP protocol is supported, however RS-485 serial support should be possible with node-serialport. I haven't had a chance to look into it yet.

A MODBUS Master (Client)

You will need to know which Function Code (defined in the MODBUS specification) you are invoking on the remote MODBUS slave. In this example, we'll request to read from the current values of the first 50 Input Registers on the slave:

// 'RIR' contains the "Function Code" that we are going to invoke on the remote device
var RIR = require('modbus-stack').FUNCTION_CODES.READ_INPUT_REGISTERS;

// IP and port of the MODBUS slave, default port is 502
var client = require('modbus-stack/client').createClient(502, '10.0.1.50');

// 'req' is an instance of the low-level `ModbusRequestStack` class
var req = client.request(RIR, // Function Code: 4
                         0,    // Start at address 0
                         50);  // Read 50 contiguous registers from 0

// 'response' is emitted after the entire contents of the response has been received.
req.on('response', function(registers) {
  // An Array of length 50 filled with Numbers of the current registers.
  console.log(registers);
  client.end();
});

A MODBUS Slave (Server)

node-modbus-stack makes it dead simple to create a compliant MODBUS Slave (or Server) written in pure JavaScript. Here's an example of a server that would respond to the request above:

var FC = require('modbus-stack').FUNCTION_CODES;

// 'handlers' is an Object with keys containing the "Function Codes" that your MODBUS
// server will handle. Anything function code requested without a handler defined here
// will have the Server transparently respond with Exception Code 1 ("Illegal Function")
var handlers = {};

// Define a handler for "Read Input Registers". We'll just respond with the register
// number requested. In a real-world situation, you'd probably look up these values from
// a database, etc.
handlers[FC.READ_INPUT_REGISTERS] = function(request, response) {
  var start = request.startAddress;
  var length = request.quantity;
  
  var resp = new Array(length);
  for (var i=0; i<length; i++) {
    resp[i] = start + i;
  }
  response.writeResponse(resp);
}

require('modbus-stack/server').createServer(handlers).listen(502);

A "catch-all" function can be passed to createServer() instead of a "handlers" object, if you'd rather have a single callback invoked for all MODBUS requests. Just be sure to call writeException() manually for any "Function Codes" your server isn't going to handle.

API

require('modbus-stack')

  • FUNCTION_CODES - Object
    Contains the defined "Function Codes" as programmer-friendly names that translate into the defined code number.
    Usage: FUNCTION_CODES.READ_COILS → 1

  • EXCEPTION_CODES - Object
    Same as FUNCTION_CODES, contains the defined "Exception Codes".
    Usage: EXCEPTION_CODES.ILLEGAL_FUNCTION → 1

  • ModbusRequestStack - Function
    A StreamStack subclass that handles the client-side (Master) of the MODBUS protocol.
    Usage: var req = new ModbusRequestStack(stream)

    • ModbusRequestStack#request(functionCode[, param1, param2, ...], cb) - Function
      Writes a MODBUS request to the underlying Stream (usually a net.Stream). response will be emitted after the slave responds to the request. The first arg is the "Function Code" to request. Anything after that are parameters specific to each function code. cb is an optional callback to attach to the response and error events. The function should have the signature: function(err, response) {}.
      Usage: req.request(FC.READ_COILS, 0, 50)

    • "response" - function(response) - Event
      The "response" event is fired after the remote MODBUS slave responds to the request previously sent.

    • "error" - function(error) - Event
      The "error" event is fired if the remote MODBUS slave responds with an Exception Code instead of a successful response code, or if a Function Code is requested in which node-modbus-stack hasn't implemented the proper Function Code parsing logic in client.js.

  • ModbusResponseStack - Function
    A StreamStack implementation to handle the server-side (Slave) of the MODBUS protocol.
    Usage: var res = new ModbusResponseStack(stream)

    • ModbusResponseStack#writeResponse(param1[, param2, param3, ...]) - Function
      Writes out the MODBUS response after receiving a request event. The parameters given are dependant on the MODBUS "Function Code" that was requested.
      Usage: res.writeResponse(array) // After receiving a "Read Input Registers" request

    • ModbusResponseStack#writeException(exceptionCode) - Function
      Writes out a MODBUS exception response after receiving a request event. exceptionCode should be the desired exception code to respond with. See EXCEPTION_CODES.
      Usage: res.writeException(EXCEPTION_CODES.ILLEGAL_FUNCTION)

    • "request" - function(request) - Event
      The "request" event is fired once a remote MODBUS master sends a Function Code request. request is an Object containing interesting properties about the request, like functionCode and any other parameters that go with the desired Function Code.

    • "error" - function(error) - Event
      The "error" event is fired if a Function Code is requested in which node-modbus-stack hasn't implemented the proper Function Code parsing logic in server.js.

require('modbus-stack/client')

  • createClient(port[, host]) - Client
    Creates and return a new Client instance, which is the preferred method of conventional MODBUS master communication over TCP. The default MODBUS port is 502.
    Usage: var client = modbusClient.createClient(502, 'example.com')

    • Client#request(functionCode[, param1, param2, ...], cb) - ModbusRequestStack
      Makes a MODBUS request to the remote MODBUS slave. Same as ModusRequestStack#request().
      Usage: var req = client.request(FC.READ_COILS, 0, 10)

    • Client#end() - Function
      Sends a FIN to the remote slave device, closing the TCP connection.
      Usage: client.end()

require('modbus-stack/server')

  • createServer(handlers | callback) - Server
    Creates and returns a new Server instance, which is used to make MODBUS compliant servers easily. handlers should be an Object containing keys and callbacks of the Function Codes your server is implementing, or a "catch-all" callback function can be passed to invoke for every MODBUS request, regardless of the Function Code.
    Usage: var server = modbusServer.createServer(handlers)