jsmodebus
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 1;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
let fc = pdu.readUInt8(0);
|
||||
if (fc !== FC) {
|
||||
cb(`ReadCoils: Invalid FC ${fc}`);
|
||||
} else {
|
||||
let byteCount = pdu.readUInt8(1);
|
||||
// let bitCount = byteCount * 8;
|
||||
let resp = {
|
||||
unitId,
|
||||
fc: fc,
|
||||
byteCount: byteCount,
|
||||
payload: pdu.slice(2),
|
||||
data: []
|
||||
};
|
||||
|
||||
let counter = 0;
|
||||
for (let i = 0; i < byteCount; i+=1) {
|
||||
let h = 1, cur = pdu.readUInt8(2 + i);
|
||||
for (let j = 0; j < 8; j++) {
|
||||
resp.data[counter] = (cur & h) > 0 ;
|
||||
h = h << 1;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
cb && cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.readCoils = (unitId, start, quantity) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdu = Put().word8(FC).word16be(start).word16be(quantity).buffer();
|
||||
|
||||
this.queueRequest(unitId, FC, pdu, (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 2;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
let fc = pdu.readUInt8(0);
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`ReadDiscreteInputs: Invalid FC ${fc}`);
|
||||
} else {
|
||||
let byteCount = pdu.readUInt8(1);
|
||||
let counter = 0;
|
||||
let resp = {
|
||||
unitId,
|
||||
fc: fc,
|
||||
byteCount: byteCount,
|
||||
payload: pdu.slice(2),
|
||||
data: []
|
||||
};
|
||||
|
||||
for (let i = 0; i < byteCount; i++) {
|
||||
let h = 1, cur = pdu.readUInt8(2 + i);
|
||||
for (let j = 0; j < 8; j+=1) {
|
||||
resp.data[counter] = (cur & h) > 0 ;
|
||||
h = h << 1;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
cb && cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.readDiscreteInputs = (unitId, start, quantity) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (quantity > 2000) {
|
||||
return reject('quantity is too big');
|
||||
}
|
||||
|
||||
let pdu = Put().word8be(FC).word16be(start).word16be(quantity).buffer();
|
||||
|
||||
this.queueRequest(unitId, FC, pdu, (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 3;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
let fc = pdu.readUInt8(0);
|
||||
if (fc !== FC) {
|
||||
cb(`ReadHoldingRegisters: Invalid FC ${fc}`);
|
||||
} else {
|
||||
let byteCount = pdu.readUInt8(1);
|
||||
|
||||
let resp = {
|
||||
unitId,
|
||||
fc: fc,
|
||||
byteCount: byteCount,
|
||||
payload: pdu.slice(2),
|
||||
register: []
|
||||
};
|
||||
const registerCount = byteCount / 2;
|
||||
|
||||
for (let i = 0; i < registerCount; i++) {
|
||||
resp.register.push(pdu.readUInt16BE(2 + (i * 2)));
|
||||
}
|
||||
|
||||
cb && cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.readHoldingRegisters = (unitId, start, quantity) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdu = Put().word8be(FC).word16be(start).word16be(quantity).buffer();
|
||||
|
||||
this.queueRequest(unitId, FC, pdu, (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 4;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
let fc = pdu.readUInt8(0);
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`ReadInputRegisters: Invalid FC ${fc}`);
|
||||
} else {
|
||||
let byteCount = pdu.readUInt8(1);
|
||||
|
||||
let resp = {
|
||||
unitId,
|
||||
fc: fc,
|
||||
byteCount: byteCount,
|
||||
payload: pdu.slice(2),
|
||||
register: []
|
||||
};
|
||||
const registerCount = byteCount / 2;
|
||||
|
||||
for (let i = 0; i < registerCount; i++) {
|
||||
resp.register.push(pdu.readUInt16BE(2 + (i * 2)));
|
||||
}
|
||||
|
||||
cb && cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.readInputRegisters = (unitId, start, quantity) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdu = Put().word8be(FC).word16be(start).word16be(quantity).buffer();
|
||||
|
||||
this.queueRequest(unitId, FC, pdu, (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 15;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const startAddress = pdu.readUInt16BE(1);
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
|
||||
let resp = {
|
||||
unitId: unitId,
|
||||
fc: fc,
|
||||
startAddress: startAddress,
|
||||
quantity: quantity
|
||||
};
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`WriteMultipleCoils: Invalid FC ${fc}`);
|
||||
} else {
|
||||
cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.writeMultipleCoils = (unitId, startAddress, data, N) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdu = Put().word8(FC).word16be(startAddress);
|
||||
|
||||
if (data instanceof Buffer) {
|
||||
pdu.word16be(N).word8(data.length).put(data);
|
||||
} else if (data instanceof Array) {
|
||||
if (data.length > 1968) {
|
||||
reject('Length is too big');
|
||||
return;
|
||||
}
|
||||
|
||||
const byteCount = Math.ceil(data.length / 8);
|
||||
let curByte = 0;
|
||||
let cntr = 0;
|
||||
|
||||
pdu.word16be(data.length).word8(byteCount);
|
||||
|
||||
for (let i = 0; i < data.length; i += 1) {
|
||||
curByte += data[i] ? Math.pow(2, cntr) : 0;
|
||||
|
||||
cntr = (cntr + 1) % 8;
|
||||
|
||||
if (cntr === 0 || i === coils.length - 1 ) {
|
||||
pdu.word8(curByte);
|
||||
curByte = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.queueRequest(unitId, FC, pdu.buffer(), (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 16;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
const fc = pdu.readUInt8(0);
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`WriteMultipleRegisters: Invalid FC ${fc}`);
|
||||
} else {
|
||||
const startAddress = pdu.readUInt16BE(1);
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
|
||||
let resp = {
|
||||
unitId: unitId,
|
||||
fc: fc,
|
||||
startAddress: startAddress,
|
||||
quantity: quantity
|
||||
};
|
||||
cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.writeMultipleRegisters = (unitId, startAddress, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdu = Put().word8(FC).word16be(startAddress);
|
||||
if (data instanceof Buffer) {
|
||||
if (data.length / 2 > 0x007b) {
|
||||
reject('Length is too big');
|
||||
return;
|
||||
}
|
||||
|
||||
pdu.word16be(data.length / 2).word8(data.length).put(data);
|
||||
} else if (data instanceof Array) {
|
||||
if (data.length > 0x007b) {
|
||||
reject('Length is too big');
|
||||
return;
|
||||
}
|
||||
|
||||
let byteCount = Math.ceil(data.length * 2);
|
||||
pdu.word16be(data.length).word8(byteCount);
|
||||
|
||||
for (let i = 0; i < data.length; i += 1) {
|
||||
pdu.word16be(data[i]);
|
||||
}
|
||||
} else {
|
||||
reject('Invalid data');
|
||||
return;
|
||||
}
|
||||
|
||||
this.queueRequest(unitId, FC, pdu.buffer(), (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 5;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const outputAddress = pdu.readUInt16BE(1);
|
||||
const outputValue = pdu.readUInt16BE(3);
|
||||
|
||||
let resp = {
|
||||
unitId: unitId,
|
||||
fc: fc,
|
||||
outputAddress: outputAddress,
|
||||
outputValue: outputValue === 0x0000 ? false : (outputValue === 0xFF00 ? true : undefined)
|
||||
};
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`WriteSingleCoil: Invalid FC ${fc}`);
|
||||
} else {
|
||||
cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.writeSingleCoil = (unitId, address, value) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const payload = (value instanceof Buffer) ? (value.readUInt8(0) > 0) : value;
|
||||
const pdu = Put().word8be(FC).word16be(address).word16be(payload ? 0xff00 : 0x0000);
|
||||
|
||||
this.queueRequest(unitId, FC, pdu.buffer(), (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 6;
|
||||
|
||||
let init = () => this.addResponseHandler(FC, onResponse);
|
||||
|
||||
let onResponse = (unitId, pdu, cb) => {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const registerAddress = pdu.readUInt16BE(1);
|
||||
const registerValue = pdu.readUInt16BE(3);
|
||||
|
||||
let resp = {
|
||||
unitId: unitId,
|
||||
fc: fc,
|
||||
registerAddress: registerAddress,
|
||||
registerValue: registerValue,
|
||||
registerAddressRaw: pdu.slice(1,2),
|
||||
registerValueRaw: pdu.slice(3,2)
|
||||
};
|
||||
|
||||
if (fc !== FC) {
|
||||
cb(`WriteSingleRegister: Invalid FC ${fc}`);
|
||||
} else {
|
||||
cb(null, resp);
|
||||
}
|
||||
};
|
||||
|
||||
this.writeSingleRegister = (unitId, address, value) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const payload = (value instanceof Buffer) ? value : Put().word16be(value).buffer();
|
||||
const pdu = Put().word8be(FC).word16be(address).put(payload);
|
||||
|
||||
this.queueRequest(unitId, FC, pdu.buffer(), (err, resp) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 1;
|
||||
|
||||
let init = () => {
|
||||
this.log.debug('initiating read coils request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
this.log.debug('handling read coils request.');
|
||||
|
||||
if (pdu.length !== 5) {
|
||||
cb(Put().word8(0x81).word8(0x02).buffer());
|
||||
} else {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const address = pdu.readUInt16BE(1);
|
||||
const byteAddress = address * 2;
|
||||
const value = pdu.readUInt16BE(3);
|
||||
|
||||
this.emit('preWriteSingleRegisterRequest', byteAddress, value);
|
||||
|
||||
let mem = this.getHolding();
|
||||
|
||||
if (byteAddress + 2 > mem.length) {
|
||||
cb(Put().word8(0x86).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x06).word16be(address).word16be(value).buffer();
|
||||
mem.writeUInt16BE(value, byteAddress);
|
||||
this.emit('postWriteSingleRegisterRequest', byteAddress, value);
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 2;
|
||||
|
||||
let init = () => {
|
||||
this.log.debug('initiating read discrete inputs request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
this.log.debug('handling read discrete inputs request.');
|
||||
|
||||
if (pdu.length !== 5) {
|
||||
cb(Put().word8(0x82).word8(0x02).buffer());
|
||||
} else {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const start = pdu.readUInt16BE(1);
|
||||
const quantity = pdu.readUInt16BE( 3);
|
||||
|
||||
this.emit('readDiscreteInputsRequest', start, quantity);
|
||||
|
||||
let mem = this.getDiscrete();
|
||||
|
||||
if (!quantity || start + quantity > mem.length * 8) {
|
||||
cb(Put().word8(0x82).word8(0x02).buffer());
|
||||
} else {
|
||||
let val = 0;
|
||||
let thisByteBitCount = 0;
|
||||
let response = Put().word8(0x02).word8(Math.floor(quantity / 8) + (quantity % 8 === 0 ? 0 : 1));
|
||||
|
||||
for (let totalBitCount = start; totalBitCount < start + quantity; totalBitCount += 1) {
|
||||
let buf = mem.readUInt8(Math.floor(totalBitCount / 8));
|
||||
let mask = 1 << (totalBitCount % 8);
|
||||
|
||||
if (buf & mask) {
|
||||
val += 1 << (thisByteBitCount % 8)
|
||||
}
|
||||
|
||||
thisByteBitCount += 1;
|
||||
|
||||
if (thisByteBitCount % 8 === 0 || totalBitCount === (start + quantity) - 1) {
|
||||
response.word8(val);
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cb(response.buffer());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
init();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 3;
|
||||
let init = () => {
|
||||
this.log.debug('initiating read holding registers request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
if (pdu.length !== 5) {
|
||||
this.log.warn('wrong pdu length.');
|
||||
cb(Put().word8(0x83).word8(0x02).buffer());
|
||||
} else {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const start = pdu.readUInt16BE(1);
|
||||
const byteStart = start * 2;
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
|
||||
this.emit('readHoldingRegistersRequest', byteStart, quantity);
|
||||
|
||||
let mem = this.getHolding();
|
||||
|
||||
if (!quantity || byteStart + (quantity * 2) > mem.length) {
|
||||
this.log.debug('request outside register boundaries.');
|
||||
cb(Put().word8(0x83).word8(0x02).buffer());
|
||||
return;
|
||||
}
|
||||
|
||||
let response = Put().word8(0x03).word8(quantity * 2);
|
||||
|
||||
for (let i = byteStart; i < byteStart + (quantity * 2); i += 2) {
|
||||
response.word16be(mem.readUInt16BE(i));
|
||||
}
|
||||
|
||||
this.log.debug('finished read holding register request.');
|
||||
cb(response.buffer());
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 4;
|
||||
let init = () => {
|
||||
this.log.debug('initiating read input registers request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
this.log.debug('handling read input registers request.');
|
||||
if (pdu.length !== 5) {
|
||||
cb(Put().word8(0x84).word8(0x02).buffer());
|
||||
} else {
|
||||
const fc = pdu.readUInt8(0);
|
||||
const start = pdu.readUInt16BE(1);
|
||||
const byteStart = start * 2;
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
|
||||
this.emit('readInputRegistersRequest', byteStart, quantity);
|
||||
|
||||
let mem = this.getInput();
|
||||
|
||||
if (!quantity || byteStart + (quantity * 2) > mem.length) {
|
||||
cb(Put().word8(0x84).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x04).word8(quantity * 2);
|
||||
|
||||
for (let i = byteStart; i < byteStart + (quantity * 2); i += 2) {
|
||||
response.word16be(mem.readUInt16BE(i));
|
||||
}
|
||||
|
||||
cb(response.buffer());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 15;
|
||||
let init = () => {
|
||||
this.log.debug('initiating write multiple coils request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
this.log.debug('handling write multiple coils request.');
|
||||
|
||||
if (pdu.length < 3) {
|
||||
cb(Put().word8(0x8F).word8(0x02).buffer());
|
||||
} else {
|
||||
// const fc = pdu.readUInt8(0);
|
||||
const start = pdu.readUInt16BE(1);
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
const byteCount = pdu.readUInt8(5);
|
||||
|
||||
this.emit('preWriteMultipleCoilsRequest', start, quantity, byteCount);
|
||||
|
||||
let mem = this.getCoils();
|
||||
|
||||
// error response
|
||||
if (!quantity || start + quantity > mem.length * 8) {
|
||||
cb(Put().word8(0x8F).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x0F).word16be(start).word16be(quantity).buffer();
|
||||
let oldValue;
|
||||
let newValue, current = pdu.readUInt8(6);
|
||||
let j = 0;
|
||||
|
||||
for (let i = start; i < start + quantity; i += 1) {
|
||||
// reading old value from the coils register
|
||||
oldValue = mem.readUInt8(Math.floor(i / 8));
|
||||
|
||||
// apply new value
|
||||
if ((Math.pow(2, j % 8) & current)) {
|
||||
newValue = oldValue | Math.pow(2, i % 8);
|
||||
} else {
|
||||
newValue = oldValue & ~Math.pow(2, i % 8);
|
||||
}
|
||||
|
||||
// write to buffer
|
||||
mem.writeUInt8(newValue, Math.floor(i / 8));
|
||||
|
||||
// read new value from request pdu
|
||||
j += 1;
|
||||
|
||||
if (j % 8 === 0 && j < quantity) {
|
||||
current = pdu.readUInt8(6 + Math.floor(j / 8));
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('postWriteMultipleCoilsRequest', start, quantity, byteCount);
|
||||
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 16;
|
||||
let init = () => {
|
||||
this.log.debug('initiating write multiple registers request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
if (pdu.length < 3) {
|
||||
cb(Put().word8(0x90).word8(0x02).buffer());
|
||||
} else {
|
||||
// const fc = pdu.readUInt8(0);
|
||||
const start = pdu.readUInt16BE(1);
|
||||
const byteStart = start * 2;
|
||||
const quantity = pdu.readUInt16BE(3);
|
||||
const byteCount = pdu.readUInt8(5);
|
||||
|
||||
if (quantity > 0x007b) {
|
||||
cb(Put().word8(0x90).word8(0x03).buffer());
|
||||
} else {
|
||||
this.emit('preWriteMultipleRegistersRequest', byteStart, quantity, byteCount);
|
||||
|
||||
let mem = this.getHolding();
|
||||
|
||||
if (!quantity || byteStart + (quantity * 2) > mem.length) {
|
||||
cb(Put().word8(0x90).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x10).word16be(start).word16be(quantity).buffer();
|
||||
let j = 0;
|
||||
|
||||
for (let i = byteStart; i < byteStart + byteCount; i += 1) {
|
||||
mem.writeUInt8(pdu.readUInt8(6 + j), i);
|
||||
j++;
|
||||
}
|
||||
|
||||
this.emit('postWriteMultipleRegistersRequest', byteStart, quantity, byteCount);
|
||||
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 5;
|
||||
let init = () => {
|
||||
this.log.debug('initiating write single coil request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
if (pdu.length !== 5) {
|
||||
cb(Put().word8(0x85).word8(0x02).buffer());
|
||||
} else {
|
||||
// const fc = pdu.readUInt8(0);
|
||||
const address = pdu.readUInt16BE(1);
|
||||
const value = (pdu.readUInt16BE(3) === 0x0000);
|
||||
|
||||
if (pdu.readUInt16BE(3) !== 0x0000 && pdu.readUInt16BE(3) !== 0xFF00) {
|
||||
cb(Put().word8(0x85).word8(0x03).buffer());
|
||||
} else {
|
||||
this.emit('preWriteSingleCoilRequest', address, value);
|
||||
|
||||
let mem = this.getCoils();
|
||||
|
||||
if (address + 1 > mem.length * 8) {
|
||||
cb(Put().word8(0x85).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x05).word16be(address).word16be(value ? 0xFF00 : 0x0000);
|
||||
let oldValue = mem.readUInt8(Math.floor(address / 8));
|
||||
let newValue;
|
||||
|
||||
if (value) {
|
||||
newValue = oldValue | Math.pow(2, address % 8);
|
||||
} else {
|
||||
newValue = oldValue & ~Math.pow(2, address % 8);
|
||||
}
|
||||
|
||||
mem.writeUInt8(newValue, Math.floor(address / 8));
|
||||
|
||||
this.emit('postWriteSingleCoilRequest', address, value);
|
||||
|
||||
cb(response.buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
const Stampit = require('stampit');
|
||||
const Put = require('put');
|
||||
|
||||
module.exports = Stampit()
|
||||
.init(function () {
|
||||
const FC = 6;
|
||||
let init = () => {
|
||||
this.log.debug('initiating write single register request handler.');
|
||||
this.responseDelay = this.responseDelay || 0;
|
||||
this.setRequestHandler(FC, onRequest);
|
||||
};
|
||||
|
||||
let _onRequest = (pdu, cb) => {
|
||||
this.log.debug('handling write single register request.');
|
||||
|
||||
if (pdu.length !== 5) {
|
||||
cb(Put().word8(0x86).word8(0x02).buffer());
|
||||
} else {
|
||||
// const fc = pdu.readUInt8(0);
|
||||
const address = pdu.readUInt16BE(1);
|
||||
const byteAddress = address * 2;
|
||||
const value = pdu.readUInt16BE(3);
|
||||
|
||||
this.emit('preWriteSingleRegisterRequest', byteAddress, value);
|
||||
|
||||
let mem = this.getHolding();
|
||||
|
||||
if (byteAddress + 2 > mem.length) {
|
||||
cb(Put().word8(0x86).word8(0x02).buffer());
|
||||
} else {
|
||||
let response = Put().word8(0x06).word16be(address).word16be(value).buffer();
|
||||
mem.writeUInt16BE(value, byteAddress);
|
||||
this.emit('postWriteSingleRegisterRequest', byteAddress, value);
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let onRequest = (pdu, cb) => {
|
||||
if (this.responseDelay) {
|
||||
setTimeout(_onRequest, this.responseDelay, pdu, cb);
|
||||
} else {
|
||||
setImmediate(_onRequest, pdu, cb);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
Reference in New Issue
Block a user