nodbus-plus 0.8.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.readthedocs.yaml +35 -0
- package/LICENSE.md +21 -21
- package/README.md +163 -48
- package/docs/Makefile +20 -0
- package/docs/client/channel.rst +209 -0
- package/docs/client/nodbus_master_serial.rst +559 -0
- package/docs/client/nodbus_master_tcp.rst +573 -0
- package/docs/conf.py +41 -0
- package/docs/images/01-readcoils.png +0 -0
- package/docs/images/02-readinputs.png +0 -0
- package/docs/images/03-readholding.png +0 -0
- package/docs/images/04-readinputsreg.png +0 -0
- package/docs/images/05-writecoil.png +0 -0
- package/docs/images/06-writeregister.png +0 -0
- package/docs/images/15-writecoil.png +0 -0
- package/docs/images/16.png +0 -0
- package/docs/images/22-mask.png +0 -0
- package/docs/images/23.png +0 -0
- package/docs/images/7.png +0 -0
- package/docs/images/modbus_pdu.png +0 -0
- package/docs/images/serial_adu.png +0 -0
- package/docs/images/tcp_adu.png +0 -0
- package/docs/index.rst +30 -0
- package/docs/make.bat +35 -0
- package/docs/protocol/modbus_master.rst +276 -0
- package/docs/protocol/modbus_master_serial.rst +290 -0
- package/docs/protocol/modbus_master_tcp.rst +296 -0
- package/docs/protocol/modbus_server.rst +469 -0
- package/docs/protocol/modbus_server_serial.rst +543 -0
- package/docs/protocol/modbus_server_tcp.rst +365 -0
- package/docs/requirements.txt +4 -0
- package/docs/server/net_server.rst +242 -0
- package/docs/server/nodbus_serial_server.rst +652 -0
- package/docs/server/nodbus_tcp_server.rst +505 -0
- package/docs/starting.rst +192 -0
- package/docs/static/simple logo.jpg +0 -0
- package/package.json +39 -30
- package/samples/mb_serial_server.js +77 -0
- package/samples/mb_tcp_client.js +114 -0
- package/samples/mb_tcp_server.js +58 -0
- package/src/client/net/serialchannel.js +195 -0
- package/src/client/net/tcpchannel.js +233 -0
- package/src/client/net/udpchannel.js +243 -0
- package/src/client/nodbus_serial_client.js +577 -0
- package/src/client/nodbus_tcp_client.js +542 -0
- package/src/nodbus-plus.js +157 -110
- package/src/protocol/modbus_master.js +298 -961
- package/src/protocol/modbus_master_serial.js +247 -0
- package/src/protocol/modbus_master_tcp.js +219 -0
- package/src/protocol/modbus_server.js +936 -0
- package/src/protocol/modbus_server_serial.js +368 -0
- package/src/protocol/modbus_server_tcp.js +129 -0
- package/src/protocol/utils.js +296 -0
- package/src/server/net/serialserver.js +184 -0
- package/src/server/net/tcpserver.js +290 -0
- package/src/server/net/udpserver.js +242 -0
- package/src/server/nodbus_serial_server.js +238 -0
- package/src/server/nodbus_tcp_server.js +249 -0
- package/test/modbus_master.test.js +279 -0
- package/test/modbus_master_serial.test.js +124 -0
- package/test/modbus_master_tcp.test.js +178 -0
- package/test/modbus_server.test.js +506 -0
- package/test/modbus_server_serial.test.js +328 -0
- package/test/modbus_server_tcp.test.js +91 -0
- package/test/nodbus_client_serial.test.js +307 -0
- package/test/nodbus_client_tcp.test.js +334 -0
- package/test/nodbus_server_serial.test.js +255 -0
- package/test/nodbus_server_tcp.test.js +216 -0
- package/CHANGELOG.md +0 -27
- package/src/client/m_stcp_client.js +0 -214
- package/src/client/m_tcp_client.js +0 -234
- package/src/net/tcpclient.js +0 -173
- package/src/net/tcpserver.js +0 -329
- package/src/protocol/adu.js +0 -40
- package/src/protocol/ascii_adu.js +0 -139
- package/src/protocol/boolean_register.js +0 -78
- package/src/protocol/functions/Force_Multiple_Coils.js +0 -76
- package/src/protocol/functions/Force_Single_Coil.js +0 -54
- package/src/protocol/functions/Mask_Holding_Register.js +0 -47
- package/src/protocol/functions/Preset_Multiple_Registers.js +0 -53
- package/src/protocol/functions/Preset_Single_Register.js +0 -39
- package/src/protocol/functions/Read_Coil_Status.js +0 -59
- package/src/protocol/functions/Read_Holding_Registers.js +0 -52
- package/src/protocol/functions/Read_Input_Registers.js +0 -52
- package/src/protocol/functions/Read_Input_Status.js +0 -58
- package/src/protocol/mbap.js +0 -60
- package/src/protocol/modbus_device.js +0 -35
- package/src/protocol/modbus_slave.js +0 -522
- package/src/protocol/pdu.js +0 -70
- package/src/protocol/rtu_adu.js +0 -122
- package/src/protocol/serial_adu.js +0 -29
- package/src/protocol/tcp_adu.js +0 -84
- package/src/protocol/word_register.js +0 -122
- package/src/server/m_stcp_server.js +0 -310
- package/src/server/m_tcp_server.js +0 -295
- package/test/modbus-stcp-server-test.js +0 -72
- package/test/modbus-stcp-server-test1.js +0 -72
- package/test/modbus-tcp-client-test.js +0 -159
- package/test/modbus-tcp-server-test.js +0 -75
- package/test/modbus-tcp-server-test2.js +0 -75
- package/test/modbus_stcp_client.js +0 -149
package/src/net/tcpserver.js
DELETED
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
** Tcp server module.
|
|
3
|
-
* @module net/tcpserver.
|
|
4
|
-
* @author Hector E. Socarras.
|
|
5
|
-
* @version 0.4.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
var net = require('net');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Class representing a tcp server layer for modbus tcp.
|
|
12
|
-
*/
|
|
13
|
-
class TCPServer {
|
|
14
|
-
/**
|
|
15
|
-
* Create a Tcp Server.
|
|
16
|
-
*/
|
|
17
|
-
constructor(){
|
|
18
|
-
|
|
19
|
-
var self = this;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* tcp server
|
|
23
|
-
* @type {Object}
|
|
24
|
-
*/
|
|
25
|
-
this.tcpServer = net.createServer();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let connections = [];
|
|
29
|
-
/**
|
|
30
|
-
* list of connections
|
|
31
|
-
* @type {Object[]}
|
|
32
|
-
*/
|
|
33
|
-
Object.defineProperty(self,'activeConections',{
|
|
34
|
-
get: function(){ return connections}
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* listening status
|
|
39
|
-
* @type {boolean}
|
|
40
|
-
*/
|
|
41
|
-
Object.defineProperty(self, 'isListening',{
|
|
42
|
-
get: function(){
|
|
43
|
-
return self.tcpServer.listening;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Max connections
|
|
49
|
-
* @type {number}
|
|
50
|
-
*/
|
|
51
|
-
Object.defineProperty(self, 'maxConnections',{
|
|
52
|
-
get: function(){
|
|
53
|
-
return self.tcpServer.maxConnections;
|
|
54
|
-
},
|
|
55
|
-
set: function(max){
|
|
56
|
-
self.tcpServer.maxConnections = max;
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* port
|
|
62
|
-
* @type {number}
|
|
63
|
-
*/
|
|
64
|
-
this.port = 502;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* list of ip allowed
|
|
68
|
-
* @type {string[]}
|
|
69
|
-
*/
|
|
70
|
-
this.listAuthorizedIP = ['INADDR_ANY'];
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* list of ip denied
|
|
74
|
-
* @type {string[]}
|
|
75
|
-
*/
|
|
76
|
-
this.listForbidendIP = ['NONE'];
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Acces control function.
|
|
80
|
-
* @param {object} net.socket
|
|
81
|
-
* @return {bool}
|
|
82
|
-
*/
|
|
83
|
-
function AllowConnection (socket) {
|
|
84
|
-
|
|
85
|
-
var isForbidden = self.listForbidendIP.indexOf(socket.remoteAddres);
|
|
86
|
-
var isAuthorized = self.listAuthorizedIP.indexOf(socket.remoteAddres);
|
|
87
|
-
|
|
88
|
-
if(isForbidden == -1 && self.listAuthorizedIP.indexOf('INADDR_ANY') >= 0 ){
|
|
89
|
-
return true
|
|
90
|
-
}
|
|
91
|
-
else if(isForbidden >= 0 ){
|
|
92
|
-
return false
|
|
93
|
-
}
|
|
94
|
-
else if(isAuthorized >= 0 & isForbidden == -1){
|
|
95
|
-
return true
|
|
96
|
-
}
|
|
97
|
-
else{
|
|
98
|
-
return false
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
//Socket config
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Inactivity time to close a connection
|
|
106
|
-
* @type {number}
|
|
107
|
-
*/
|
|
108
|
-
this.connectionTimeout = 0;
|
|
109
|
-
|
|
110
|
-
//User listeners
|
|
111
|
-
/**
|
|
112
|
-
* function to executed when event data is emited
|
|
113
|
-
* @param {Buffer} data
|
|
114
|
-
*/
|
|
115
|
-
this.onData = function(data){console.log(data)};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* function to executed when event listening is emited
|
|
119
|
-
*/
|
|
120
|
-
this.onListening = function(){ console.log('listening')};
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* function to executed when event connection is emited
|
|
124
|
-
* @param {Object} net.socket
|
|
125
|
-
*/
|
|
126
|
-
this.onConnection = function(){ console.log('new connection')};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* function to executed when event access-denied is emited
|
|
130
|
-
* @param {Object} net.socket
|
|
131
|
-
*/
|
|
132
|
-
this.onAccessDenied = null;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* function to executed when event error is emited
|
|
136
|
-
* @param {Object} error
|
|
137
|
-
*/
|
|
138
|
-
this.onError = function(err){ console.log(err)};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* function to executed when event close is emited
|
|
142
|
-
*/
|
|
143
|
-
this.onServerClose = function(){ console.log('server close')};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* function to executed when event socket#close is emited
|
|
147
|
-
*/
|
|
148
|
-
this.onConnectionClose = null;;
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
*function to executed when event socket#end is emited
|
|
152
|
-
*/
|
|
153
|
-
this.onClientEnd = null;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* function to executed when event write is emited
|
|
157
|
-
* @param {Buffer} buff
|
|
158
|
-
*/
|
|
159
|
-
this.onWrite = null
|
|
160
|
-
|
|
161
|
-
this.tcpServer.on('error', function(err){
|
|
162
|
-
self.onError(err);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
this.tcpServer.on('close', function(){
|
|
166
|
-
connections = [];
|
|
167
|
-
self.onServerClose();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
this.tcpServer.on('listening', function(){
|
|
171
|
-
self.onListening()
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
this.tcpServer.on('connection', function(socket) {
|
|
175
|
-
|
|
176
|
-
self.onConnection(socket);
|
|
177
|
-
|
|
178
|
-
if(AllowConnection(socket)){
|
|
179
|
-
|
|
180
|
-
//agrego el socket a la lista de conexiones activas
|
|
181
|
-
connections.push(socket)
|
|
182
|
-
|
|
183
|
-
//defining sockets behavior
|
|
184
|
-
if(self.connectionTimeout > 0) {
|
|
185
|
-
socket.setTimeout(self.connectionTimeout);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
socket.on('data',function(data){
|
|
189
|
-
|
|
190
|
-
var response = self.onData(data);
|
|
191
|
-
|
|
192
|
-
if(response.length <= 1 ){
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
else{
|
|
196
|
-
socket.write(response, 'utf8', function(){
|
|
197
|
-
if(self.onWrite){
|
|
198
|
-
self.onWrite(response);
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
socket.on('error',self.onError);
|
|
205
|
-
|
|
206
|
-
socket.on('timeout',function() {
|
|
207
|
-
socket.end();
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if(self.onClientEnd){
|
|
212
|
-
socket.on('end', self.onClientEnd);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
socket.on('close',function(){
|
|
216
|
-
var index = connections.indexOf(socket);
|
|
217
|
-
connections.splice(index,1);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
if(self.onConnectionClose){
|
|
221
|
-
socket.on('close', self.onConnectionClose);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
else{
|
|
225
|
-
socket.end();
|
|
226
|
-
if(self.onAccessDenied){
|
|
227
|
-
self.onAccessDenied(socket);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Add a ip to list of allowed ip
|
|
236
|
-
* @param {string} ip format aaa.bbb.ccc.ddd
|
|
237
|
-
* @throws {string}
|
|
238
|
-
*/
|
|
239
|
-
AddAuthorizedIP(ip){
|
|
240
|
-
if(typeof(ip) == 'string'){
|
|
241
|
-
this.listAuthorizedIP.push(ip);
|
|
242
|
-
}
|
|
243
|
-
else{
|
|
244
|
-
throw 'error of ip format'
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Remove a ip to list of allowed ip
|
|
250
|
-
* @param {string} ip format aaa.bbb.ccc.ddd
|
|
251
|
-
* @throws {string}
|
|
252
|
-
*/
|
|
253
|
-
RemoveAuthorizedIP (ip){
|
|
254
|
-
if(typeof(ip) == 'string'){
|
|
255
|
-
var index = listAuthorizedIP.indexOf(ip)
|
|
256
|
-
this.listAuthorizedIP.splice(index,i);
|
|
257
|
-
}
|
|
258
|
-
else{
|
|
259
|
-
throw 'error of ip format'
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Add a ip to list of forbiden ip
|
|
265
|
-
* @param {string} ip format aaa.bbb.ccc.ddd
|
|
266
|
-
* @throws {string}
|
|
267
|
-
*/
|
|
268
|
-
AddForbidenIP (ip){
|
|
269
|
-
if(typeof(ip) == 'string'){
|
|
270
|
-
this.listForbidendIPIP.push(ip);
|
|
271
|
-
}
|
|
272
|
-
else{
|
|
273
|
-
throw 'error of ip format'
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Remove a ip to list of forbiden ip
|
|
279
|
-
* @param {string} ip format aaa.bbb.ccc.ddd
|
|
280
|
-
* @throws {string}
|
|
281
|
-
*/
|
|
282
|
-
RemoveForbidendIP (ip){
|
|
283
|
-
if(typeof(ip) == 'string'){
|
|
284
|
-
var index = listAuthorizedIP.indexOf(ip)
|
|
285
|
-
this.listForbidendIP.splice(index,i);
|
|
286
|
-
}
|
|
287
|
-
else{
|
|
288
|
-
throw 'error of ip format'
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Start the tcp server
|
|
294
|
-
*/
|
|
295
|
-
Start (){
|
|
296
|
-
try {
|
|
297
|
-
this.tcpServer.listen(this.port)
|
|
298
|
-
}
|
|
299
|
-
catch(error){
|
|
300
|
-
this.onError(error);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Stop the tcp server
|
|
306
|
-
*/
|
|
307
|
-
Stop (){
|
|
308
|
-
//cerrando el server
|
|
309
|
-
this.tcpServer.close();
|
|
310
|
-
var sockets = this.activeConections;
|
|
311
|
-
sockets.forEach(function(element){
|
|
312
|
-
element.destroy();
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* function to write in a conection
|
|
318
|
-
* @param {objec} socket
|
|
319
|
-
* @param {buffer} data
|
|
320
|
-
*/
|
|
321
|
-
Write (socket,data){
|
|
322
|
-
socket.write(data);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
module.exports = TCPServer;
|
package/src/protocol/adu.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
** Modbus Aplication Data Unit base class.
|
|
3
|
-
* @module protocol/adu.js.
|
|
4
|
-
* @author Hector E. Socarras.
|
|
5
|
-
* @version 0.4.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const PDU = require('./pdu');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Class representing a modbus aplication data unit.
|
|
12
|
-
*/
|
|
13
|
-
class ADU {
|
|
14
|
-
/**
|
|
15
|
-
* Create a ADU.
|
|
16
|
-
* @param {Buffer} aduRaw Frame modbus.
|
|
17
|
-
*/
|
|
18
|
-
constructor(aduRaw = Buffer.alloc(1)){
|
|
19
|
-
/**
|
|
20
|
-
*Frame
|
|
21
|
-
*@type {Buffer}
|
|
22
|
-
*/
|
|
23
|
-
this.aduBuffer = aduRaw;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
*modbus address
|
|
27
|
-
*@type {number}
|
|
28
|
-
*/
|
|
29
|
-
this.address = 247;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
*Protocol data unit object
|
|
33
|
-
*@type {object}
|
|
34
|
-
*/
|
|
35
|
-
this.pdu = new PDU();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = ADU;
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*@brief Clase de Aplication Data Unit Ascii
|
|
3
|
-
*
|
|
4
|
-
*@author Hector E. Socarras.
|
|
5
|
-
*date 19/5/2016
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const SerialADU = require('./serial_adu');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
module.exports = class AsciiADU extends SerialADU {
|
|
12
|
-
constructor(aduRaw = Buffer.alloc(1)){
|
|
13
|
-
super(aduRaw);
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
MakeBuffer(){
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*function to convert a value in 2 chars lenght buffer
|
|
21
|
-
*@param byte number;
|
|
22
|
-
*@return {Buffer}
|
|
23
|
-
*/
|
|
24
|
-
function Byte2Chars (byte){
|
|
25
|
-
|
|
26
|
-
var temp = Buffer.alloc(2);
|
|
27
|
-
|
|
28
|
-
if(byte > 0x0F){
|
|
29
|
-
//convierto el numero en su sttring equivalente en hexadecimal y lo escrbo en el buffer temp
|
|
30
|
-
temp.write((byte & 0x0F).toString(16).toUpperCase(), 1);
|
|
31
|
-
temp.write((byte >> 4).toString(16).toUpperCase());
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
|
|
35
|
-
temp.write(0x00.toString(16).toUpperCase());
|
|
36
|
-
temp.write(byte.toString(16).toUpperCase(),1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return temp;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
//buffer temporal para el calculo de los caracteres
|
|
43
|
-
var charBuffer = Buffer.alloc(2);
|
|
44
|
-
|
|
45
|
-
//creando el buffer de la pdu
|
|
46
|
-
this.pdu.MakeBuffer();
|
|
47
|
-
|
|
48
|
-
//size of aduBuffer = 1 start char + 2 address char + 2*pduBuffer + 2 char lrc + 2 char end
|
|
49
|
-
var tempBuffer = Buffer.alloc(2*this.pdu.pduBuffer.length + 7);
|
|
50
|
-
var l = tempBuffer.length;
|
|
51
|
-
|
|
52
|
-
let rtuBuffer = Buffer.alloc(this.pdu.pduBuffer.length + 1)
|
|
53
|
-
rtuBuffer.writeUInt8(this.address);
|
|
54
|
-
this.pdu.pduBuffer.copy(rtuBuffer, 1);
|
|
55
|
-
|
|
56
|
-
//caracter ascii de inicio ':'
|
|
57
|
-
tempBuffer[0] = 0x3A;
|
|
58
|
-
|
|
59
|
-
if(this.address <= 247){
|
|
60
|
-
charBuffer = Byte2Chars(this.address);
|
|
61
|
-
charBuffer.copy(tempBuffer,1)
|
|
62
|
-
}
|
|
63
|
-
else{
|
|
64
|
-
throw Error('address error');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
for(var i = 0;i < this.pdu.pduBuffer.length;i++){
|
|
69
|
-
charBuffer = Byte2Chars(this.pdu.pduBuffer[i])
|
|
70
|
-
charBuffer.copy(tempBuffer,2*i+3)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
this.errorCheck = this.GetLRC(rtuBuffer);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
tempBuffer.write(this.errorCheck.toString(16).toUpperCase(), l-4, 2,'ascii');
|
|
77
|
-
|
|
78
|
-
//caracter ascii de fin 'CRLF'
|
|
79
|
-
tempBuffer[l-2] = 0x0D;
|
|
80
|
-
tempBuffer[l-1] = 0x0A;
|
|
81
|
-
|
|
82
|
-
this.aduBuffer = tempBuffer;
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
ParseBuffer() {
|
|
87
|
-
/**
|
|
88
|
-
*@brief function que parsea un buffer y para obtiener los atributos de la adu
|
|
89
|
-
*/
|
|
90
|
-
|
|
91
|
-
var l= this.aduBuffer.length;
|
|
92
|
-
var rtuBuffer;
|
|
93
|
-
|
|
94
|
-
this.address = Number('0x'+this.aduBuffer.toString('ascii',1,3));
|
|
95
|
-
|
|
96
|
-
//pdu normal en rtu entendible por el serial server
|
|
97
|
-
this.pdu.pduBuffer = Buffer.alloc(Math.floor((l - 7)/2));
|
|
98
|
-
|
|
99
|
-
for(var i = 0; i < this.pdu.pduBuffer.length; i++){
|
|
100
|
-
this.pdu.pduBuffer[i]=Number('0x'+this.aduBuffer.toString('ascii',2*i+3 ,2*i+5));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
rtuBuffer = Buffer.alloc(this.pdu.pduBuffer.length + 1)
|
|
104
|
-
rtuBuffer.writeUInt8(this.address);
|
|
105
|
-
this.pdu.pduBuffer.copy(rtuBuffer, 1);
|
|
106
|
-
|
|
107
|
-
this.errorCheck = Number('0x'+this.aduBuffer.toString('ascii',l-4,l-2));
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if(this.errorCheck == this.GetLRC(rtuBuffer)){
|
|
111
|
-
try{
|
|
112
|
-
this.pdu.ParseBuffer();
|
|
113
|
-
}
|
|
114
|
-
catch(e){
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else{
|
|
119
|
-
throw new Error('checksum error');
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
GetLRC(frame){
|
|
125
|
-
|
|
126
|
-
var byteLRC = Buffer.alloc(1);
|
|
127
|
-
|
|
128
|
-
for(var i = 0; i < frame.length;i++){
|
|
129
|
-
byteLRC[0] = byteLRC[0] + frame[i];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
var lrc_temp = Buffer.alloc(1);
|
|
133
|
-
lrc_temp[0] = -byteLRC[0];
|
|
134
|
-
var lrc = lrc_temp.readUInt8(0)
|
|
135
|
-
return lrc;
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
** bolean datatype memory.
|
|
3
|
-
* @module protocol/bolean_register
|
|
4
|
-
* @author Hector E. Socarras.
|
|
5
|
-
* @version 0.4.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Class representing a boolean memory area.
|
|
10
|
-
*/
|
|
11
|
-
class BoleanRegister {
|
|
12
|
-
/**
|
|
13
|
-
* Create a bolean register.
|
|
14
|
-
* @param {number} size total amount of references (inputs or coils).
|
|
15
|
-
*/
|
|
16
|
-
constructor(size = 1024){
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
*core.
|
|
20
|
-
*@type {Buffer}
|
|
21
|
-
*/
|
|
22
|
-
this.registerBuffer = Buffer.alloc((size > 8) ? size/8 : 1);
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
*@type {number}
|
|
26
|
-
*/
|
|
27
|
-
this.size = size;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
ReadData(dataAddress = 0){
|
|
33
|
-
if(dataAddress <= this.size){
|
|
34
|
-
|
|
35
|
-
let Byte = this.registerBuffer[Math.floor(dataAddress/8)];
|
|
36
|
-
let offset = dataAddress%8;
|
|
37
|
-
let masks = [0x01, 0x02, 0x04, 0x08, 0x010, 0x20, 0x40, 0x80];
|
|
38
|
-
|
|
39
|
-
return ((Byte & masks[offset]) > 0 ) ? true : false;
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
else{
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
WriteData(value, dataAddress = 0){
|
|
48
|
-
if(dataAddress <= this.size){
|
|
49
|
-
let newByte = 0x00;
|
|
50
|
-
let Byte = this.registerBuffer[Math.floor(dataAddress/8)];
|
|
51
|
-
let offset = dataAddress%8;
|
|
52
|
-
let masks = [0x01, 0x02, 0x04, 0x08, 0x010, 0x20, 0x40, 0x80];
|
|
53
|
-
if(value == true || value > 0){
|
|
54
|
-
newByte = Byte | masks[offset];
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
newByte = Byte & (~masks[offset]);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
this.registerBuffer[Math.floor(dataAddress/8)] = newByte;
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
else{
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* function to rezise the buffer of register
|
|
70
|
-
* @param {number} newSise
|
|
71
|
-
*/
|
|
72
|
-
ReSize(newSize){
|
|
73
|
-
this.registerBuffer = Buffer.alloc((newSize > 8) ? newSize/8 : 1);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
module.exports = BoleanRegister;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*@author Hector E. Socarras
|
|
3
|
-
*@brief
|
|
4
|
-
*Se implementa la funcion 05 del protocolo de modbus.
|
|
5
|
-
*Debuelve un objeto pdu con el echo del request.
|
|
6
|
-
*
|
|
7
|
-
*@param objeto pdu
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
var PDU = require('../pdu');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var ForceMultipleCoils = function (pdu){
|
|
15
|
-
|
|
16
|
-
var respPDU = new PDU();
|
|
17
|
-
|
|
18
|
-
//coil inicial ejemplo el coil 20 direccionado como 0x13 (19)
|
|
19
|
-
var startCoil = pdu.modbus_data.readUInt16BE(0);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (startCoil >= this.coils.size){
|
|
23
|
-
//Verificando q la coil solicitada exista
|
|
24
|
-
//Creando exception 0x02
|
|
25
|
-
respPDU.modbus_function = pdu.modbus_function | 0x80;
|
|
26
|
-
respPDU.modbus_data[0] = 0x02;
|
|
27
|
-
|
|
28
|
-
this.emit('modbus_exception','ILLEGAL DATA ADDRESS');
|
|
29
|
-
|
|
30
|
-
return respPDU;
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
|
|
34
|
-
//coil inicial ejemplo el coil 20 direccionado como 0x13 (19)
|
|
35
|
-
var startCoil = pdu.modbus_data.readUInt16BE(0);
|
|
36
|
-
|
|
37
|
-
//cantidad de coils a escribir
|
|
38
|
-
var number_points = pdu.modbus_data.readUInt16BE(2);
|
|
39
|
-
|
|
40
|
-
//Datos a forzar
|
|
41
|
-
var forceDataCount = pdu.modbus_data.readUInt8(5);
|
|
42
|
-
|
|
43
|
-
let forceData = pdu.modbus_data.slice(5);
|
|
44
|
-
|
|
45
|
-
let filletMask = [0x00, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80];
|
|
46
|
-
let masks = [0x01, 0x02, 0x04, 0x08, 0x010, 0x20, 0x40, 0x80];
|
|
47
|
-
|
|
48
|
-
if( (forceData[forceData.length] & filletMask[number_points%8]) != 0x00){
|
|
49
|
-
//Creando exception 0x03
|
|
50
|
-
respPDU.modbus_function = pdu.modbus_function | 0x80;
|
|
51
|
-
respPDU.modbus_data[0] = 0x03;
|
|
52
|
-
|
|
53
|
-
this.emit('modbus_exception', 'Illegal Data');
|
|
54
|
-
return respPDU;
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
else{
|
|
58
|
-
let values = new Map();
|
|
59
|
-
for(var i = 0; i < number_points; i++){
|
|
60
|
-
let offset = startCoil + i;
|
|
61
|
-
let val = forceData[Math.floor(i/8)] & masks[i%8]
|
|
62
|
-
this.coils.WriteData(val, offset);
|
|
63
|
-
values.set(offset, val > 0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
respPDU.modbus_function = 0x0F;
|
|
67
|
-
respPDU.modbus_data = Buffer.alloc(4);
|
|
68
|
-
pdu.modbus_data.copy(respPDU.modbus_data,0,0,4);
|
|
69
|
-
|
|
70
|
-
this.emit('values', '0x', values);
|
|
71
|
-
return respPDU;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
module.exports = ForceMultipleCoils;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*@author Hector E. Socarras
|
|
3
|
-
*@brief
|
|
4
|
-
*Se implementa la funcion 05 del protocolo de modbus.
|
|
5
|
-
*Debuelve un objeto pdu con el echo del request.
|
|
6
|
-
*
|
|
7
|
-
*@param objeto pdu
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
var PDU = require('../pdu');
|
|
11
|
-
|
|
12
|
-
var ForceSingleCoil = function (pdu){
|
|
13
|
-
|
|
14
|
-
var respPDU = new PDU();
|
|
15
|
-
|
|
16
|
-
//coil inicial ejemplo el coil 20 direccionado como 0x13 (19)
|
|
17
|
-
var targetCoil = pdu.modbus_data.readUInt16BE(0);
|
|
18
|
-
|
|
19
|
-
//valor a forzar
|
|
20
|
-
var value = pdu.modbus_data.readUInt16BE(2);
|
|
21
|
-
|
|
22
|
-
if(targetCoil >= this.coils.size){
|
|
23
|
-
//Verificando q la coil solicitada exista
|
|
24
|
-
//Creando exception 0x02
|
|
25
|
-
respPDU.modbus_function = pdu.modbus_function | 0x80;
|
|
26
|
-
respPDU.modbus_data[0] = 0x02;
|
|
27
|
-
|
|
28
|
-
this.emit('modbus_exception','ILLEGAL DATA ADDRESS');
|
|
29
|
-
|
|
30
|
-
return respPDU;
|
|
31
|
-
}
|
|
32
|
-
else if (value != 0x0000 & value != 0xFF00 ) {
|
|
33
|
-
//verificando el campo valor sea valido
|
|
34
|
-
//Creando exception 0x03
|
|
35
|
-
respPDU.modbus_function = pdu.modbus_function | 0x80;
|
|
36
|
-
respPDU.modbus_data[0] = 0x03;
|
|
37
|
-
|
|
38
|
-
this.emit('modbus_exception','ILLEGAL VALUE');
|
|
39
|
-
|
|
40
|
-
return respPDU;
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
let values = new Map();
|
|
44
|
-
this.coils.WriteData(value, targetCoil);
|
|
45
|
-
values.set(targetCoil, (value > 0));
|
|
46
|
-
//creando una copia del request
|
|
47
|
-
respPDU = pdu;
|
|
48
|
-
this.emit('values', '0x', values);
|
|
49
|
-
|
|
50
|
-
return respPDU;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
module.exports = ForceSingleCoil;
|