Browse files

Added Server example and API section to README.

  • Loading branch information...
1 parent 7239888 commit 69c94de3f5f4e64c16915a3606852bdeb19b91a5 @TooTallNate committed Jan 3, 2011
Showing with 130 additions and 15 deletions.
  1. +130 −15 README.md
View
145 README.md
@@ -17,36 +17,151 @@ RS-485 serial support should be possible with [node-serialport]. I haven't
had a chance to look into it yet.
-A MODBUS Request
-----------------
+A MODBUS Master (Client)
+------------------------
-You will need to know which _function code_ (defined in the MODBUS specification)
-you are invoking on the MODBUS slave. In this example, we'll request to read
-from the current values of the first 50 __Input Registers__ on the slave:
+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:
- var net = require('net');
- var ModbusRequestStack = require('modbus-stack').ModbusRequestStack;
+ // '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 conn = net.createConnection(502, '10.0.1.50');
+ // IP and port of the MODBUS slave, default port is 502
+ var client = require('modbus-stack/client').createClient(502, '10.0.1.50');
- var req = new ModbusRequestStack(conn);
- req.request(0x04, // Function Code: 4
- 0, // Start at address 0
- 50); // Read 50 contiguous registers from 0
+ // '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();
});
-More to come...
+
+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_<br>
+ Contains the defined "Function Codes" as programmer-friendly names that translate into the defined code number.<br>
+ __Usage:__ `FUNCTION_CODES.READ_COILS → 1`
+
+ * `EXCEPTION_CODES` - _Object_<br>
+ Same as `FUNCTION_CODES`, contains the defined "Exception Codes".<br>
+ __Usage:__ `EXCEPTION_CODES.ILLEGAL_FUNCTION → 1`
+
+ * `ModbusRequestStack` - _Function_<br>
+ A `StreamStack` subclass that handles the client-side (Master) of the MODBUS protocol.<br>
+ __Usage:__ `var req = new ModbusRequestStack(stream)`
+
+ * `ModbusRequestStack#request(functionCode[, param1, param2, ...], cb)` - _Function_<br>
+ 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) {}`.<br>
+ __Usage:__ `req.request(FC.READ_COILS, 0, 50)`
+
+ * `"response" - function(response)` - _Event_<br>
+ The "response" event is fired after the remote MODBUS slave responds to the `request` previously
+ sent.
+
+ * `"error" - function(error)` - _Event_<br>
+ 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_<br>
+ A `StreamStack` implementation to handle the server-side (Slave) of the MODBUS protocol.<br>
+ __Usage:__ `var res = new ModbusResponseStack(stream)`
+
+ * `ModbusResponseStack#writeResponse(param1[, param2, param3, ...])` - _Function_<br>
+ Writes out the MODBUS response after receiving a `request` event. The parameters given are
+ dependant on the MODBUS "Function Code" that was requested.<br>
+ __Usage:__ `res.writeResponse(array) // After receiving a "Read Input Registers" request`
+
+ * `ModbusResponseStack#writeException(exceptionCode)` - _Function_<br>
+ 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_<br>
+ 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_<br>
+ 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_<br>
+ 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__.<br>
+ __Usage:__ `var client = modbusClient.createClient(502, 'example.com')`
+
+ * `Client#request(functionCode[, param1, param2, ...], cb)` - _ModbusRequestStack_<br>
+ Makes a MODBUS request to the remote MODBUS slave. Same as `ModusRequestStack#request()`.<br>
+ __Usage:__ `var req = client.request(FC.READ_COILS, 0, 10)`
+
+ * `Client#end()` - _Function_<br>
+ Sends a FIN to the remote slave device, closing the TCP connection.
+ __Usage:__ `client.end()`
+
+`require('modbus-stack/server')`
+
+ * `createServer(handlers | callback)` - _Server_<br>
+ 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.<br>
+ __Usage:__ `var server = modbusServer.createServer(handlers)`
[StreamStack]: http://github.com/TooTallNate/node-stream-stack
[node-serialport]: https://github.com/voodootikigod/node-serialport
[ModbusWiki]: http://en.wikipedia.org/wiki/Modbus
[Modbus]: http://www.modbus.org
[Node]: http://nodejs.org
-

0 comments on commit 69c94de

Please sign in to comment.