Socket
Socket
Sign inDemoInstall

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 4.0.0 to 4.0.1

2

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

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

@@ -6,30 +6,9 @@ 'use strict';

var crc16 = require('./../utils/crc16');
var EXCEPTION_LENGTH = 5;
/**
* check if a buffer chunk can be a modbus answer
* or modbus exception
*
* @param {RTUBufferedPort} modbus
* @param {Buffer} buf the buffer to check.
* @return {boolean} if the buffer can be an answer
*/
function checkData(modbus, buf) {
// check buffer size
if (buf.length != modbus._length && buf.length != 5) return false;
// calculate crc16
var crcIn = buf.readUInt16LE(buf.length - 2);
// check buffer unit-id, command and crc
return (buf[0] == modbus._id &&
(0x7f & buf[1]) == modbus._cmd &&
crcIn == crc16(buf.slice(0, -2)));
}
/**
* Simulate a modbus-RTU port using buffered serial connection
*/
var RTUBufferedPort = function(path, options) {
var modbus = this;
var self = this;

@@ -49,35 +28,30 @@ // options

// register the port data event
this._client.on('data', function(data) {
/* add data to buffer
*/
modbus._buffer = Buffer.concat([modbus._buffer, data]);
this._client.on('data', function onData(data) {
// add data to buffer
self._buffer = Buffer.concat([self._buffer, data]);
/* check if buffer include a complete modbus answer
*/
var length = modbus._length;
var bufferLength = modbus._buffer.length ;
// check if buffer include a complete modbus answer
var expectedLength = self._length;
var bufferLength = self._buffer.length ;
// check data length
if (bufferLength < 5 || length < 6) return;
if (expectedLength < 6 || bufferLength < EXCEPTION_LENGTH) return;
// loop and check length-sized buffer chunks
for (var i = 0; i < (bufferLength - length + 1); i++) {
// cut a length of bytes from buffer
var _data = modbus._buffer.slice(i, i + length);
var maxOffset = bufferLength - EXCEPTION_LENGTH;
for (var i = 0; i <= maxOffset; i++) {
var unitId = self._buffer[i];
var functionCode = self._buffer[i+1];
// check if this is the data we are waiting for
if (checkData(modbus, _data)) {
// adjust i to end of data chunk
i = i + length;
if (unitId !== self._id) continue;
// emit a data signal
modbus.emit('data', _data);
if (functionCode === self._cmd && i + expectedLength <= bufferLength) {
self._emitData(i, expectedLength);
return;
}
if (functionCode === (0x80 | self._cmd) && i + EXCEPTION_LENGTH <= bufferLength) {
self._emitData(i, EXCEPTION_LENGTH);
return;
}
}
/* cut checked data from buffer
*/
if (i) {
modbus._buffer = modbus._buffer.slice(i);
}
});

@@ -90,2 +64,18 @@

/**
* Emit the received response, cut the buffer and reset the internal vars.
* @param {number} start the start index of the response within the buffer
* @param {number} length the length of the response
* @private
*/
RTUBufferedPort.prototype._emitData = function(start, length) {
this.emit('data', this._buffer.slice(start, start + length));
this._buffer = this._buffer.slice(start + length);
// reset internal vars
this._id = 0;
this._cmd = 0;
this._length = 0;
};
/**
* Simulate successful port open

@@ -92,0 +82,0 @@ */

@@ -6,32 +6,10 @@ 'use strict';

var crc16 = require('./../utils/crc16');
var EXCEPTION_LENGTH = 5;
var TELNET_PORT = 2217;
/**
* check if a buffer chunk can be a modbus answer
* or modbus exception
*
* @param {TelnetPort} modbus
* @param {Buffer} buf the buffer to check.
* @return {boolean} if the buffer can be an answer
*/
function checkData(modbus, buf) {
// check buffer size
if (buf.length != modbus._length && buf.length != 5) return false;
// calculate crc16
var crcIn = buf.readUInt16LE(buf.length - 2);
// check buffer unit-id, command and crc
return (buf[0] == modbus._id &&
(0x7f & buf[1]) == modbus._cmd &&
crcIn == crc16(buf.slice(0, -2)));
}
/**
* Simulate a modbus-RTU port using Telent connection
*/
var TelnetPort = function(ip, options) {
var modbus = this;
var self = this;
this.ip = ip;

@@ -54,43 +32,38 @@ this.openFlag = false;

// register the port data event
this._client.on('data', function(data) {
/* add data to buffer
*/
modbus._buffer = Buffer.concat([modbus._buffer, data]);
this._client.on('data', function onData(data) {
// add data to buffer
self._buffer = Buffer.concat([self._buffer, data]);
/* check if buffer include a complete modbus answer
*/
var length = modbus._length;
var bufferLength = modbus._buffer.length ;
// check if buffer include a complete modbus answer
var expectedLength = self._length;
var bufferLength = self._buffer.length ;
// check data length
if (bufferLength < 5 || length < 6) return;
if (expectedLength < 6 || bufferLength < EXCEPTION_LENGTH) return;
// loop and check length-sized buffer chunks
for (var i = 0; i < (bufferLength - length + 1); i++) {
// cut a length of bytes from buffer
var _data = modbus._buffer.slice(i, i + length);
var maxOffset = bufferLength - EXCEPTION_LENGTH;
for (var i = 0; i <= maxOffset; i++) {
var unitId = self._buffer[i];
var functionCode = self._buffer[i+1];
// check if this is the data we are waiting for
if (checkData(modbus, _data)) {
// adjust i to end of data chunk
i = i + length;
if (unitId !== self._id) continue;
// emit a data signal
modbus.emit('data', _data);
if (functionCode === self._cmd && i + expectedLength <= bufferLength) {
self._emitData(i, expectedLength);
return;
}
if (functionCode === (0x80 | self._cmd) && i + EXCEPTION_LENGTH <= bufferLength) {
self._emitData(i, EXCEPTION_LENGTH);
return;
}
}
/* cut checked data from buffer
*/
if (i) {
modbus._buffer = modbus._buffer.slice(i);
}
});
this._client.on('connect', function() {
modbus.openFlag = true;
self.openFlag = true;
});
this._client.on('close', function(had_error) {
modbus.openFlag = false;
self.openFlag = false;
});

@@ -103,2 +76,18 @@

/**
* Emit the received response, cut the buffer and reset the internal vars.
* @param {number} start the start index of the response within the buffer
* @param {number} length the length of the response
* @private
*/
TelnetPort.prototype._emitData = function(start, length) {
this.emit('data', this._buffer.slice(start, start + length));
this._buffer = this._buffer.slice(start + length);
// reset internal vars
this._id = 0;
this._cmd = 0;
this._length = 0;
};
/**
* Simulate successful port open

@@ -105,0 +94,0 @@ */

@@ -70,2 +70,19 @@ 'use strict';

});
it('should return a valid Modbus RTU exception', function(done) {
port.once('data', function(data) {
expect(data.toString('hex')).to.equal('1183044136');
done();
});
port.open(function() {
port.write(new Buffer('1103006B00037687', 'hex'));
setTimeout(function() {
port._client.receive(new Buffer('11', 'hex'));
port._client.receive(new Buffer('83', 'hex'));
port._client.receive(new Buffer('04', 'hex'));
port._client.receive(new Buffer('41', 'hex'));
port._client.receive(new Buffer('36', 'hex'));
});
});
});
});

@@ -72,0 +89,0 @@

@@ -70,2 +70,19 @@ 'use strict';

});
it('should return a valid Modbus RTU exception', function(done) {
port.once('data', function(data) {
expect(data.toString('hex')).to.equal('1183044136');
done();
});
port.open(function() {
port.write(new Buffer('1103006B00037687', 'hex'));
setTimeout(function() {
port._client.receive(new Buffer('11', 'hex'));
port._client.receive(new Buffer('83', 'hex'));
port._client.receive(new Buffer('04', 'hex'));
port._client.receive(new Buffer('41', 'hex'));
port._client.receive(new Buffer('36', 'hex'));
});
});
});
});

@@ -72,0 +89,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