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
|
@@ -1,961 +1,298 @@
|
|
|
1
|
-
/**
|
|
2
|
-
** Modbus Master Base Class module.
|
|
3
|
-
*
|
|
4
|
-
* @
|
|
5
|
-
* @
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
*
|
|
119
|
-
* @param {
|
|
120
|
-
* @param {
|
|
121
|
-
* @
|
|
122
|
-
* @
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
value[1] = responsePDU.modbus_data[2*i+2];
|
|
300
|
-
key = '4x'.concat((startItem + i).toString());
|
|
301
|
-
data.set(key, value);
|
|
302
|
-
}
|
|
303
|
-
break;
|
|
304
|
-
case 0x04:
|
|
305
|
-
for(let i = 0; i < numberItems; i++){
|
|
306
|
-
value = Buffer.alloc(2);
|
|
307
|
-
value[0] = responsePDU.modbus_data[2*i+1];
|
|
308
|
-
value[1] = responsePDU.modbus_data[2*i+2];
|
|
309
|
-
key = '3x'.concat((startItem + i).toString());
|
|
310
|
-
data.set(key, value);
|
|
311
|
-
}
|
|
312
|
-
break;
|
|
313
|
-
case 0x05:
|
|
314
|
-
startItem = responsePDU.modbus_data.readUInt16BE(0);
|
|
315
|
-
key = '0x'.concat(startItem.toString());
|
|
316
|
-
|
|
317
|
-
if(responsePDU.modbus_data[2] == 0xff){
|
|
318
|
-
value = true;
|
|
319
|
-
}
|
|
320
|
-
else{
|
|
321
|
-
value = false;
|
|
322
|
-
}
|
|
323
|
-
data.set(key, value);
|
|
324
|
-
break;
|
|
325
|
-
case 0x06:
|
|
326
|
-
startItem = responsePDU.modbus_data.readUInt16BE(0);
|
|
327
|
-
key = '4x'.concat(startItem.toString());
|
|
328
|
-
value = Buffer.alloc(2);
|
|
329
|
-
value[0] = responsePDU.modbus_data[2];
|
|
330
|
-
value[1] = responsePDU.modbus_data[3];
|
|
331
|
-
data.set(key, value);
|
|
332
|
-
break;
|
|
333
|
-
case 0x0f:
|
|
334
|
-
startItem = responsePDU.modbus_data.readUInt16BE(0);
|
|
335
|
-
numberItems = responsePDU.modbus_data.readUInt16BE(2);
|
|
336
|
-
for(let i = 0; i < numberItems; i++){
|
|
337
|
-
index = Math.floor(i/8);
|
|
338
|
-
offset = i % 8;
|
|
339
|
-
value = (slave.currentRequest.pdu.modbus_data[index + 5] & masks[offset]) ? true : false;
|
|
340
|
-
key = '0x'.concat((startItem + i).toString());
|
|
341
|
-
data.set(key, value);
|
|
342
|
-
}
|
|
343
|
-
break;
|
|
344
|
-
case 0x10:
|
|
345
|
-
startItem = responsePDU.modbus_data.readUInt16BE(0);
|
|
346
|
-
numberItems = responsePDU.modbus_data.readUInt16BE(2);
|
|
347
|
-
for(let i = 0; i < numberItems; i++){
|
|
348
|
-
value = Buffer.alloc(2);
|
|
349
|
-
value[0] = slave.currentRequest.pdu.modbus_data[2*i+5];
|
|
350
|
-
value[1] = slave.currentRequest.pdu.modbus_data[2*i+6];
|
|
351
|
-
key = '4x'.concat((startItem + i).toString());
|
|
352
|
-
data.set(key, value);
|
|
353
|
-
}
|
|
354
|
-
break;
|
|
355
|
-
case 0x16:
|
|
356
|
-
startItem = responsePDU.modbus_data.readUInt16BE(0);
|
|
357
|
-
key = '4x'.concat(startItem.toString());
|
|
358
|
-
let mask = Buffer.alloc(2);
|
|
359
|
-
values = [0, 0];
|
|
360
|
-
mask= responsePDU.modbus_data.readUInt16BE(2);
|
|
361
|
-
values[0] = mask;
|
|
362
|
-
mask= responsePDU.modbus_data.readUInt16BE(4);
|
|
363
|
-
values[1] = mask;
|
|
364
|
-
data.set(key, values);
|
|
365
|
-
break;
|
|
366
|
-
default:
|
|
367
|
-
//modbus exeption
|
|
368
|
-
switch(responsePDU.modbus_data[0]){
|
|
369
|
-
case 1:
|
|
370
|
-
this.emit('modbus_exception', id, 'Illegal Function');
|
|
371
|
-
break;
|
|
372
|
-
case 2:
|
|
373
|
-
this.emit('modbus_exception', id, 'Illegal Data Address');
|
|
374
|
-
break;
|
|
375
|
-
case 3:
|
|
376
|
-
this.emit('modbus_exception', id, 'Illegal Data Value');
|
|
377
|
-
break;
|
|
378
|
-
case 4:
|
|
379
|
-
this.emit('modbus_exception', id, 'Slave Device Failure');
|
|
380
|
-
break;
|
|
381
|
-
case 5:
|
|
382
|
-
this.emit('modbus_exception', id, 'Unknow Error');
|
|
383
|
-
break;
|
|
384
|
-
case 6:
|
|
385
|
-
this.emit('modbus_exception', id, 'Unknow Error');
|
|
386
|
-
break;
|
|
387
|
-
case 7:
|
|
388
|
-
this.emit('modbus_exception', id, 'Unknow Error');
|
|
389
|
-
break;
|
|
390
|
-
case 8:
|
|
391
|
-
this.emit('modbus_exception', id, 'Unknow Error');
|
|
392
|
-
break;
|
|
393
|
-
}
|
|
394
|
-
//devuelvo null
|
|
395
|
-
data = null;
|
|
396
|
-
}
|
|
397
|
-
return data;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* extract data for a slave response
|
|
402
|
-
* @param {string} id reference of device.
|
|
403
|
-
* @param {Buffer} resp
|
|
404
|
-
* @fires ModbusMaster#raw_data {buffer} response frame
|
|
405
|
-
* @fires ModbusMaster#data {object} map object whit pair register:values
|
|
406
|
-
* @fires ModbusMaster#error {object}
|
|
407
|
-
*/
|
|
408
|
-
ProcessResponse(id, resp){
|
|
409
|
-
|
|
410
|
-
let slave = this.slaveList.get(id);
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* raw_data event.
|
|
414
|
-
* @event ModbusMaster#raw_data
|
|
415
|
-
* @type {object}
|
|
416
|
-
*/
|
|
417
|
-
this.emit('raw_data',id, resp);
|
|
418
|
-
|
|
419
|
-
if(slave.currentRequest){
|
|
420
|
-
try{
|
|
421
|
-
var respData = this.ParseResponse(id, resp);
|
|
422
|
-
|
|
423
|
-
if(respData){
|
|
424
|
-
/**
|
|
425
|
-
* data event.
|
|
426
|
-
* @event ModbusMaster#data
|
|
427
|
-
* @type {object}
|
|
428
|
-
*/
|
|
429
|
-
this.emit('data',id, respData);
|
|
430
|
-
|
|
431
|
-
//elimino la query activa.
|
|
432
|
-
let slave = this.slaveList.get(id);
|
|
433
|
-
slave.currentRequest = null;
|
|
434
|
-
slave._retriesNumber = 0;
|
|
435
|
-
this.emit('idle', id);
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
else{
|
|
439
|
-
if(slave.maxRetries > slave._retriesNumber){
|
|
440
|
-
this.netClient.Write(id, slave.currentRequest.aduBuffer);
|
|
441
|
-
slave._retriesNumber++;
|
|
442
|
-
}
|
|
443
|
-
else{
|
|
444
|
-
//discart request
|
|
445
|
-
slave.currentRequest = null;
|
|
446
|
-
slave._retriesNumber = 0;
|
|
447
|
-
this.emit('error',id, new Error('Unknow Error'));
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
catch (err){
|
|
454
|
-
slave.currentRequest = null;
|
|
455
|
-
|
|
456
|
-
this.emit('idle', id);
|
|
457
|
-
this.emit('error',id, err);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Make a modbus indication from query object.
|
|
465
|
-
*@param {string} id
|
|
466
|
-
*@param {Object} query
|
|
467
|
-
*@fires ModbusTCPClient#modbus_exception
|
|
468
|
-
*/
|
|
469
|
-
Poll(id, query){
|
|
470
|
-
/*
|
|
471
|
-
let ModbusFunction = 3;
|
|
472
|
-
|
|
473
|
-
switch(area){
|
|
474
|
-
case 'holding-registers':
|
|
475
|
-
if(itemsValues == null){
|
|
476
|
-
ModbusFunction = 3;
|
|
477
|
-
}
|
|
478
|
-
else{
|
|
479
|
-
if(numberItems == 1){
|
|
480
|
-
ModbusFunction = 6;
|
|
481
|
-
}
|
|
482
|
-
else{
|
|
483
|
-
ModbusFunction = 16;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
break;
|
|
487
|
-
case 'holding':
|
|
488
|
-
if(itemsValues == null){
|
|
489
|
-
ModbusFunction = 3;
|
|
490
|
-
}
|
|
491
|
-
else{
|
|
492
|
-
if(numberItems == 1){
|
|
493
|
-
ModbusFunction = 6;
|
|
494
|
-
}
|
|
495
|
-
else{
|
|
496
|
-
ModbusFunction = 16;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
break;
|
|
500
|
-
case 4:
|
|
501
|
-
if(itemsValues == null){
|
|
502
|
-
ModbusFunction = 3;
|
|
503
|
-
}
|
|
504
|
-
else{
|
|
505
|
-
if(numberItems == 1){
|
|
506
|
-
ModbusFunction = 6;
|
|
507
|
-
}
|
|
508
|
-
else{
|
|
509
|
-
ModbusFunction = 16;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
break;
|
|
513
|
-
case 'inputs-registers':
|
|
514
|
-
ModbusFunction = 3;
|
|
515
|
-
break;
|
|
516
|
-
case 3:
|
|
517
|
-
ModbusFunction = 3;
|
|
518
|
-
break;
|
|
519
|
-
case 'inputs':
|
|
520
|
-
ModbusFunction = 2;
|
|
521
|
-
break;
|
|
522
|
-
case 1:
|
|
523
|
-
ModbusFunction = 2;
|
|
524
|
-
break;
|
|
525
|
-
case 'coils':
|
|
526
|
-
if(itemsValues == null){
|
|
527
|
-
ModbusFunction = 1;
|
|
528
|
-
}
|
|
529
|
-
else{
|
|
530
|
-
if(numberItems == 1){
|
|
531
|
-
ModbusFunction = 5;
|
|
532
|
-
}
|
|
533
|
-
else{
|
|
534
|
-
ModbusFunction = 15;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
break;
|
|
538
|
-
case 0:
|
|
539
|
-
if(itemsValues == null){
|
|
540
|
-
ModbusFunction = 1;
|
|
541
|
-
}
|
|
542
|
-
else{
|
|
543
|
-
if(numberItems == 1){
|
|
544
|
-
ModbusFunction = 5;
|
|
545
|
-
}
|
|
546
|
-
else{
|
|
547
|
-
ModbusFunction = 15;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
break;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
switch (ModbusFunction) {
|
|
554
|
-
case 1:
|
|
555
|
-
this.ReadCoilStatus(id, startItem, numberItems);
|
|
556
|
-
break;
|
|
557
|
-
case 2:
|
|
558
|
-
this.ReadInputStatus(id, startItem, numberItems);
|
|
559
|
-
break;
|
|
560
|
-
case 3:
|
|
561
|
-
this.ReadHoldingRegisters(id, startItem, numberItems);
|
|
562
|
-
break;
|
|
563
|
-
case 4:
|
|
564
|
-
this.ReadInputRegisters(id, startItem, numberItems);
|
|
565
|
-
break;
|
|
566
|
-
case 5:
|
|
567
|
-
this.ForceSingleCoil(itemsValues, address, tartItem);
|
|
568
|
-
break;
|
|
569
|
-
case 6:
|
|
570
|
-
this.PresetSingleRegister(itemsValues, address, tartItem);
|
|
571
|
-
break;
|
|
572
|
-
case 15:
|
|
573
|
-
this.ForceMultipleCoils(itemsValues, address, startItem);
|
|
574
|
-
break;
|
|
575
|
-
case 16:
|
|
576
|
-
this.PresetMultipleRegisters(itemsValues, address, startItem);
|
|
577
|
-
break;
|
|
578
|
-
default:
|
|
579
|
-
return false;
|
|
580
|
-
break;
|
|
581
|
-
|
|
582
|
-
}
|
|
583
|
-
*/
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* function 01 of modbus protocol
|
|
588
|
-
* @param {string} id reference of device.
|
|
589
|
-
* @param {number} startcoil first coil to read, start at 0 coil
|
|
590
|
-
* @param {number} coilQuantity number of coils to read
|
|
591
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
592
|
-
*/
|
|
593
|
-
ReadCoilStatus(id, startCoil = 0, coilQuantity = 1){
|
|
594
|
-
|
|
595
|
-
if(this.slaveList.has(id) == false){
|
|
596
|
-
return undefined
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
let slave = this.slaveList.get(id);
|
|
600
|
-
|
|
601
|
-
//if is enable and there are no active request
|
|
602
|
-
if(slave.isReady && slave.currentRequest == null ){
|
|
603
|
-
let isSuccesfull
|
|
604
|
-
var pdu = this.CreateRequestPDU(1, startCoil, coilQuantity);
|
|
605
|
-
var adu = this.CreateADU(id, pdu);
|
|
606
|
-
slave.currentRequest = adu;
|
|
607
|
-
slave._retriesNumber = 0;
|
|
608
|
-
|
|
609
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
610
|
-
|
|
611
|
-
return isSuccesfull;
|
|
612
|
-
}
|
|
613
|
-
else{
|
|
614
|
-
return false;
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* function 02 of modbus protocol
|
|
620
|
-
* @param {string} id reference of device.
|
|
621
|
-
* @param {number} startInput first Input to read, start at 0 coil
|
|
622
|
-
* @param {number} InputQuantity number of Inputs to read
|
|
623
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
624
|
-
*/
|
|
625
|
-
ReadInputStatus(id, startInput = 0, inputQuantity = 1){
|
|
626
|
-
if(this.slaveList.has(id) == false){
|
|
627
|
-
return undefined
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
let slave = this.slaveList.get(id);
|
|
631
|
-
|
|
632
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
633
|
-
//si estoy conectado
|
|
634
|
-
let isSuccesfull;
|
|
635
|
-
var pdu = this.CreateRequestPDU(2, startInput, inputQuantity);
|
|
636
|
-
var adu = this.CreateADU(id, pdu);
|
|
637
|
-
slave.currentRequest = adu;
|
|
638
|
-
slave._retriesNumber = 0;
|
|
639
|
-
|
|
640
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
641
|
-
|
|
642
|
-
return isSuccesfull;
|
|
643
|
-
}
|
|
644
|
-
else{
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
/**
|
|
651
|
-
* function 03 of modbus protocol
|
|
652
|
-
* @param {string} id reference of device.
|
|
653
|
-
* @param {number} startRegister first holding register to read, start at 0 coil
|
|
654
|
-
* @param {number} registerQuantity number of holding register to read
|
|
655
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
656
|
-
*/
|
|
657
|
-
ReadHoldingRegisters(id, startRegister = 0, registerQuantity = 1){
|
|
658
|
-
if(this.slaveList.has(id) == false){
|
|
659
|
-
return undefined
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
let slave = this.slaveList.get(id);
|
|
663
|
-
|
|
664
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
665
|
-
//si estoy conectado
|
|
666
|
-
let isSuccesfull;
|
|
667
|
-
var pdu = this.CreateRequestPDU(3, startRegister, registerQuantity);
|
|
668
|
-
var adu = this.CreateADU(id, pdu);
|
|
669
|
-
slave.currentRequest = adu;
|
|
670
|
-
slave._retriesNumber = 0;
|
|
671
|
-
|
|
672
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
673
|
-
|
|
674
|
-
return isSuccesfull;
|
|
675
|
-
}
|
|
676
|
-
else{
|
|
677
|
-
return false;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
/**
|
|
683
|
-
* function 04 of modbus protocol
|
|
684
|
-
* @param {string} id reference of device.
|
|
685
|
-
* @param {number} startRegister first input register to read, start at 0 coil
|
|
686
|
-
* @param {number} registerQuantity number of input register to read
|
|
687
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
688
|
-
*/
|
|
689
|
-
ReadInputRegisters(id, startRegister = 0, registerQuantity = 1){
|
|
690
|
-
if(this.slaveList.has(id) == false){
|
|
691
|
-
return undefined
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
let slave = this.slaveList.get(id);
|
|
695
|
-
|
|
696
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
697
|
-
//si estoy conectado
|
|
698
|
-
let isSuccesfull;
|
|
699
|
-
var pdu = this.CreateRequestPDU(4, startRegister, registerQuantity);
|
|
700
|
-
var adu = this.CreateADU(id, pdu);
|
|
701
|
-
slave.currentRequest = adu;
|
|
702
|
-
slave._retriesNumber = 0;
|
|
703
|
-
|
|
704
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
705
|
-
|
|
706
|
-
return isSuccesfull;
|
|
707
|
-
}
|
|
708
|
-
else{
|
|
709
|
-
return false;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
/**
|
|
715
|
-
* function 05 of modbus protocol
|
|
716
|
-
* @param {string} id reference of device.
|
|
717
|
-
* @param {bool} value value to force
|
|
718
|
-
* @param {number} startcoil first coil to write, start at 0 coil
|
|
719
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
720
|
-
*/
|
|
721
|
-
ForceSingleCoil(id, value, startCoil = 0){
|
|
722
|
-
|
|
723
|
-
if(this.slaveList.has(id) == false){
|
|
724
|
-
return undefined
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
let bufferValue = Buffer.alloc(2);
|
|
728
|
-
let slave = this.slaveList.get(id);
|
|
729
|
-
|
|
730
|
-
if(value){
|
|
731
|
-
bufferValue[0] = 0xFF;
|
|
732
|
-
}
|
|
733
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
734
|
-
//si estoy conectado
|
|
735
|
-
let isSuccesfull;
|
|
736
|
-
var pdu = this.CreateRequestPDU(5, startCoil, 1, bufferValue);
|
|
737
|
-
var adu = this.CreateADU(id, pdu);
|
|
738
|
-
slave.currentRequest = adu;
|
|
739
|
-
slave._retriesNumber = 0;
|
|
740
|
-
|
|
741
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
742
|
-
|
|
743
|
-
return isSuccesfull;
|
|
744
|
-
}
|
|
745
|
-
else{
|
|
746
|
-
return false;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
/**
|
|
751
|
-
* function 06 of modbus protocol
|
|
752
|
-
* @param {string} id reference of device.
|
|
753
|
-
* @param {number} startRegister register to write.
|
|
754
|
-
* @param {number} value value to force
|
|
755
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
756
|
-
*/
|
|
757
|
-
PresetSingleRegister(id, value, startRegister = 0){
|
|
758
|
-
if(this.slaveList.has(id) == false){
|
|
759
|
-
return undefined
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
let val = Buffer.alloc(2);
|
|
763
|
-
let slave = this.slaveList.get(id);
|
|
764
|
-
|
|
765
|
-
if(value >= 0){
|
|
766
|
-
val.writeUInt16BE(value);
|
|
767
|
-
}
|
|
768
|
-
else{
|
|
769
|
-
val.writeInt16BE(value);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
773
|
-
//si estoy conectado
|
|
774
|
-
let isSuccesfull;
|
|
775
|
-
var pdu = this.CreateRequestPDU(6, startRegister, 1, val);
|
|
776
|
-
var adu = this.CreateADU(id, pdu);
|
|
777
|
-
slave.currentRequest = adu;
|
|
778
|
-
slave._retriesNumber = 0;
|
|
779
|
-
|
|
780
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
781
|
-
|
|
782
|
-
return isSuccesfull;
|
|
783
|
-
}
|
|
784
|
-
else{
|
|
785
|
-
return false;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
/**
|
|
790
|
-
* function 15 of modbus protocol
|
|
791
|
-
* @param {string} id reference of device.
|
|
792
|
-
* @param {bool[]} forceData array of values to write.
|
|
793
|
-
* @param {number} startCoil first coil to write, start at 0 coil.
|
|
794
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
795
|
-
*/
|
|
796
|
-
ForceMultipleCoils(id, forceData, startCoil = 0){
|
|
797
|
-
if(this.slaveList.has(id) == false){
|
|
798
|
-
return undefined
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
let coilQuantity = forceData.length;
|
|
802
|
-
let valueBuffer = Buffer.alloc(Math.floor((coilQuantity - 1)/8)+1);
|
|
803
|
-
let byteTemp = 0x00;
|
|
804
|
-
let offset = 0;
|
|
805
|
-
let masks = [0x01, 0x02, 0x04, 0x08, 0x010, 0x20, 0x40, 0x80];
|
|
806
|
-
let slave = this.slaveList.get(id);
|
|
807
|
-
|
|
808
|
-
for(let i =0; i < coilQuantity; i++){
|
|
809
|
-
if(forceData[i] == true){
|
|
810
|
-
valueBuffer[Math.floor(i/8)] = valueBuffer[Math.floor(i/8)] | masks[i%8];
|
|
811
|
-
}
|
|
812
|
-
else {
|
|
813
|
-
valueBuffer[Math.floor(i/8)] = valueBuffer[Math.floor(i/8)] & (~masks[i%8]);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
818
|
-
//si estoy conectado
|
|
819
|
-
let isSuccesfull
|
|
820
|
-
var pdu = this.CreateRequestPDU(15, startCoil, coilQuantity, valueBuffer);
|
|
821
|
-
var adu = this.CreateADU(id, pdu);
|
|
822
|
-
slave.currentRequest = adu;
|
|
823
|
-
slave._retriesNumber = 0;
|
|
824
|
-
|
|
825
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
826
|
-
|
|
827
|
-
return isSuccesfull;
|
|
828
|
-
}
|
|
829
|
-
else{
|
|
830
|
-
return false;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
/**
|
|
835
|
-
* function 16 of modbus protocol
|
|
836
|
-
* @param {string} id reference of device.
|
|
837
|
-
* @param {number[]} forceData array whit the values to write
|
|
838
|
-
* @param {number} startRegister register to write.
|
|
839
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
840
|
-
*/
|
|
841
|
-
PresetMultipleRegisters(id, forceData, startRegister = 0){
|
|
842
|
-
if(this.slaveList.has(id) == false){
|
|
843
|
-
return undefined
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
let valueBuffer = Buffer.alloc(0);
|
|
847
|
-
let slave = this.slaveList.get(id);
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
forceData.forEach(function(value){
|
|
851
|
-
let tempBufer = null;
|
|
852
|
-
if(Number.isInteger(value)){
|
|
853
|
-
if(value >= 0 && value <= 65535){
|
|
854
|
-
tempBufer = Buffer.alloc(2);
|
|
855
|
-
tempBufer.writeUInt16BE(value);
|
|
856
|
-
valueBuffer = Buffer.concat([valueBuffer, tempBufer], valueBuffer.length + 2)
|
|
857
|
-
}
|
|
858
|
-
else if (value < 0 && value > -32767) {
|
|
859
|
-
tempBufer = Buffer.alloc(2);
|
|
860
|
-
tempBufer.writeInt16BE(value);
|
|
861
|
-
valueBuffer = Buffer.concat([valueBuffer, tempBufer], valueBuffer.length + 2)
|
|
862
|
-
}
|
|
863
|
-
else{
|
|
864
|
-
tempBufer = Buffer.alloc(4);
|
|
865
|
-
tempBufer.writeInt32LE(value);
|
|
866
|
-
valueBuffer = Buffer.concat([valueBuffer, tempBufer.swap16()], valueBuffer.length + 4)
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
else{
|
|
870
|
-
tempBufer = Buffer.alloc(4);
|
|
871
|
-
tempBufer.writeFloatLE(value);
|
|
872
|
-
valueBuffer = Buffer.concat([valueBuffer, tempBufer.swap16()], valueBuffer.length + 4);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
})
|
|
876
|
-
|
|
877
|
-
let registerQuantity = valueBuffer.length/2;
|
|
878
|
-
|
|
879
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
880
|
-
//si estoy conectado
|
|
881
|
-
let isSuccesfull;
|
|
882
|
-
var pdu = this.CreateRequestPDU(16, startRegister, registerQuantity, valueBuffer);
|
|
883
|
-
var adu = this.CreateADU(id, pdu);
|
|
884
|
-
slave.currentRequest = adu;
|
|
885
|
-
slave._retriesNumber = 0;
|
|
886
|
-
|
|
887
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
888
|
-
|
|
889
|
-
return isSuccesfull;
|
|
890
|
-
}
|
|
891
|
-
else{
|
|
892
|
-
return false;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
* function 22 of modbus protocol
|
|
898
|
-
* @param {string} id reference of device.
|
|
899
|
-
* @param {number} startRegister register to write.
|
|
900
|
-
* @param {int [16]} value : array with 1 in position that want to be true, 0 on position that
|
|
901
|
-
* want to be false and -1 in position that not to be modified.
|
|
902
|
-
* example register value is [0 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1] 0x9E36
|
|
903
|
-
* desired value is [1 0 0 1 -1 0 1 -1 -1 -1 0 0 1 1 -1 0]
|
|
904
|
-
* result [1 0 0 1 1 0 1 0 0 1 0 0 1 1 0 0] 0x3259
|
|
905
|
-
* @return {boolean} true if succes, false if not connected, or waiting for response
|
|
906
|
-
*/
|
|
907
|
-
MaskHoldingRegister(id, value, startRegister = 0){
|
|
908
|
-
if(this.slaveList.has(id) == false){
|
|
909
|
-
return undefined
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
let val = Buffer.alloc(4)
|
|
913
|
-
let slave = this.slaveList.get(id);
|
|
914
|
-
|
|
915
|
-
let AND_Mask = 0x00;
|
|
916
|
-
let OR_Mask = 0xFFFF;
|
|
917
|
-
|
|
918
|
-
let tempMask = 1;
|
|
919
|
-
|
|
920
|
-
for (let i = 0; i <value.length; i++){
|
|
921
|
-
|
|
922
|
-
if(value[i] == 1){
|
|
923
|
-
//AND_MASK = 0;
|
|
924
|
-
//OR_Mask = 1;
|
|
925
|
-
}
|
|
926
|
-
else if(value[i] == 0){
|
|
927
|
-
//AND_MASK = 0;
|
|
928
|
-
OR_Mask = OR_Mask & (~tempMask); //OR_MASK = 0
|
|
929
|
-
}
|
|
930
|
-
else{
|
|
931
|
-
AND_Mask = AND_Mask | tempMask;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
tempMask = tempMask << 1;
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
val.writeUInt16BE(AND_Mask);
|
|
938
|
-
val.writeUInt16BE(OR_Mask, 2);
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
if(slave.isReady && slave.currentRequest == null){
|
|
942
|
-
//si estoy conectado
|
|
943
|
-
let isSuccesfull;
|
|
944
|
-
var pdu = this.CreateRequestPDU(22, startRegister, 1, val);
|
|
945
|
-
var adu = this.CreateADU(id, pdu);
|
|
946
|
-
slave.currentRequest = adu;
|
|
947
|
-
slave._retriesNumber = 0;
|
|
948
|
-
|
|
949
|
-
isSuccesfull = this.netClient.Write(id, adu.aduBuffer);
|
|
950
|
-
|
|
951
|
-
return isSuccesfull;
|
|
952
|
-
}
|
|
953
|
-
else{
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
module.exports = ModbusMaster;
|
|
1
|
+
/**
|
|
2
|
+
** Modbus Master Base Class module.
|
|
3
|
+
* Only deal with creating request PDU
|
|
4
|
+
* @module protocol/modbus_master
|
|
5
|
+
* @author Hector E. Socarras.
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const EventEmitter = require('events');
|
|
11
|
+
const utils = require('./utils');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Class representing a modbus master.
|
|
15
|
+
* @extends EventEmitter
|
|
16
|
+
*/
|
|
17
|
+
class ModbusClient extends EventEmitter {
|
|
18
|
+
/**
|
|
19
|
+
* Create a Modbus Master.
|
|
20
|
+
*/
|
|
21
|
+
constructor(){
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Function to make the request pdu for function code 1 of modbus protocol
|
|
30
|
+
* @param {number} startCoil first coil to read, start at 0
|
|
31
|
+
* @param {number} coilQuantity number of coils to read
|
|
32
|
+
* @return {buffer} pdu buffer.
|
|
33
|
+
*/
|
|
34
|
+
readCoilStatusPdu(startCoil = 0, coilQuantity = 1){
|
|
35
|
+
//funcion 01 read coils status
|
|
36
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
37
|
+
reqPduBuffer[0] = 0x01;
|
|
38
|
+
reqPduBuffer.writeUInt16BE(startCoil,1);
|
|
39
|
+
reqPduBuffer.writeUInt16BE(coilQuantity,3);
|
|
40
|
+
return reqPduBuffer;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Function to make the request pdu for function code 2 of modbus protocol.
|
|
45
|
+
* @param {number} startinput first input to read, start at 0.
|
|
46
|
+
* @param {number} inputQuantity number of inputs to read
|
|
47
|
+
* @return {buffer} pdu buffer.
|
|
48
|
+
*/
|
|
49
|
+
readInputStatusPdu(startInput = 0, inputQuantity = 1){
|
|
50
|
+
|
|
51
|
+
//funcion 02 read inputs status
|
|
52
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
53
|
+
reqPduBuffer[0] = 0x02;
|
|
54
|
+
reqPduBuffer.writeUInt16BE(startInput,1);
|
|
55
|
+
reqPduBuffer.writeUInt16BE(inputQuantity,3);
|
|
56
|
+
return reqPduBuffer;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Function to make the request pdu for function code 3 of modbus protocol.
|
|
61
|
+
* @param {number} startRegister first holding register to read, start at 0.
|
|
62
|
+
* @param {number} registerQuantity number of holding register to read.
|
|
63
|
+
* @return {buffer} pdu buffer.
|
|
64
|
+
*/
|
|
65
|
+
readHoldingRegistersPdu(startRegister = 0, registerQuantity = 1){
|
|
66
|
+
//funcion 0x03 read holdings registers
|
|
67
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
68
|
+
reqPduBuffer[0] = 0x03;
|
|
69
|
+
reqPduBuffer.writeUInt16BE(startRegister,1);
|
|
70
|
+
reqPduBuffer.writeUInt16BE(registerQuantity,3);
|
|
71
|
+
return reqPduBuffer;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @brief function to make the request pdu for function code 4 of modbus protocol.
|
|
76
|
+
* @param {number} startRegister first input register to read, start at 0.
|
|
77
|
+
* @param {number} registerQuantity number of input register to read.
|
|
78
|
+
* @return {buffer} pdu buffer.
|
|
79
|
+
*/
|
|
80
|
+
readInputRegistersPdu(startRegister = 0, registerQuantity = 1){
|
|
81
|
+
//funcion 0x04 read inputs registers
|
|
82
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
83
|
+
reqPduBuffer[0] = 0x04;
|
|
84
|
+
reqPduBuffer.writeUInt16BE(startRegister, 1);
|
|
85
|
+
reqPduBuffer.writeUInt16BE(registerQuantity, 3);
|
|
86
|
+
return reqPduBuffer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @brief function to make the request pdu for function code 5 of modbus protocol.
|
|
91
|
+
* @param {Buffer} value value to force
|
|
92
|
+
* @param {number} startcoil first coil to write, start at 0 coil
|
|
93
|
+
* @return {buffer} pdu buffer.
|
|
94
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
95
|
+
* @throws {RangeError} if values's length is diferent than 2.
|
|
96
|
+
*/
|
|
97
|
+
forceSingleCoilPdu(value, startCoil = 0){
|
|
98
|
+
//funcion 05 write single coil
|
|
99
|
+
if(value instanceof Buffer){
|
|
100
|
+
if(value.length == 2){
|
|
101
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
102
|
+
reqPduBuffer[0] = 0x05;
|
|
103
|
+
reqPduBuffer.writeUInt16BE(startCoil,1);
|
|
104
|
+
value.copy(reqPduBuffer,3);
|
|
105
|
+
return reqPduBuffer;
|
|
106
|
+
}
|
|
107
|
+
else{
|
|
108
|
+
throw new RangeError('Error, value length must be 2', 'modbus_master.js', 180);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else{
|
|
112
|
+
throw new TypeError('Error, value must be a Buffer', "modbus_master.js", 105);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Function to make the request pdu for function code 6 of modbus protocol.
|
|
119
|
+
* @param {Buffer} value value to force
|
|
120
|
+
* @param {number} startRegister register to write.
|
|
121
|
+
* @return {buffer} pdu buffer.
|
|
122
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
123
|
+
* @throws {RangeError} if values's length is diferent than 2.
|
|
124
|
+
*/
|
|
125
|
+
presetSingleRegisterPdu(value, startRegister = 0){
|
|
126
|
+
|
|
127
|
+
if(value instanceof Buffer){
|
|
128
|
+
if(value.length == 2){
|
|
129
|
+
//creando la pdu del request
|
|
130
|
+
let reqPduBuffer = Buffer.alloc(5);
|
|
131
|
+
//funcion 06 PresetSingleRegister
|
|
132
|
+
reqPduBuffer[0] = 0x06;
|
|
133
|
+
reqPduBuffer.writeUInt16BE(startRegister, 1);
|
|
134
|
+
value.copy(reqPduBuffer, 3);
|
|
135
|
+
|
|
136
|
+
return reqPduBuffer;
|
|
137
|
+
}
|
|
138
|
+
else{
|
|
139
|
+
throw new RangeError('Error, value length must be 2', 'modbus_master.js', 180);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else{
|
|
143
|
+
throw new TypeError('Error, value must be a Buffer', 'modbus_master.js', 130);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Function to make the request pdu for function code 15 of modbus protocol.
|
|
149
|
+
* @param {Buffer} values value to force.
|
|
150
|
+
* @param {number} startCoil first coil to write, start at 0 coil.
|
|
151
|
+
* @param {number} coilQuantity number of coils to read
|
|
152
|
+
* @return {buffer} pdu buffer.
|
|
153
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
154
|
+
* @throws {RangeError} if values's length is greater than 246.
|
|
155
|
+
*/
|
|
156
|
+
forceMultipleCoilsPdu(values, startCoil, coilQuantity){
|
|
157
|
+
//function 15 force multiples coils
|
|
158
|
+
if(values instanceof Buffer){
|
|
159
|
+
if(values.length <= 246){
|
|
160
|
+
//creando la pdu del request
|
|
161
|
+
let reqPduBuffer = Buffer.alloc(6+values.length);
|
|
162
|
+
reqPduBuffer[0] = 0x0F;
|
|
163
|
+
reqPduBuffer.writeUInt16BE(startCoil, 1);
|
|
164
|
+
reqPduBuffer.writeUInt16BE(coilQuantity,3);
|
|
165
|
+
reqPduBuffer[5]= values.length;
|
|
166
|
+
values.copy(reqPduBuffer, 6);
|
|
167
|
+
return reqPduBuffer;
|
|
168
|
+
}
|
|
169
|
+
else{
|
|
170
|
+
throw new RangeError('Error, values length exceed the max pdu length', 'modbus_master.js', 180);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else{
|
|
174
|
+
throw new TypeError('Error, values must be a Buffer', 'modbus_master.js', 156);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Function to make the request pdu for function code 16 of modbus protocol.
|
|
181
|
+
* @param {Buffer} values value to write.
|
|
182
|
+
* @param {number} startRegister first register to write.
|
|
183
|
+
* @param {number} registerQuantity number of holding register to write.
|
|
184
|
+
* @return {buffer} pdu buffer.
|
|
185
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
186
|
+
* @throws {RangeError} if values's length is greater than 246.
|
|
187
|
+
*/
|
|
188
|
+
presetMultipleRegistersPdu(values, startRegister, registerQuantity = Math.floor(values.length/2)){
|
|
189
|
+
//function 16 write multiples coils
|
|
190
|
+
if(values instanceof Buffer){
|
|
191
|
+
if(values.length <= 246){
|
|
192
|
+
//creando la pdu del request
|
|
193
|
+
let reqPduBuffer = Buffer.alloc(6 + 2*registerQuantity);
|
|
194
|
+
reqPduBuffer[0] = 0x10;
|
|
195
|
+
reqPduBuffer.writeUInt16BE(startRegister, 1);
|
|
196
|
+
reqPduBuffer.writeUInt16BE(registerQuantity, 3);
|
|
197
|
+
reqPduBuffer[5]= 2*registerQuantity;
|
|
198
|
+
values.copy(reqPduBuffer, 6);
|
|
199
|
+
return reqPduBuffer;
|
|
200
|
+
}
|
|
201
|
+
else{
|
|
202
|
+
throw new RangeError('Error, values length exceed the max pdu length', 'modbus_master.js', 180);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else{
|
|
206
|
+
throw new TypeError('Error, values must be a Buffer', 'modbus_master.js', 180);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @brief function to make the request pdu for function code 22 of modbus protocol.
|
|
213
|
+
* @param {Buffer} values value to write.
|
|
214
|
+
* @param {number} startRegister register to write.
|
|
215
|
+
* @return {buffer} pdu buffer
|
|
216
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
217
|
+
* @throws {RangeError} if values's length is diferent than 4.
|
|
218
|
+
*/
|
|
219
|
+
maskHoldingRegisterPdu( values, startRegister = 0){
|
|
220
|
+
//function 22 mask holding register
|
|
221
|
+
if(values instanceof Buffer){
|
|
222
|
+
if(values.length == 4){
|
|
223
|
+
let reqPduBuffer = Buffer.alloc(7);
|
|
224
|
+
reqPduBuffer[0] = 0x16;
|
|
225
|
+
reqPduBuffer.writeUInt16BE(startRegister, 1);
|
|
226
|
+
values.copy(reqPduBuffer, 3);
|
|
227
|
+
return reqPduBuffer;
|
|
228
|
+
}
|
|
229
|
+
else{
|
|
230
|
+
throw new RangeError('Error, values length diferent than 4', 'modbus_master.js');
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else{
|
|
234
|
+
throw new TypeError('Error, values must be a Buffer', 'modbus_master.js', 203);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @brief function to make the request pdu for function code 23 of modbus protocol.
|
|
241
|
+
* @param {Buffer} values values to write.
|
|
242
|
+
* @param {number} readStartingAddress first register to read.
|
|
243
|
+
* @param {number} quantitytoRead number of registers to read
|
|
244
|
+
* @param {number} writeStartingAddress first register to write.
|
|
245
|
+
* @param {number} quantityToWrite number of registers to weite
|
|
246
|
+
* @return {buffer} pdu buffer.
|
|
247
|
+
* @throws {TypeError} if values is not a buffer's instance.
|
|
248
|
+
* @throws {RangeError} if values's length is greater than 242.
|
|
249
|
+
*/
|
|
250
|
+
readWriteMultipleRegistersPdu(values, readStartingAddress, quantitytoRead, writeStartingAddress, quantityToWrite = Math.floor(values.length/2)){
|
|
251
|
+
//function 23 write and read multiples registers
|
|
252
|
+
if(values instanceof Buffer){
|
|
253
|
+
if(values.length <= 242){
|
|
254
|
+
//creando la pdu del request
|
|
255
|
+
let reqPduBuffer = Buffer.alloc(10 + quantityToWrite*2);
|
|
256
|
+
reqPduBuffer[0] = 0x17;
|
|
257
|
+
reqPduBuffer.writeUInt16BE(readStartingAddress, 1);
|
|
258
|
+
reqPduBuffer.writeUInt16BE(quantitytoRead, 3);
|
|
259
|
+
reqPduBuffer.writeUInt16BE(writeStartingAddress, 5);
|
|
260
|
+
reqPduBuffer.writeUInt16BE(quantityToWrite, 7);
|
|
261
|
+
reqPduBuffer[9]= quantityToWrite*2;
|
|
262
|
+
values.copy(reqPduBuffer, 10);
|
|
263
|
+
return reqPduBuffer;
|
|
264
|
+
}
|
|
265
|
+
else{
|
|
266
|
+
throw new RangeError('Error, values length exceed the max pdu length', 'modbus_master.js', 180);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else{
|
|
270
|
+
throw new TypeError('Error, values must be a Buffer', 'modbus_master.js', 180);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Function to get a buffer from a bool value for function 5 of modbus protocol.
|
|
276
|
+
* @param {boolean} value Bool value.
|
|
277
|
+
* @return {Buffer} A buffer that can be 0x0000 for false or 0xFF00 for true value
|
|
278
|
+
*/
|
|
279
|
+
boolToBuffer(value){
|
|
280
|
+
let valBuffer = Buffer.alloc(2)
|
|
281
|
+
if(value){
|
|
282
|
+
valBuffer[0] = 0xFF;
|
|
283
|
+
}
|
|
284
|
+
return valBuffer
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
ModbusClient.prototype.getMaskRegisterBuffer = utils.getMaskRegisterBuffer;
|
|
291
|
+
|
|
292
|
+
ModbusClient.prototype.boolsToBuffer = utils.boolsToBuffer;
|
|
293
|
+
|
|
294
|
+
ModbusClient.prototype.getWordFromBuffer = utils.getWordFromBuffer;
|
|
295
|
+
|
|
296
|
+
ModbusClient.prototype.setWordToBuffer = utils.setWordToBuffer;
|
|
297
|
+
|
|
298
|
+
module.exports = ModbusClient;
|