node-modbus
Advanced tools
Comparing version 2.0.5 to 2.0.6
@@ -1,30 +0,29 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(1, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handeling read coils response."); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1), | ||
bitCount = byteCount * 8; | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1), | ||
bitCount = byteCount * 8; | ||
var resp = { | ||
fc: fc, | ||
byteCount: byteCount, | ||
coils: [] | ||
}; | ||
fc : fc, | ||
byteCount : byteCount, | ||
payload : pdu.slice(2), | ||
coils : [] | ||
}; | ||
@@ -37,30 +36,30 @@ if (fc !== 1) { | ||
var cntr = 0; | ||
for (var i = 0; i < byteCount; i += 1) { | ||
for (var i = 0; i < byteCount; i+=1) { | ||
var h = 1, cur = pdu.readUInt8(2 + i); | ||
for (var j = 0; j < 8; j += 1) { | ||
resp.coils[cntr] = (cur & h) > 0; | ||
for (var j = 0; j < 8; j+=1) { | ||
resp.coils[cntr] = (cur & h) > 0 ; | ||
h = h << 1; | ||
cntr += 1; | ||
} | ||
} | ||
} | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.readCoils = function (start, quantity) { | ||
var fc = 1, | ||
defer = Q.defer(), | ||
pdu = Put().word8(fc).word16be(start).word16be(quantity).buffer(); | ||
var fc = 1, | ||
defer = Q.defer(), | ||
pdu = Put().word8(fc).word16be(start).word16be(quantity).buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
}; | ||
init(); | ||
}); |
@@ -1,28 +0,27 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(2, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handeling read discrete inputs response."); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1), | ||
cntr = 0, | ||
resp = { | ||
fc: fc, | ||
byteCount: byteCount, | ||
coils: [] | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1), | ||
cntr = 0, | ||
resp = { | ||
fc : fc, | ||
byteCount : byteCount, | ||
payload : pdu.slice(2), | ||
coils : [] | ||
}; | ||
@@ -35,38 +34,38 @@ | ||
for (var i = 0; i < byteCount; i += 1) { | ||
for (var i = 0; i < byteCount; i+=1) { | ||
var h = 1, cur = pdu.readUInt8(2 + i); | ||
for (var j = 0; j < 8; j += 1) { | ||
resp.coils[cntr] = (cur & h) > 0; | ||
for (var j = 0; j < 8; j+=1) { | ||
resp.coils[cntr] = (cur & h) > 0 ; | ||
h = h << 1; | ||
cntr += 1; | ||
} | ||
} | ||
} | ||
request.defer.resolve(resp); | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.readDiscreteInputs = function (start, quantity) { | ||
var fc = 2, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(2).word16be(start).word16be(quantity).buffer(); | ||
var fc = 2, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(2).word16be(start).word16be(quantity).buffer(); | ||
if (quantity > 2000) { | ||
if (quantity > 2000) { | ||
defer.reject(); | ||
return defer.promise; | ||
defer.reject(); | ||
return defer.promise; | ||
} | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
}; | ||
init(); | ||
}); |
@@ -1,28 +0,27 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(3, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling read holding registers response."); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
var resp = { | ||
fc: fc, | ||
byteCount: byteCount, | ||
register: [] | ||
fc : fc, | ||
byteCount : byteCount, | ||
payload : pdu.slice(2), | ||
register : [ ] | ||
}; | ||
@@ -42,14 +41,14 @@ | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.readHoldingRegisters = function (start, quantity) { | ||
this.log.debug('Starting read holding registers request.'); | ||
this.log.debug('Starting read holding registers request.'); | ||
var fc = 3, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(3).word16be(start).word16be(quantity).buffer(); | ||
var fc = 3, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(3).word16be(start).word16be(quantity).buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
@@ -62,3 +61,3 @@ | ||
init(); | ||
}); |
@@ -1,28 +0,27 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(4, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling read input registers response."); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
var resp = { | ||
fc: fc, | ||
byteCount: byteCount, | ||
register: [] | ||
fc : fc, | ||
byteCount : byteCount, | ||
payload : pdu.slice(2), | ||
register : [] | ||
}; | ||
@@ -42,12 +41,12 @@ | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.readInputRegisters = function (start, quantity) { | ||
var fc = 4, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(4).word16be(start).word16be(quantity).buffer(); | ||
var fc = 4, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(4).word16be(start).word16be(quantity).buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
@@ -60,3 +59,3 @@ | ||
init(); | ||
}); |
@@ -1,6 +0,4 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
Q = require('q'), | ||
Put = require('put'); | ||
@@ -10,21 +8,21 @@ | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(15, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling multiple coils response."); | ||
var fc = pdu.readUInt8(0), | ||
startAddress = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
startAddress = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var resp = { | ||
fc: fc, | ||
startAddress: startAddress, | ||
quantity: quantity | ||
fc : fc, | ||
startAddress : startAddress, | ||
quantity : quantity | ||
}; | ||
@@ -39,44 +37,49 @@ | ||
}.bind(this); | ||
this.writeMultipleCoils = function (startAddress, coils) { | ||
this.writeMultipleCoils = function (startAddress, coils, N) { | ||
var defer = Q.defer(); | ||
var fc = 15, | ||
pdu = Put() | ||
.word8(fc) | ||
.word16be(startAddress) | ||
if (coils.length > 1968) { | ||
if (coils instanceof Buffer) { | ||
pdu.word16be(N) | ||
.word8(coils.length) | ||
.put(coils) | ||
} else if (coils instanceof Array) { | ||
if (coils.length > 1968) { | ||
defer.reject(); | ||
return; | ||
} | ||
} | ||
var byteCount = Math.ceil(coils.length / 8), | ||
curByte = 0, | ||
cntr = 0 | ||
var fc = 15, | ||
byteCount = Math.ceil(coils.length / 8), | ||
curByte = 0, | ||
cntr = 0, | ||
pdu = Put() | ||
.word8(fc) | ||
.word16be(startAddress) | ||
.word16be(coils.length) | ||
.word8(byteCount); | ||
pdu.word16be(coils.length) | ||
.word8(byteCount); | ||
for (var i = 0; i < coils.length; i += 1) { | ||
for (var i = 0; i < coils.length; i += 1) { | ||
curByte += coils[i] ? Math.pow(2, cntr) : 0; | ||
curByte += coils[i]?Math.pow(2, cntr):0; | ||
cntr = (cntr + 1) % 8; | ||
cntr = (cntr + 1) % 8; | ||
if (cntr === 0) { | ||
pdu.word8(curByte); | ||
} | ||
if (cntr === 0 || i === coils.length - 1 ) { | ||
pdu.word8(curByte) | ||
curByte = 0 | ||
} | ||
} | ||
} | ||
pdu = pdu.buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
@@ -87,3 +90,3 @@ | ||
init(); | ||
}); |
@@ -1,6 +0,4 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
Q = require('q'), | ||
Put = require('put'); | ||
@@ -10,21 +8,21 @@ | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(16, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling multiple registers response."); | ||
var fc = pdu.readUInt8(0), | ||
startAddress = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
startAddress = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var resp = { | ||
fc: fc, | ||
startAddress: startAddress, | ||
quantity: quantity | ||
fc : fc, | ||
startAddress : startAddress, | ||
quantity : quantity | ||
}; | ||
@@ -39,29 +37,41 @@ | ||
}.bind(this); | ||
this.writeMultipleRegisters = function (startAddress, register) { | ||
var defer = Q.defer(); | ||
var fc = 16, | ||
pdu = Put() | ||
.word8(fc) | ||
.word16be(startAddress) | ||
if (register.length > 0x007b) { | ||
if(register instanceof Buffer) { | ||
if(register.length/2 > 0x007b) { | ||
defer.reject(); | ||
return; | ||
} | ||
pdu.word16be(register.length/2) | ||
.word8(register.length) | ||
.put(register) | ||
} | ||
else if(register instanceof Array) { | ||
var fc = 16, | ||
byteCount = Math.ceil(register.length * 2), | ||
curByte = 0, | ||
pdu = Put() | ||
.word8(fc) | ||
.word16be(startAddress) | ||
.word16be(register.length) | ||
.word8(byteCount); | ||
if (register.length > 0x007b) { | ||
defer.reject(); | ||
return; | ||
} | ||
for (var i = 0; i < register.length; i += 1) { | ||
var byteCount = Math.ceil(register.length * 2), | ||
curByte = 0 | ||
pdu.word16be(register[i]); | ||
pdu.word16be(register.length) | ||
.word8(byteCount) | ||
for (var i = 0; i < register.length; i += 1) { | ||
pdu.word16be(register[i]); | ||
} | ||
} else { | ||
defer.reject(); | ||
} | ||
@@ -71,12 +81,9 @@ | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
}; | ||
init(); | ||
}); |
@@ -1,28 +0,26 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(5, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling write single coil response."); | ||
var fc = pdu.readUInt8(0), | ||
outputAddress = pdu.readUInt16BE(1), | ||
outputValue = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
outputAddress = pdu.readUInt16BE(1), | ||
outputValue = pdu.readUInt16BE(3); | ||
var resp = { | ||
fc: fc, | ||
outputAddress: outputAddress, | ||
outputValue: outputValue === 0x0000 ? false : outputValue === 0xFF00 ? true : undefined | ||
fc : fc, | ||
outputAddress : outputAddress, | ||
outputValue : outputValue === 0x0000?false:outputValue===0xFF00?true:undefined | ||
}; | ||
@@ -36,20 +34,22 @@ | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.writeSingleCoil = function (address, value) { | ||
var fc = 5, | ||
defer = Q.defer(), | ||
payload = (value instanceof Buffer) ? (value.readUInt8(0) > 0) : value, | ||
pdu = Put().word8be(5).word16be(address).word16be(payload?0xff00:0x0000).buffer(); | ||
var fc = 5, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(5).word16be(address).word16be(value ? 0xff00 : 0x0000).buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
}; | ||
init(); | ||
}); |
@@ -1,29 +0,29 @@ | ||
"use strict"; | ||
var Stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Q = require('q'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
module.exports = Stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.addResponseHandler(6, onResponse); | ||
}.bind(this); | ||
var onResponse = function (pdu, request) { | ||
this.log.debug("handling write single register response."); | ||
var fc = pdu.readUInt8(0), | ||
registerAddress = pdu.readUInt16BE(1), | ||
registerValue = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
registerAddress = pdu.readUInt16BE(1), | ||
registerValue = pdu.readUInt16BE(3); | ||
var resp = { | ||
fc: fc, | ||
registerAddress: registerAddress, | ||
registerValue: registerValue | ||
fc : fc, | ||
registerAddress : registerAddress, | ||
registerValue : registerValue, | ||
registerAddressRaw: pdu.slice(1,2), | ||
registerValueRaw: pdu.slice(3,2) | ||
}; | ||
@@ -37,19 +37,20 @@ | ||
request.defer.resolve(resp); | ||
}.bind(this); | ||
this.writeSingleRegister = function (address, value) { | ||
var fc = 6, | ||
defer = Q.defer(), | ||
payload = (value instanceof Buffer) ? value : Put().word16be(value).buffer(), | ||
pdu = Put().word8be(6).word16be(address).put(payload).buffer(); | ||
var fc = 6, | ||
defer = Q.defer(), | ||
pdu = Put().word8be(6).word16be(address).word16be(value).buffer(); | ||
this.queueRequest(fc, pdu, defer); | ||
return defer.promise; | ||
}; | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating read coils request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(1, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -31,3 +29,3 @@ | ||
if (pdu.length !== 5) { | ||
cb(Put().word8(0x81).word8(0x02).buffer()); | ||
@@ -38,5 +36,5 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
@@ -48,3 +46,3 @@ this.emit('readCoilsRequest', start, quantity); | ||
if (start > mem.length * 8 || start + quantity > mem.length * 8) { | ||
cb(Put().word8(0x81).word8(0x02).buffer()); | ||
@@ -55,20 +53,22 @@ return; | ||
var val = 0, | ||
j = 0, | ||
var val = 0, | ||
thisByteBitCount = 0, | ||
response = Put().word8(0x01).word8(Math.floor(quantity / 8) + (quantity % 8 === 0 ? 0 : 1)); | ||
for (var i = start; i < start + quantity; i += 1) { | ||
for (var totalBitCount = start; totalBitCount < start + quantity; totalBitCount += 1) { | ||
var buf = mem.readUInt8(Math.floor(totalBitCount / 8)) | ||
var mask = 1 << (totalBitCount % 8) | ||
val += mem.readUInt8(Math.floor(i / 8)) & Math.pow(2, i % 8); | ||
if(buf & mask) { | ||
val += 1 << (thisByteBitCount % 8) | ||
} | ||
thisByteBitCount += 1; | ||
j += 1; | ||
if (j % 8 === 0 || i === (start + quantity) - 1) { | ||
if (thisByteBitCount % 8 === 0 || totalBitCount === (start + quantity) - 1) { | ||
response.word8(val); | ||
val = 0; | ||
} | ||
} | ||
@@ -79,8 +79,8 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,11 +0,9 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var handler = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating read discrete inputs request handler.'); | ||
@@ -17,6 +15,7 @@ | ||
this.setRequestHandler(2, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +29,3 @@ | ||
if (pdu.length !== 5) { | ||
cb(Put().word8(0x82).word8(0x02).buffer()); | ||
@@ -37,5 +36,5 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3); | ||
@@ -47,3 +46,3 @@ this.emit('readDiscreteInputsRequest', start, quantity); | ||
if (start > mem.length * 8 || start + quantity > mem.length * 8) { | ||
cb(Put().word8(0x82).word8(0x02).buffer()); | ||
@@ -54,19 +53,22 @@ return; | ||
var val = 0, | ||
j = 0, | ||
var val = 0, | ||
thisByteBitCount = 0, | ||
response = Put().word8(0x02).word8(Math.floor(quantity / 8) + (quantity % 8 === 0 ? 0 : 1)); | ||
for (var i = start; i < start + quantity; i += 1) { | ||
for (var totalBitCount = start; totalBitCount < start + quantity; totalBitCount += 1) { | ||
var buf = mem.readUInt8(Math.floor(totalBitCount / 8)) | ||
var mask = 1 << (totalBitCount % 8) | ||
val += mem.readUInt8(Math.floor(i / 8)) & Math.pow(2, i % 8); | ||
if(buf & mask) { | ||
val += 1 << (thisByteBitCount % 8) | ||
} | ||
thisByteBitCount += 1; | ||
j += 1; | ||
if (j % 8 === 0 || i === (start + quantity) - 1) { | ||
if (thisByteBitCount % 8 === 0 || totalBitCount === (start + quantity) - 1) { | ||
response.word8(val); | ||
val = 0; | ||
} | ||
} | ||
@@ -77,10 +79,10 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); | ||
module.exports = handler; |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating read holding registers request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(3, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -38,6 +36,6 @@ | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3); | ||
@@ -50,3 +48,3 @@ this.emit('readHoldingRegistersRequest', byteStart, quantity); | ||
this.log.debug('request outside register boundaries.'); | ||
this.log.debug('request outside register boundaries.'); | ||
cb(Put().word8(0x83).word8(0x02).buffer()); | ||
@@ -60,3 +58,3 @@ return; | ||
for (var i = byteStart; i < byteStart + (quantity * 2); i += 2) { | ||
response.word16be(mem.readUInt16BE(i)); | ||
@@ -71,8 +69,8 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating read input registers request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(4, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +28,3 @@ | ||
if (pdu.length !== 5) { | ||
cb(Put().word8(0x84).word8(0x02).buffer()); | ||
@@ -37,6 +35,6 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3); | ||
@@ -48,3 +46,3 @@ this.emit('readInputRegistersRequest', byteStart, quantity); | ||
if (byteStart > mem.length || byteStart + (quantity * 2) > mem.length) { | ||
cb(Put().word8(0x84).word8(0x02).buffer()); | ||
@@ -58,3 +56,3 @@ return; | ||
for (var i = byteStart; i < byteStart + (quantity * 2); i += 2) { | ||
response.word16be(mem.readUInt16BE(i)); | ||
@@ -67,8 +65,8 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating write multiple coils request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(15, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +28,3 @@ | ||
if (pdu.length < 3) { | ||
cb(Put().word8(0x8F).word8(0x02).buffer()); | ||
@@ -37,6 +35,6 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3), | ||
byteCount = pdu.readUInt8(5); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
quantity = pdu.readUInt16BE(3), | ||
byteCount = pdu.readUInt8(5); | ||
@@ -48,3 +46,3 @@ this.emit('preWriteMultipleCoilsRequest', start, quantity, byteCount); | ||
if (start > mem.length * 8 || start + quantity > mem.length * 8) { | ||
cb(Put().word8(0x8F).word8(0x02).buffer()); | ||
@@ -56,18 +54,15 @@ return; | ||
var response = Put().word8(0x0F).word16be(start).word16be(quantity).buffer(), | ||
oldValue, | ||
newValue, | ||
current = pdu.readUInt8(6), | ||
j = 0; | ||
oldValue, newValue, current = pdu.readUInt8(6 + 0), j = 0; | ||
for (var i = start; i < start + quantity; i += 1) { | ||
for (var i = start; i < start + quantity; i += 1 ) { | ||
oldValue = mem.readUInt8(Math.floor(i / 8)); | ||
if (Math.pow(2, j % 8) & current) { | ||
newValue = oldValue | Math.pow(2, i % 8); | ||
} else { | ||
newValue = oldValue & ~Math.pow(2, i % 8); | ||
newValue = oldValue & ~Math.pow(2, i % 8); | ||
} | ||
mem.writeUInt8(newValue, Math.floor(start / 8)); | ||
mem.writeUInt8(newValue, Math.floor(start / 8)); | ||
@@ -77,5 +72,5 @@ j += 1; | ||
if (j % 8 === 0) { | ||
current = pdu.readUInt8(6 + Math.floor(j / 8)); | ||
current = pdu.readUInt8(6 + Math.floor(j / 8)); | ||
} | ||
@@ -90,8 +85,8 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating write multiple registers request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(16, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +28,3 @@ | ||
if (pdu.length < 3) { | ||
cb(Put().word8(0x90).word8(0x02).buffer()); | ||
@@ -37,13 +35,13 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3), | ||
byteCount = pdu.readUInt8(5); | ||
var fc = pdu.readUInt8(0), | ||
start = pdu.readUInt16BE(1), | ||
byteStart = start * 2, | ||
quantity = pdu.readUInt16BE(3), | ||
byteCount = pdu.readUInt8(5); | ||
if (quantity > 0x007b) { | ||
cb(Put().word8(0x90).word8(0x03).buffer()); | ||
return; | ||
} | ||
@@ -56,3 +54,3 @@ | ||
if (byteStart > mem.length || byteStart + (quantity * 2) > mem.length) { | ||
cb(Put().word8(0x90).word8(0x02).buffer()); | ||
@@ -64,11 +62,10 @@ return; | ||
var response = Put().word8(0x10).word16be(start).word16be(quantity).buffer(), | ||
j = 0, | ||
currentByte; | ||
j = 0, currentByte; | ||
for (var i = byteStart; i < byteStart + byteCount; i += 1) { | ||
mem.writeUInt8(pdu.readUInt8(6 + j + 0), i); | ||
j += 1; | ||
j += 1; | ||
} | ||
@@ -81,8 +78,8 @@ | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating write single coil request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(5, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +28,3 @@ | ||
if (pdu.length !== 5) { | ||
cb(Put().word8(0x85).word8(0x02).buffer()); | ||
@@ -37,11 +35,11 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
address = pdu.readUInt16BE(1), | ||
value = pdu.readUInt16BE(3) === 0x0000 ? false : true; | ||
var fc = pdu.readUInt8(0), | ||
address = pdu.readUInt16BE(1), | ||
value = pdu.readUInt16BE(3) === 0x0000?false:true; | ||
if (pdu.readUInt16BE(3) !== 0x0000 && pdu.readUInt16BE(3) !== 0xFF00) { | ||
cb(Put().word8(0x85).word8(0x03).buffer()); | ||
return; | ||
return; | ||
} | ||
@@ -54,3 +52,3 @@ | ||
if (address > mem.length * 8) { | ||
cb(Put().word8(0x85).word8(0x02).buffer()); | ||
@@ -61,13 +59,13 @@ return; | ||
var response = Put().word8(0x05).word16be(address).word16be(value ? 0xFF00 : 0x0000), | ||
var response = Put().word8(0x05).word16be(address).word16be(value?0xFF00:0x0000), | ||
oldValue = mem.readUInt8(Math.floor(address / 8)), | ||
newValue; | ||
if (value) { | ||
newValue = oldValue | Math.pow(2, address % 8); | ||
} else { | ||
newValue = oldValue & ~Math.pow(2, address % 8); | ||
newValue = oldValue & ~Math.pow(2, address % 8); | ||
} | ||
mem.writeUInt8(newValue, Math.floor(address / 8)); | ||
mem.writeUInt8(newValue, Math.floor(address / 8)); | ||
@@ -79,8 +77,8 @@ this.emit('postWriteSingleCoilRequest', address, value); | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
var stampit = require('stampit'), | ||
Put = require('put'); | ||
module.exports = stampit() | ||
.init(function () { | ||
var init = function () { | ||
this.log.debug('initiating write single register request handler.'); | ||
@@ -19,5 +17,5 @@ | ||
this.setRequestHandler(6, onRequest); | ||
}.bind(this); | ||
var onRequest = function (pdu, cb) { | ||
@@ -30,3 +28,3 @@ | ||
if (pdu.length !== 5) { | ||
cb(Put().word8(0x86).word8(0x02).buffer()); | ||
@@ -37,6 +35,6 @@ return; | ||
var fc = pdu.readUInt8(0), | ||
address = pdu.readUInt16BE(1), | ||
var fc = pdu.readUInt8(0), | ||
address = pdu.readUInt16BE(1), | ||
byteAddress = address * 2, | ||
value = pdu.readUInt16BE(3); | ||
value = pdu.readUInt16BE(3); | ||
@@ -48,3 +46,3 @@ this.emit('preWriteSingleRegisterRequest', byteAddress, value); | ||
if (byteAddress > mem.length) { | ||
cb(Put().word8(0x86).word8(0x02).buffer()); | ||
@@ -57,3 +55,3 @@ return; | ||
mem.writeUInt16BE(value, byteAddress); | ||
mem.writeUInt16BE(value, byteAddress); | ||
@@ -65,8 +63,8 @@ this.emit('postWriteSingleRegisterRequest', byteAddress, value); | ||
}.bind(this), this.responseDelay); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,20 +0,19 @@ | ||
"use strict"; | ||
var Util = require('util'), | ||
Put = require('put'), | ||
stampit = require('stampit'), | ||
Log = require('stampit-log'), | ||
StateMachine = require('stampit-state-machine'); | ||
var Util = require('util'), | ||
Put = require('put'), | ||
stampit = require('stampit'), | ||
Log = require('stampit-log'), | ||
StateMachine = require('stampit-state-machine'); | ||
var ExceptionMessage = { | ||
0x01: 'ILLEGAL FUNCTION', | ||
0x02: 'ILLEGAL DATA ADDRESS', | ||
0x03: 'ILLEGAL DATA VALUE', | ||
0x04: 'SLAVE DEVICE FAILURE', | ||
0x05: 'ACKNOWLEDGE', | ||
0x06: 'SLAVE DEVICE BUSY', | ||
0x08: 'MEMORY PARITY ERROR', | ||
0x0A: 'GATEWAY PATH UNAVAILABLE', | ||
0x0B: 'GATEWAY TARGET DEVICE FAILED TO RESPOND' | ||
0x01 : 'ILLEGAL FUNCTION', | ||
0x02 : 'ILLEGAL DATA ADDRESS', | ||
0x03 : 'ILLEGAL DATA VALUE', | ||
0x04 : 'SLAVE DEVICE FAILURE', | ||
0x05 : 'ACKNOWLEDGE', | ||
0x06 : 'SLAVE DEVICE BUSY', | ||
0x08 : 'MEMORY PARITY ERROR', | ||
0x0A : 'GATEWAY PATH UNAVAILABLE', | ||
0x0B : 'GATEWAY TARGET DEVICE FAILED TO RESPOND' | ||
@@ -28,6 +27,19 @@ }; | ||
var reqFifo = [], | ||
responseHandler = {}, | ||
currentRequest = null; | ||
var responseHandler = { }, | ||
currentRequest = null; | ||
this.reqFifo = []; | ||
var init = function () { | ||
if (!this.timeout) { | ||
this.timeout = 5 * 1000; // 5s | ||
} | ||
this.on('data', onData); | ||
this.on('newState_ready', flush); | ||
this.on('newState_closed', onClosed); | ||
}.bind(this); | ||
var flush = function () { | ||
@@ -38,3 +50,3 @@ | ||
if (reqFifo.length === 0) { | ||
if (this.reqFifo.length === 0) { | ||
this.log.debug('Nothing in request pipe.'); | ||
@@ -44,7 +56,7 @@ return; | ||
currentRequest = reqFifo.shift(); | ||
currentRequest = this.reqFifo.shift(); | ||
currentRequest.timeout = setTimeout(function () { | ||
currentRequest.defer.reject({err: 'timeout'}); | ||
currentRequest.defer.reject({ err: 'timeout' }); | ||
this.emit('trashCurrentRequest'); | ||
@@ -55,2 +67,3 @@ | ||
this.setState('error'); | ||
// this.setState('ready'); | ||
@@ -61,3 +74,3 @@ }.bind(this), this.timeout); | ||
this.emit('send', currentRequest.pdu); | ||
this.log.debug('Data flushed.'); | ||
@@ -69,4 +82,4 @@ | ||
var onClosed = function () { | ||
if (currentRequest) { | ||
if (currentRequest) { | ||
this.log.debug('Clearing timeout of the current request.'); | ||
@@ -77,11 +90,11 @@ clearTimeout(currentRequest.timeout); | ||
this.log.debug('Cleaning up request fifo.'); | ||
reqFifo.forEach(function () { | ||
reqFifo.pop(); | ||
this.reqFifo.forEach(function () { | ||
this.reqFifo.pop(); | ||
}); | ||
}.bind(this); | ||
var handleErrorPDU = function (pdu) { | ||
var errorCode = pdu.readUInt8(0); | ||
@@ -91,3 +104,3 @@ | ||
// ths pdu describes no error | ||
if (errorCode < 0x80) { | ||
@@ -98,3 +111,3 @@ return false; | ||
// pdu describes an error | ||
var exceptionCode = pdu.readUInt8(1), | ||
@@ -113,9 +126,9 @@ message = ExceptionMessage[exceptionCode]; | ||
return true; | ||
}.bind(this); | ||
/** | ||
* Handle the incoming data, cut out the mbap | ||
* packet and send the pdu to the listener | ||
*/ | ||
* Handle the incoming data, cut out the mbap | ||
* packet and send the pdu to the listener | ||
*/ | ||
var onData = function (pdu) { | ||
@@ -142,3 +155,3 @@ | ||
// handle pdu | ||
var handler = responseHandler[currentRequest.fc]; | ||
@@ -151,17 +164,17 @@ if (!handler) { | ||
handler(pdu, currentRequest); | ||
this.setState('ready'); | ||
}.bind(this); | ||
this.addResponseHandler = function (fc, handler) { | ||
responseHandler[fc] = handler; | ||
return this; | ||
}.bind(this); | ||
this.queueRequest = function (fc, pdu, defer) { | ||
var req = { | ||
@@ -173,3 +186,3 @@ fc: fc, | ||
reqFifo.push(req); | ||
this.reqFifo.push(req); | ||
@@ -179,19 +192,7 @@ if (this.inState('ready')) { | ||
} | ||
}; | ||
var init = function () { | ||
if (!this.timeout) { | ||
this.timeout = 5 * 1000; // 5s | ||
} | ||
this.on('data', onData); | ||
this.on('newState_ready', flush); | ||
this.on('newState_closed', onClosed); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,70 +0,13 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
ModbusCore = require('./modbus-client-core.js'); | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
ModbusCore = require('./modbus-client-core.js'); | ||
module.exports = stampit() | ||
.compose(ModbusCore) | ||
.init(function () { | ||
var SerialPort = require('serialport').SerialPort, | ||
serialport; | ||
var onOpen = function () { | ||
this.emit('connect'); | ||
this.setState('ready'); | ||
}.bind(this); | ||
var onClose = function () { | ||
this.setState('closed'); | ||
}.bind(this); | ||
var onData = function (pdu) { | ||
this.log.debug('received data'); | ||
this.emit('data', pdu); | ||
}.bind(this); | ||
var onError = function (err) { | ||
this.emit('error', err); | ||
}.bind(this); | ||
var onSend = function (pdu) { | ||
var pkt = Put() | ||
.word8(1) | ||
.put(pdu), | ||
buf = pkt.buffer(), | ||
crc = 0; | ||
for (var i = 0; i < buf.length; i += 1) { | ||
crc = (buf.readUInt8(i) + crc) % 0xFFFF; | ||
} | ||
pkt = pkt.word16be(crc).buffer(); | ||
for (var j = 0; j < pkt.length; j += 1) { | ||
console.log(pkt.readUInt8(j).toString(16)); | ||
} | ||
serialport.write(pkt, function (err) { | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
} | ||
}.bind(this)); | ||
}.bind(this); | ||
var init = function () { | ||
@@ -97,4 +40,5 @@ | ||
// TODO: settings - ['brk', 'cts', 'dtr', 'dts', 'rts'] | ||
serialport = new SerialPort(this.portName, { | ||
baudRate: this.baudrate, | ||
baudRate: this.baudRate, | ||
parity: this.parity, | ||
@@ -113,11 +57,69 @@ dataBits: this.dataBits, | ||
}.bind(this); | ||
var onOpen = function () { | ||
this.emit('connect'); | ||
this.setState('ready'); | ||
}.bind(this); | ||
var onClose = function () { | ||
this.setState('closed'); | ||
}.bind(this); | ||
var onData = function (pdu) { | ||
this.log.debug('received data'); | ||
this.emit('data', pdu); | ||
}.bind(this); | ||
var onError = function (err) { | ||
this.emit('error', err); | ||
}.bind(this); | ||
var onSend = function (pdu) { | ||
var pkt = Put() | ||
.word8(1) | ||
.put(pdu), | ||
buf = pkt.buffer(); | ||
crc = 0; | ||
for (var i = 0; i < buf.length; i += 1) { | ||
crc = (buf.readUInt8(i) + crc) % 0xFFFF; | ||
} | ||
pkt = pkt.word16be(crc).buffer(); | ||
for (var j = 0; j < pkt.length; j += 1) { | ||
console.log(pkt.readUInt8(j).toString(16)); | ||
} | ||
serialport.write(pkt, function (err) { | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
} | ||
}.bind(this)); | ||
}.bind(this); | ||
this.close = function () { | ||
serialport.close(); | ||
}; | ||
init(); | ||
}); |
@@ -1,14 +0,12 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
EventBus = require('stampit-event-bus'), | ||
Log = require('stampit-log'); | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
EventBus = require('stampit-event-bus'), | ||
Log = require('stampit-log'); | ||
var core = stampit() | ||
var core = stampit() | ||
.compose(EventBus, Log) | ||
.init(function () { | ||
var coils, holding, input, handler = { }; | ||
var coils, holding, input, handler = {}; | ||
var init = function () { | ||
@@ -33,3 +31,3 @@ | ||
} | ||
}.bind(this); | ||
@@ -39,8 +37,8 @@ | ||
// get fc and byteCount in advance | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
// get fc and byteCount in advance | ||
var fc = pdu.readUInt8(0), | ||
byteCount = pdu.readUInt8(1); | ||
// get the pdu handler | ||
var reqHandler = handler[fc]; | ||
var reqHandler = handler[fc]; | ||
@@ -52,3 +50,3 @@ if (!reqHandler) { | ||
// exception code 0x01 (Illegal Function) | ||
this.log.debug('no handler for fc', fc); | ||
@@ -59,16 +57,16 @@ | ||
return; | ||
} | ||
reqHandler(pdu, function (response) { | ||
callback(response); | ||
}.bind(this)); | ||
}.bind(this); | ||
this.setRequestHandler = function (fc, callback) { | ||
this.log.debug('setting request handler', fc); | ||
@@ -79,27 +77,27 @@ | ||
return this; | ||
}; | ||
this.getCoils = function () { | ||
return coils; | ||
}; | ||
this.getInput = function () { | ||
return input; | ||
}; | ||
this.getHolding = function () { | ||
return holding; | ||
}; | ||
init(); | ||
}); | ||
module.exports = core; | ||
module.exports = core; |
@@ -1,21 +0,38 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
Net = require('net'), | ||
ModbusCore = require('./modbus-client-core.js'); | ||
var stampit = require('stampit'), | ||
Put = require('put'), | ||
Net = require('net'), | ||
ModbusCore = require('./modbus-client-core.js'); | ||
module.exports = stampit() | ||
.compose(ModbusCore) | ||
.init(function () { | ||
var reqId = 0, | ||
currentRequestId = reqId, | ||
closedOnPurpose = false, | ||
reconnect = false, | ||
trashRequestId, | ||
socket; | ||
var init = function () { | ||
var reqId = 0, | ||
currentRequestId = reqId, | ||
closedOnPurpose = false, | ||
reconnect = false, | ||
trashRequestId, | ||
socket = null; | ||
this.setState('init'); | ||
var do_connect = function () { | ||
if (!this.unitId) { this.unitId = 0; } | ||
if (!this.protocolVersion) { this.protocolVersion = 0; } | ||
if (!this.port) { this.port = 502; } | ||
if (!this.host) { this.host = 'localhost'; } | ||
if (!this.autoReconnect) { this.autoReconnect = false; } | ||
if (!this.reconnectTimeout) { this.reconnectTimeout = 0; } | ||
this.on('send', onSend); | ||
this.on('newState_error', onError); | ||
this.on('trashCurrentRequest', onTrashCurrentRequest); | ||
this.on('stateChanged', this.log.debug); | ||
}.bind(this); | ||
var connect = function () { | ||
this.setState('connect'); | ||
@@ -31,14 +48,14 @@ | ||
socket.on('data', onSocketData); | ||
} | ||
socket.connect(this.port, this.host); | ||
}.bind(this); | ||
var onSocketConnect = function () { | ||
var onSocketConnect = function () { | ||
this.emit('connect'); | ||
this.setState('ready'); | ||
}.bind(this); | ||
@@ -51,3 +68,3 @@ | ||
this.setState('closed'); | ||
this.setState('closed'); | ||
this.emit('close'); | ||
@@ -60,8 +77,8 @@ | ||
reconnect = false; | ||
do_connect(); | ||
connect(); | ||
}, this.reconnectTimeout || 0); | ||
} | ||
} | ||
}.bind(this); | ||
@@ -75,11 +92,10 @@ | ||
this.emit('error', err); | ||
}.bind(this); | ||
var onSocketData = function (data) { | ||
this.log.debug('received data'); | ||
var cnt = 0; | ||
var pdu, mbap, id, len; | ||
@@ -90,10 +106,12 @@ while (cnt < data.length) { | ||
mbap = data.slice(cnt, cnt + 7); | ||
id = mbap.readUInt16BE(0); | ||
len = mbap.readUInt16BE(4); | ||
var mbap = data.slice(cnt, cnt + 7), | ||
id = mbap.readUInt16BE(0), | ||
len = mbap.readUInt16BE(4); | ||
if (id === trashRequestId) { | ||
this.log.debug('current mbap contains trashed request id.'); | ||
this.log.debug('current mbap contains trashed request id.'); | ||
return; | ||
} | ||
@@ -107,3 +125,4 @@ | ||
pdu = data.slice(cnt, cnt + len - 1); | ||
var pdu = data.slice(cnt, cnt + len - 1); | ||
cnt += pdu.length; | ||
@@ -115,6 +134,7 @@ | ||
// listener handle the pdu | ||
this.emit('data', pdu); | ||
} | ||
}.bind(this); | ||
@@ -138,7 +158,7 @@ | ||
var pkt = Put() | ||
.word16be(reqId) // transaction id | ||
.word16be(this.protocolVersion) // protocol version | ||
.word16be(pdu.length + 1) // pdu length | ||
.word8(this.unitId) // unit id | ||
.put(pdu) // the actual pdu | ||
.word16be(reqId) // transaction id | ||
.word16be(this.protocolVersion) // protocol version | ||
.word16be(pdu.length + 1) // pdu length | ||
.word8(this.unitId) // unit id | ||
.put(pdu) // the actual pdu | ||
.buffer(); | ||
@@ -149,19 +169,19 @@ | ||
socket.write(pkt); | ||
}.bind(this); | ||
var onTrashCurrentRequest = function () { | ||
trashRequestId = currentRequestId; | ||
}.bind(this); | ||
this.connect = function () { | ||
this.setState('connect'); | ||
do_connect(); | ||
connect(); | ||
return this; | ||
}; | ||
@@ -176,3 +196,3 @@ | ||
closedOnPurpose = false; | ||
reconnect = true; | ||
reconnect = true; | ||
@@ -184,3 +204,3 @@ this.log.debug('Reconnecting client.'); | ||
return this; | ||
}; | ||
@@ -200,35 +220,4 @@ | ||
var init = function () { | ||
this.setState('init'); | ||
if (!this.unitId) { | ||
this.unitId = 0; | ||
} | ||
if (!this.protocolVersion) { | ||
this.protocolVersion = 0; | ||
} | ||
if (!this.port) { | ||
this.port = 502; | ||
} | ||
if (!this.host) { | ||
this.host = 'localhost'; | ||
} | ||
if (!this.autoReconnect) { | ||
this.autoReconnect = false; | ||
} | ||
if (!this.reconnectTimeout) { | ||
this.reconnectTimeout = 0; | ||
} | ||
this.on('send', onSend); | ||
this.on('newState_error', onError); | ||
this.on('trashCurrentRequest', onTrashCurrentRequest); | ||
this.on('stateChanged', this.log.debug); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,9 +0,7 @@ | ||
"use strict"; | ||
var stampit = require('stampit'), | ||
ModbusServerCore = require('./modbus-server-core.js'), | ||
StateMachine = require('stampit-state-machine'), | ||
Put = require('put'), | ||
net = require('net'); | ||
var stampit = require('stampit'), | ||
ModbusServerCore = require('./modbus-server-core.js'), | ||
StateMachine = require('stampit-state-machine'), | ||
Put = require('put'), | ||
net = require('net'); | ||
module.exports = stampit() | ||
@@ -13,66 +11,73 @@ .compose(ModbusServerCore) | ||
.init(function () { | ||
var server, socketCount = 0, fifo = []; | ||
var clients = [] | ||
var onSocketEnd = function (socket, socketId) { | ||
return function () { | ||
this.log.debug('connection closed, socket', socketId, socket); | ||
}.bind(this); | ||
}.bind(this); | ||
var flush = function () { | ||
if (this.inState('processing')) { | ||
return; | ||
var init = function () { | ||
if (!this.port) { | ||
this.port = 502; | ||
} | ||
if (fifo.length === 0) { | ||
return; | ||
if (!this.hostname) { | ||
this.hostname = '0.0.0.0'; | ||
} | ||
this.setState('processing'); | ||
server = net.createServer(); | ||
server.on('connection', function (s) { | ||
var current = fifo.shift(); | ||
this.log.debug('new connection', s.address()); | ||
clients.push(s) | ||
initiateSocket(s); | ||
}.bind(this)); | ||
this.onData(current.pdu, function (response) { | ||
server.listen(this.port, this.hostname, function (err) { | ||
if (err) { | ||
this.log.debug('error while listening', err); | ||
this.emit('error', err); | ||
return; | ||
this.log.debug('sending tcp data'); | ||
} | ||
var pkt = Put() | ||
.word16be(current.request.trans_id) // transaction id | ||
.word16be(current.request.protocol_ver) // protocol version | ||
.word16be(response.length + 1) // pdu length | ||
.word8(current.request.unit_id) // unit id | ||
.put(response) // the actual pdu | ||
.buffer(); | ||
}.bind(this)); | ||
this.log.debug('server is listening on port', this.hostname + ':' + this.port); | ||
current.socket.write(pkt); | ||
this.on('newState_ready', flush); | ||
this.setState('ready'); | ||
this.setState('ready'); | ||
}.bind(this)); | ||
}.bind(this); | ||
var onSocketEnd = function (socket, socketId) { | ||
return function () { | ||
this.log.debug('connection closed, socket', socketId); | ||
}.bind(this); | ||
}.bind(this); | ||
var onSocketData = function (socket, socketId) { | ||
return function (data) { | ||
this.log.debug('received data socket', socketId, data.byteLength); | ||
this.log.debug('received data socket',socketId, data.byteLength); | ||
// 1. extract mbap | ||
var mbap = data.slice(0, 7), | ||
len = mbap.readUInt16BE(4); | ||
var mbap = data.slice(0, 0 + 7), | ||
len = mbap.readUInt16BE(4); | ||
request = { | ||
trans_id: mbap.readUInt16BE(0), | ||
protocol_ver: mbap.readUInt16BE(2), | ||
unit_id: mbap.readUInt8(6) | ||
}; | ||
var request = { | ||
trans_id: mbap.readUInt16BE(0), | ||
protocol_ver: mbap.readUInt16BE(2), | ||
unit_id: mbap.readUInt8(6) | ||
}; | ||
// 2. extract pdu | ||
@@ -85,23 +90,57 @@ | ||
fifo.push({request: request, pdu: pdu, socket: socket}); | ||
fifo.push({ request : request, pdu : pdu, socket : socket }); | ||
flush(); | ||
}.bind(this); | ||
}.bind(this); | ||
var onSocketError = function (socket, socketCount) { | ||
var flush = function () { | ||
if (this.inState('processing')) { | ||
return; | ||
} | ||
return function (e) { | ||
if (fifo.length === 0) { | ||
return; | ||
} | ||
this.logError('Socket error', socket, socketCount, e); | ||
this.setState('processing'); | ||
}.bind(this); | ||
var current = fifo.shift(); | ||
this.onData(current.pdu, function (response) { | ||
this.log.debug('sending tcp data'); | ||
var pkt = Put() | ||
.word16be(current.request.trans_id) // transaction id | ||
.word16be(current.request.protocol_ver) // protocol version | ||
.word16be(response.length + 1) // pdu length | ||
.word8(current.request.unit_id) // unit id | ||
.put(response) // the actual pdu | ||
.buffer(); | ||
current.socket.write(pkt); | ||
this.setState('ready'); | ||
}.bind(this)); | ||
}.bind(this); | ||
var onSocketError = function (socket, socketCount) { | ||
return function (e) { | ||
this.logError('Socker error', e); | ||
}.bind(this); | ||
}.bind(this); | ||
var initiateSocket = function (socket) { | ||
socketCount += 1; | ||
@@ -112,51 +151,21 @@ | ||
socket.on('error', onSocketError(socket, socketCount)); | ||
}.bind(this); | ||
}.bind(this); | ||
this.close = function (cb) { | ||
for(var c in clients) { | ||
clients[c].destroy() | ||
} | ||
server.close(cb); | ||
server.close(function() { | ||
server.unref() | ||
if(cb) { cb() } | ||
}); | ||
}; | ||
var init = function () { | ||
if (!this.port) { | ||
this.port = 502; | ||
} | ||
if (!this.hostname) { | ||
this.hostname = '0.0.0.0'; | ||
} | ||
server = net.createServer(); | ||
server.on('connection', function (s) { | ||
this.log.debug('new connection', s.address()); | ||
initiateSocket(s); | ||
}.bind(this)); | ||
server.listen(this.port, this.hostname, function (err) { | ||
if (err) { | ||
this.log.debug('error while listening', err); | ||
this.emit('error', err); | ||
} | ||
}.bind(this)); | ||
this.log.debug('server is listening on port', this.hostname + ':' + this.port); | ||
this.on('newState_ready', flush); | ||
this.setState('ready'); | ||
}.bind(this); | ||
init(); | ||
}); |
@@ -1,15 +0,15 @@ | ||
"use strict"; | ||
var fs = require('fs'); | ||
exports.client = { | ||
tcp: { | ||
core: require('./modbus-tcp-client.js'), | ||
complete: require('./modbus-tcp-client.js') | ||
tcp : { | ||
core : require('./modbus-tcp-client.js'), | ||
complete : require('./modbus-tcp-client.js') | ||
}, | ||
serial: { | ||
core: require('./modbus-serial-client.js'), | ||
complete: require('./modbus-serial-client.js') | ||
serial : { | ||
core : require('./modbus-serial-client.js'), | ||
complete : require('./modbus-serial-client.js') | ||
}, | ||
handler: {} | ||
handler : { | ||
} | ||
@@ -25,14 +25,14 @@ }; | ||
exports.client.tcp.complete = exports.client.tcp.complete.compose(require('./handler/client/' + file)); | ||
exports.client.serial.complete = exports.client.serial.complete.compose(require('./handler/client/' + file)); | ||
exports.client.handler[file.substr(0, file.length - 3)] = require('./handler/client/' + file); | ||
exports.client.tcp.complete = exports.client.tcp.complete.compose(require('./handler/client/' + file)); | ||
exports.client.serial.complete = exports.client.serial.complete.compose(require('./handler/client/' + file)); | ||
exports.client.handler[file.substr(0, file.length - 3)] = require('./handler/client/' + file); | ||
}); | ||
}); | ||
exports.server = { | ||
tcp: { | ||
core: require('./modbus-tcp-server.js'), | ||
complete: require('./modbus-tcp-server.js') | ||
exports.server = { | ||
tcp : { | ||
core : require('./modbus-tcp-server.js'), | ||
complete : require('./modbus-tcp-server.js'), | ||
}, | ||
handler: {} | ||
handler : { } | ||
}; | ||
@@ -47,6 +47,6 @@ | ||
exports.server.tcp.complete = exports.server.tcp.complete.compose(require('./handler/server/' + file)); | ||
exports.server.handler[file.substr(0, file.length - 3)] = require('./handler/server/' + file); | ||
exports.server.tcp.complete = exports.server.tcp.complete.compose(require('./handler/server/' + file)); | ||
exports.server.handler[file.substr(0, file.length - 3)] = require('./handler/server/' + file); | ||
}); | ||
}); | ||
{ | ||
"name": "node-modbus", | ||
"version": "2.0.5", | ||
"version": "2.0.6", | ||
"description": "Sum of implementations for the Serial/TCP Modbus protocol.", | ||
@@ -21,2 +21,3 @@ "author": "Klaus Landsdorf <klaus.landsdorf@bianco-royal.de>", | ||
"devDependencies": { | ||
"assert": "^1.4.1", | ||
"gulp": "^3.9.1", | ||
@@ -23,0 +24,0 @@ "gulp-htmlmin": "^2.0.0", |
54310
1221
6