Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

modbus-serial

Package Overview
Dependencies
Maintainers
1
Versions
123
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

modbus-serial - npm Package Compare versions

Comparing version 1.3.2 to 1.4.2

examples/simple-coils.js

23

examples/logger.js
// Create serial port
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort("/dev/ttyUSB0", {baudrate: 9600});
var lastAns = Date.now();

@@ -11,3 +12,3 @@ // Create modbus master

// Open modbus communication.
modbusRTU.open();
modbusRTU.open(start);

@@ -19,6 +20,20 @@ /* read 10 registers every one second

*/
setInterval(function() {
function start() {
modbusRTU.writeFC4(1, 0, 10, function(err, data) {
console.log(data.data);
if (err) {
console.log(err);
} else {
console.log(data.data);
}
lastAns = Date.now();
start();
});
}, 1000);
}
// Watch dog
setInterval(function() {
if (lastAns < (Date.now() - 5000)) {
lastAns = Date.now();
start();
}
});

@@ -61,2 +61,26 @@ /**

* Parse the data for a Modbus -
* Read Coils (FC=02,01)
*
* @param {buffer} data the data buffer to parse.
* @param {function} next the function to call next.
*/
function _readFC2(data, next) {
var length = data.readUInt8(2);
var contents = [];
for (var i = 0; i < length; i++) {
var reg = data[i + 3];
for (var j = 0; j < 8; j++) {
contents.push((reg & 1) == 1);
reg = reg >> 1;
}
}
if (next)
next(null, {"data": contents, "buffer": data.slice(3, 3 + length)});
}
/**
* Parse the data for a Modbus -
* Read Input Registers (FC=04,03)

@@ -82,2 +106,17 @@ *

* Parse the data for a Modbus -
* Force Single Coil (FC=05)
*
* @param {buffer} data the data buffer to parse.
* @param {function} next the function to call next.
*/
function _readFC5(data, next) {
var dataAddress = data.readUInt16BE(2);
var state = data.readUInt16BE(4);
if (next)
next(null, {"address": dataAddress, "state": (state == 0xff00)});
}
/**
* Parse the data for a Modbus -
* Preset Multiple Registers (FC=16)

@@ -182,2 +221,3 @@ *

var crc = _CRC16(data, length - 2)
if (crcIn != crc) {

@@ -192,3 +232,10 @@ error = "CRC error";

*/
/* Read Coil Status (FC=01)
* Read Input Status (FC=02)
*/
if (code == 2 || code == 1) {
_readFC2(data, next);
}
/* Read Input Registers (FC=04)

@@ -201,2 +248,8 @@ * Read Holding Registers (FC=03)

/* Force Single Coil (FC=05)
*/
if (code == 5) {
_readFC5(data, next);
}
// Preset Multiple Registers (FC=16)

@@ -212,2 +265,47 @@ if (code == 16) {

/**
* Write a Modbus "Read Coil Status" (FC=01) to serial port.
*
* @param {number} address the slave unit address.
* @param {number} dataAddress the Data Address of the first coil.
* @param {number} length the total number of coils requested.
* @param {function} next the function to call next.
*/
ModbusRTU.prototype.writeFC1 = function (address, dataAddress, length, next) {
this.writeFC2(address, dataAddress, length, next, 1);
}
/**
* Write a Modbus "Read Input Status" (FC=02) to serial port.
*
* @param {number} address the slave unit address.
* @param {number} dataAddress the Data Address of the first digital input.
* @param {number} length the total number of digital inputs requested.
* @param {function} next the function to call next.
*/
ModbusRTU.prototype.writeFC2 = function (address, dataAddress, length, next, code) {
// function code defaults to 2
if (!code) code = 2;
// set state variables
this._nextAddress = address;
this._nextCode = code;
this._nextLength = 3 + parseInt((length - 1) / 8 + 1) + 2;
this._next = next;
var codeLength = 6;
var buf = new Buffer(codeLength + 2); // add 2 crc bytes
buf.writeUInt8(address, 0);
buf.writeUInt8(code, 1);
buf.writeUInt16BE(dataAddress, 2);
buf.writeUInt16BE(length, 4);
// add crc bytes to buffer
_CRC16(buf, codeLength);
// write buffer to serial port
this._port.write(buf);
}
/**
* Write a Modbus "Read Holding Registers" (FC=03) to serial port.

@@ -258,2 +356,39 @@ *

/**
* Write a Modbus "Force Single Coil" (FC=05) to serial port.
*
* @param {number} address the slave unit address.
* @param {number} dataAddress the Data Address of the first register.
* @param {number} state the state to write to the coil (true / false).
* @param {function} next the function to call next.
*/
ModbusRTU.prototype.writeFC5 = function (address, dataAddress, state, next) {
var code = 5;
// set state variables
this._nextAddress = address;
this._nextCode = code;
this._nextLength = 8;
this._next = next;
var codeLength = 6;
var buf = new Buffer(codeLength + 2); // add 2 crc bytes
buf.writeUInt8(address, 0);
buf.writeUInt8(code, 1);
buf.writeUInt16BE(dataAddress, 2);
if (state) {
buf.writeUInt16BE(0xff00, 4);
} else {
buf.writeUInt16BE(0x0000, 4);
}
// add crc bytes to buffer
_CRC16(buf, codeLength);
// write buffer to serial port
this._port.write(buf);
}
/**
* Write a Modbus "Preset Multiple Registers" (FC=16) to serial port.

@@ -260,0 +395,0 @@ *

2

package.json
{
"name": "modbus-serial",
"version": "1.3.2",
"version": "1.4.2",
"description": "A pure JavaScript implemetation of MODBUS-RTU (and TCP) for NodeJS.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -12,2 +12,10 @@ # modbus-serial

- [modbus-serial](#modbus-serial)
- [Install](#install)
- [Requires](#requires)
- [What can I do with this module ?](#what-can-i-do-with-this-module-)
- [Compatibility](#compatibility)
- [Examples](#examples)
- [Methods](#methods)
#### Install

@@ -19,2 +27,6 @@

#### Requires
###### node-serialport - for using the serial port.
For use over serial port (ModbusRTU), also install node-serialport:

@@ -25,2 +37,4 @@ ```

https://github.com/voodootikigod/node-serialport
[ TCP/IP connection does not require the node-serialport package. ]

@@ -41,14 +55,15 @@

Arduino sketch for irrigation timer with modbus support:
https://github.com/yaacov/irrigation-timer-for-arduino
https://github.com/yaacov/arduino-irrigation-timer
#### Compatibility
This class implements FC3 "Read Holding Registers", FC4 "Read Input Registers" and
FC16 "Preset Multiple Registers" of modbus-RTU.
######This class implements:
#### Requires
* FC1 "Read Coil Status"
* FC2 "Read Input Status"
* FC3 "Read Holding Registers"
* FC4 "Read Input Registers"
* FC5 "Force Single Coil"
* FC16 "Preset Multiple Registers"
###### node-serialport - for using the serial port.
https://github.com/voodootikigod/node-serialport
#### Examples

@@ -152,2 +167,48 @@ ----

----
##### .writeFC1 (unit, address, length, callback)
Writes "Read coil status" (FC=01) request to serial port.
###### unit
The slave unit address.
###### address
The Data Address of the first coil.
###### length
The total number of coils requested.
###### callback (optional)
Called once the unit returns an answer. The callback should be a function
that looks like: function (error, data) { ... }
```
error - null on success, error string o/w
data - an object with two fildes:
data.data: array of boolean coils (in multiples of 8 = one byte).
data.buffer: raw baffer of bytes returned by slave.
```
----
##### .writeFC2 (unit, address, length, callback)
Writes "Read input status" (FC=02) request to serial port.
###### unit
The slave unit address.
###### address
The Data Address of the first digital input.
###### length
The total number of digital inputs requested.
###### callback (optional)
Called once the unit returns an answer. The callback should be a function
that looks like: function (error, data) { ... }
```
error - null on success, error string o/w
data - an object with two fildes:
data.data: array of boolean digital inputs (in multiples of 8 = one byte).
data.buffer: raw baffer of bytes returned by slave.
```
----
##### .writeFC3 (unit, address, length, callback)

@@ -199,2 +260,19 @@ Writes "Read Holding Registers" (FC=03) request to serial port.

----
##### .writeFC5 (unit, address, state, callback)
Writes "Force Single Coil" (FC=05) request to serial port.
###### unit
The slave unit address.
###### address
The Data Address of the coil.
###### state
The state to set into the coil (true / false).
###### callback (optional)
Called once the unit returns an answer. The callback should be a function
that looks like: function (error, data) { ... }
----
##### .writeFC16 (unit, address, array, callback)

@@ -201,0 +279,0 @@ Writes "Preset Multiple Registers" (FC=16) request to serial port.

@@ -76,3 +76,3 @@ 'use strict';

describe('#writeFC16() - write registers.', function () {
describe('#writeFC16() - write holding registers.', function () {
it('should write 3 registors [42, 128, 5] without errors', function (done) {

@@ -111,5 +111,5 @@ modbusRTU.writeFC16(1, 8, [42, 128, 5], function(err, data) {

describe('#writeFC4() - read input registers after write.', function () {
describe('#writeFC3() - read holding registers after write.', function () {
it('should read 3 registers [42, 128, 5] without errors', function (done) {
modbusRTU.writeFC4(1, 8, 3, function(err, data) {
modbusRTU.writeFC3(1, 8, 3, function(err, data) {
expect(err).to.be.a('null');

@@ -123,3 +123,41 @@ expect(data).to.have.property('data').with.length(3);

describe('#writeFC5() - force one coil.', function () {
it('should force coil 3 to be true, without errors', function (done) {
modbusRTU.writeFC5(1, 3, true, function(err, data) {
expect(err).to.be.a('null');
expect(data).to.have.property('state');
expect(data.state).to.equal(true);
done()
});
});
});
describe('#writeFC1() - read coils after force coil.', function () {
it('should read coil 3 to be true, without errors', function (done) {
modbusRTU.writeFC1(1, 3, 9, function(err, data) {
expect(err).to.be.a('null');
expect(data).to.have.property('data');
expect(data.data[0]).to.equal(true);
expect(data.data[3]).to.equal(false);
done()
});
});
});
describe('#writeFC1() - read inputs.', function () {
it('should read input 0 to be false, without errors', function (done) {
modbusRTU.writeFC1(1, 0, 9, function(err, data) {
expect(err).to.be.a('null');
expect(data).to.have.property('data');
expect(data.data[0]).to.equal(false);
expect(data.data[3]).to.equal(true);
done()
});
});
});
});

@@ -13,5 +13,11 @@ 'use strict';

var TestPort = function() {
// simulate 14 registers
// simulate 14 input registers
this._registers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// simulate 14 holding registers
this._holding_registers = [0,0,0,0,0,0,0,0, 0xa12b, 0xffff, 0xb21a ];
// simulate 16 coils / digital inputs
this._coils = 0x0000;
events.call(this);

@@ -85,2 +91,20 @@ }

// function code 1 and 2
if (functionCode == 1 || functionCode == 2) {
var address = buf.readUInt16BE(2);
var length = buf.readUInt16BE(4);
// if length is bad, ignore message
if (buf.length != 8) {
return;
}
// build answer
buffer = new Buffer(3 + parseInt((length - 1) / 8 + 1) + 2);
buffer.writeUInt8(parseInt((length - 1) / 8 + 1), 2);
// read coils
buffer.writeUInt16LE(this._coils >> address, 3);
}
// function code 3

@@ -126,2 +150,25 @@ if (functionCode == 3) {

// function code 5
if (functionCode == 5) {
var address = buf.readUInt16BE(2);
var state = buf.readUInt16BE(4);
// if length is bad, ignore message
if (buf.length != 8) {
return;
}
// build answer
buffer = new Buffer(8);
buffer.writeUInt16BE(address, 2);
buffer.writeUInt16BE(state, 4);
// write coil
if (state == 0xff00) {
this._coils |= 1 << address;
} else {
this._coils &= ~(1 << address);
}
}
// function code 16

@@ -144,3 +191,3 @@ if (functionCode == 16) {

for (var i = 0; i < length; i++) {
this._registers[address + i] = buf.readUInt16BE(7 + i * 2);
this._holding_registers[address + i] = buf.readUInt16BE(7 + i * 2);
}

@@ -147,0 +194,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc