@ncd-io/node-red-enterprise-sensors 1.6.3 → 2.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.
@@ -0,0 +1,680 @@
1
+ const { toMac, signInt, msbLsb } = require('../utils');
2
+
3
+ // --- 1. DEFINE LOCAL FUNCTIONS ---
4
+ // These are defined as local variables so they can call each other easily.
5
+ module.exports = (globalDevices) => {
6
+
7
+ const get_write_buffer_size = (firmware) => {
8
+ return 43;
9
+ };
10
+
11
+ const get_config_map = (firmware) => {
12
+ console.log('Generating sync map for firmware version', firmware);
13
+
14
+ return {
15
+ "core_version": {
16
+ "read_index": 3,
17
+ "descriptions": {
18
+ "title": "Core Version",
19
+ "main_caption": "The version of the core communication stack."
20
+ },
21
+ "validator": {
22
+ "type": "uint8"
23
+ },
24
+ "tags": [
25
+ "system"
26
+ ]
27
+ },
28
+ "firmware_version": {
29
+ "read_index": 4,
30
+ "descriptions": {
31
+ "title": "Firmware Version",
32
+ "main_caption": "The application-specific firmware version."
33
+ },
34
+ "validator": {
35
+ "type": "uint8"
36
+ },
37
+ "tags": [
38
+ "system"
39
+ ]
40
+ },
41
+ "sensor_type": {
42
+ "read_index": 5,
43
+ "descriptions": {
44
+ "title": "Sensor Type",
45
+ "main_caption": "The hardware identifier for the specific sensor model."
46
+ },
47
+ "validator": {
48
+ "type": "uint16be"
49
+ },
50
+ "tags": [
51
+ "system"
52
+ ]
53
+ },
54
+ "tx_lifetime_counter": {
55
+ "read_index": 7,
56
+ "descriptions": {
57
+ "title": "Sampling Interval",
58
+ "main_caption": "Set how often will the sensor transmit measurement data. Note: For this sensor, this value functions as the sampling interval rather than a traditional delay.",
59
+ "sub_caption": "Default value: 20 milliseconds."
60
+ },
61
+ "validator": {
62
+ "type": "uint32be"
63
+ },
64
+ "tags": [
65
+ "diagnostics"
66
+ ]
67
+ },
68
+ "hardware_id": {
69
+ "read_index": 11,
70
+ "length": 3,
71
+ "descriptions": {
72
+ "title": "Hardware ID",
73
+ "main_caption": "A unique 3-byte hardware identifier."
74
+ },
75
+ "validator": {
76
+ "type": "buffer"
77
+ },
78
+ "tags": [
79
+ "system"
80
+ ]
81
+ },
82
+ "network_id": {
83
+ "read_index": 14,
84
+ "write_index": 3,
85
+ "length": 2,
86
+ "descriptions": {
87
+ "title": "Network ID",
88
+ "main_caption": ""
89
+ },
90
+ "default_value": "7fff",
91
+ "validator": {
92
+ "type": "hex",
93
+ "length": 4
94
+ },
95
+ "html_id": "pan_id",
96
+ "tags": [
97
+ "communications"
98
+ ]
99
+ },
100
+ "destination_address": {
101
+ "read_index": 16,
102
+ "write_index": 5,
103
+ "length": 4,
104
+ "descriptions": {
105
+ "title": "Destination Address",
106
+ "main_caption": ""
107
+ },
108
+ "default_value": "0000ffff",
109
+ "validator": {
110
+ "type": "mac",
111
+ "length": 8
112
+ },
113
+ "html_id": "destination",
114
+ "tags": [
115
+ "communications"
116
+ ]
117
+ },
118
+ "node_id": {
119
+ "read_index": 20,
120
+ "write_index": 9,
121
+ "descriptions": {
122
+ "title": "Node ID",
123
+ "main_caption": ""
124
+ },
125
+ "default_value": "0",
126
+ "validator": {
127
+ "type": "uint8",
128
+ "min": 0,
129
+ "max": 255,
130
+ "generated": true
131
+ },
132
+ "html_id": "node_id",
133
+ "tags": [
134
+ "generic"
135
+ ]
136
+ },
137
+ "debouncing_timeout": {
138
+ "read_index": 21,
139
+ "write_index": 10,
140
+ "descriptions": {
141
+ "title": "Set Input Debounce Time",
142
+ "main_caption": "Configures the debounce time in milliseconds for all inputs. State changes occurring within this debounce period will be ignored."
143
+ },
144
+ "default_value": 10,
145
+ "validator": {
146
+ "type": "uint16be",
147
+ "min": 10,
148
+ "max": 65000,
149
+ "generated": true
150
+ },
151
+ "html_id": "debounce_time_123"
152
+ },
153
+ "input_1_active_edge": {
154
+ "read_index": 23,
155
+ "write_index": 12,
156
+ "descriptions": {
157
+ "title": "Set Input 1 Detection",
158
+ "main_caption": "Configures how the counter increments and how uptime is calculated for Input 1."
159
+ },
160
+ "default_value": 0,
161
+ "validator": {
162
+ "type": "uint8",
163
+ "min": 0,
164
+ "max": 1,
165
+ "generated": true
166
+ },
167
+ "options": {
168
+ "0": "Falling Edge Trigger",
169
+ "1": "Rising Edge Trigger"
170
+ },
171
+ "html_id": "input_one_123"
172
+ },
173
+ "input_2_active_edge": {
174
+ "read_index": 24,
175
+ "write_index": 13,
176
+ "descriptions": {
177
+ "title": "Set Input 2 Detection",
178
+ "main_caption": "Configures how the counter increments and how uptime is calculated for Input 2."
179
+ },
180
+ "default_value": 0,
181
+ "validator": {
182
+ "type": "uint8",
183
+ "min": 0,
184
+ "max": 1,
185
+ "generated": true
186
+ },
187
+ "options": {
188
+ "0": "Falling Edge Trigger",
189
+ "1": "Rising Edge Trigger"
190
+ },
191
+ "html_id": "input_two_123"
192
+ },
193
+ "input_3_active_edge": {
194
+ "read_index": 25,
195
+ "write_index": 14,
196
+ "descriptions": {
197
+ "title": "Set Input 3 Detection",
198
+ "main_caption": "Configures how the counter increments and how uptime is calculated for Input 3."
199
+ },
200
+ "default_value": 0,
201
+ "validator": {
202
+ "type": "uint8",
203
+ "min": 0,
204
+ "max": 1,
205
+ "generated": true
206
+ },
207
+ "options": {
208
+ "0": "Falling Edge Trigger",
209
+ "1": "Rising Edge Trigger"
210
+ },
211
+ "html_id": "input_three_123"
212
+ },
213
+ "counter_threshold": {
214
+ "read_index": 26,
215
+ "write_index": 15,
216
+ "descriptions": {
217
+ "title": "Counter Threshold",
218
+ "main_caption": "The sensor will transmit data when any connected counter reaches a multiple of this threshold value."
219
+ },
220
+ "default_value": 0,
221
+ "validator": {
222
+ "type": "uint32be",
223
+ "min": 1,
224
+ "max": 65534,
225
+ "generated": true
226
+ },
227
+ "html_id": "counter_threshold_108"
228
+ },
229
+ "trasnmit_on_change_status": {
230
+ "read_index": 30,
231
+ "write_index": 19,
232
+ "descriptions": {
233
+ "title": "Enable Push Notification",
234
+ "main_caption": "Enables the sensor to immediately transmit data upon detecting a signal change on the specified input(s)."
235
+ },
236
+ "default_value": 0,
237
+ "validator": {
238
+ "type": "uint8",
239
+ "min": 0,
240
+ "max": 7,
241
+ "generated": true
242
+ },
243
+ "options": {
244
+ "0": "Disabled",
245
+ "1": "Enable on IO1",
246
+ "2": "Enable on IO2",
247
+ "3": "Enable on IO3",
248
+ "4": "Enable on IO1 and IO2",
249
+ "5": "Enable on IO1 and IO3",
250
+ "6": "Enable on IO2 and IO3",
251
+ "7": "Enable All"
252
+ },
253
+ "html_id": "push_notification_123"
254
+ },
255
+ "shift_end_one_hours": {
256
+ "read_index": 31,
257
+ "write_index": 20,
258
+ "descriptions": {
259
+ "title": "Shift 1 End Time Hours",
260
+ "main_caption": "Based on the Real-Time Clock (RTC), configures one of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
261
+ },
262
+ "default_value": 0,
263
+ "validator": {
264
+ "type": "uint8",
265
+ "min": 0,
266
+ "max": 24,
267
+ "generated": true
268
+ },
269
+ "html_id": "shift_one_hours_108",
270
+ "html_active_id": "shift_one_108_active"
271
+ },
272
+ "shift_end_one_minutes": {
273
+ "read_index": 32,
274
+ "write_index": 21,
275
+ "descriptions": {
276
+ "title": "Shift 1 End Time Minutes",
277
+ "main_caption": "Based on the Real-Time Clock (RTC), configures one of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
278
+ },
279
+ "default_value": 0,
280
+ "validator": {
281
+ "type": "uint8",
282
+ "min": 0,
283
+ "max": 60,
284
+ "generated": true
285
+ },
286
+ "html_id": "shift_one_minutes_108",
287
+ "html_active_id": "shift_one_108_active"
288
+ },
289
+ "shift_end_two_hours": {
290
+ "read_index": 33,
291
+ "write_index": 22,
292
+ "descriptions": {
293
+ "title": "Shift 2 End Time Hours",
294
+ "main_caption": "Based on the Real-Time Clock (RTC), configures two of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
295
+ },
296
+ "default_value": 0,
297
+ "validator": {
298
+ "type": "uint8",
299
+ "min": 0,
300
+ "max": 24,
301
+ "generated": true
302
+ },
303
+ "html_id": "shift_two_hours_108",
304
+ "html_active_id": "shift_two_108_active"
305
+ },
306
+ "shift_end_two_minutes": {
307
+ "read_index": 34,
308
+ "write_index": 23,
309
+ "descriptions": {
310
+ "title": "Shift 2 End Time Minutes",
311
+ "main_caption": "Based on the Real-Time Clock (RTC), configures two of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
312
+ },
313
+ "default_value": 0,
314
+ "validator": {
315
+ "type": "uint8",
316
+ "min": 0,
317
+ "max": 60,
318
+ "generated": true
319
+ },
320
+ "html_id": "shift_two_minutes_108",
321
+ "html_active_id": "shift_two_108_active"
322
+ },
323
+ "shift_end_three_hours": {
324
+ "read_index": 35,
325
+ "write_index": 24,
326
+ "descriptions": {
327
+ "title": "Shift 3 End Time Hours",
328
+ "main_caption": "Based on the Real-Time Clock (RTC), configures three of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
329
+ },
330
+ "default_value": 0,
331
+ "validator": {
332
+ "type": "uint8",
333
+ "min": 0,
334
+ "max": 24,
335
+ "generated": true
336
+ },
337
+ "html_id": "shift_three_hours_108",
338
+ "html_active_id": "shift_three_108_active"
339
+ },
340
+ "shift_end_three_minutes": {
341
+ "read_index": 36,
342
+ "write_index": 25,
343
+ "descriptions": {
344
+ "title": "Shift 3 End Time Minutes",
345
+ "main_caption": "Based on the Real-Time Clock (RTC), configures three of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
346
+ },
347
+ "default_value": 0,
348
+ "validator": {
349
+ "type": "uint8",
350
+ "min": 0,
351
+ "max": 60,
352
+ "generated": true
353
+ },
354
+ "html_id": "shift_three_minutes_108",
355
+ "html_active_id": "shift_three_108_active"
356
+ },
357
+ "shift_end_four_hours": {
358
+ "read_index": 37,
359
+ "write_index": 26,
360
+ "descriptions": {
361
+ "title": "Shift 4 End Time Hours",
362
+ "main_caption": "Based on the Real-Time Clock (RTC), configures four of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
363
+ },
364
+ "default_value": 0,
365
+ "validator": {
366
+ "type": "uint8",
367
+ "min": 0,
368
+ "max": 24,
369
+ "generated": true
370
+ },
371
+ "html_id": "shift_four_hours_108",
372
+ "html_active_id": "shift_four_108_active"
373
+ },
374
+ "shift_end_four_minutes": {
375
+ "read_index": 38,
376
+ "write_index": 27,
377
+ "descriptions": {
378
+ "title": "Shift 4 End Time Minutes",
379
+ "main_caption": "Based on the Real-Time Clock (RTC), configures four of four specific daily times (24-hour format) for the sensor to perform an automatic reset."
380
+ },
381
+ "default_value": 0,
382
+ "validator": {
383
+ "type": "uint8",
384
+ "min": 0,
385
+ "max": 60,
386
+ "generated": true
387
+ },
388
+ "html_id": "shift_four_minutes_108",
389
+ "html_active_id": "shift_four_108_active"
390
+ },
391
+ "reset_timeout": {
392
+ "read_index": 39,
393
+ "write_index": 28,
394
+ "descriptions": {
395
+ "title": "Reset Timeout",
396
+ "main_caption": "Defines the duration (in seconds) after which the sensor will automatically reset. Before resetting, it will transmit its current data values."
397
+ },
398
+ "default_value": 60,
399
+ "validator": {
400
+ "type": "uint16be",
401
+ "min": 10,
402
+ "max": 65000,
403
+ "generated": true
404
+ },
405
+ "html_id": "reset_timeout_108"
406
+ },
407
+ "counter_reset_mode": {
408
+ "read_index": 41,
409
+ "write_index": 30,
410
+ "descriptions": {
411
+ "title": "Set Reset Mode",
412
+ "main_caption": "This setting specifies which automatic reset option the sensor will utilize."
413
+ },
414
+ "default_value": 0,
415
+ "validator": {
416
+ "type": "uint8",
417
+ "min": 0,
418
+ "max": 2,
419
+ "generated": true
420
+ },
421
+ "options": {
422
+ "0": "Do not reset counters",
423
+ "1": "Based on Shift Ends",
424
+ "2": "Based on the Timeout Provided"
425
+ },
426
+ "html_id": "reset_mode_to_disabled_108"
427
+ },
428
+ "sampling_interval": {
429
+ "read_index": 42,
430
+ "write_index": 31,
431
+ "descriptions": {
432
+ "title": "Data Transmission Interval",
433
+ "main_caption": "Sets the regular interval at which the sensor wakes up and transmits its data. This interval operates independently of any interrupt-driven (Push Notifications or Resets)."
434
+ },
435
+ "default_value": 2,
436
+ "validator": {
437
+ "type": "uint8",
438
+ "min": 0,
439
+ "max": 12,
440
+ "generated": true
441
+ },
442
+ "options": {
443
+ "0": "1 minute",
444
+ "1": "5 minutes",
445
+ "2": "15 minutes",
446
+ "3": "30 minutes",
447
+ "4": "1 hour",
448
+ "5": "2 hours",
449
+ "6": "3 hours",
450
+ "7": "6 hours",
451
+ "8": "12 hours",
452
+ "9": "5 seconds",
453
+ "10": "10 seconds",
454
+ "11": "15 seconds",
455
+ "12": "30 seconds"
456
+ },
457
+ "html_id": "transmission_interval_108"
458
+ },
459
+ "interrupt_timeout": {
460
+ "read_index": 43,
461
+ "write_index": 32,
462
+ "descriptions": {
463
+ "title": "Set Interrupt Timeout",
464
+ "main_caption": "Set the sensor to detect an initial IO (input/output) change and not transmit subsequent IO changes for a specified duration; set the duration value to control how long changes are ignored in milliseconds, set it to 0 to disable ignoring."
465
+ },
466
+ "default_value": 0,
467
+ "validator": {
468
+ "type": "uint16be",
469
+ "min": 0,
470
+ "max": 65000,
471
+ "generated": true
472
+ },
473
+ "html_id": "interrupt_timeout_35"
474
+ },
475
+ "current_sensor_1_ct": {
476
+ "read_index": 45,
477
+ "write_index": 34,
478
+ "descriptions": {
479
+ "title": "Set Sensor One CT",
480
+ "main_caption": "Select the AC Current probe type for Input 1."
481
+ },
482
+ "default_value": 0,
483
+ "validator": {
484
+ "type": "uint8",
485
+ "min": 0,
486
+ "max": 3,
487
+ "generated": true
488
+ },
489
+ "options": {
490
+ "0": "100A",
491
+ "1": "200A",
492
+ "2": "600A",
493
+ "3": "1000A"
494
+ },
495
+ "html_id": "probe_one_126"
496
+ },
497
+ "current_sensor_2_ct": {
498
+ "read_index": 46,
499
+ "write_index": 35,
500
+ "descriptions": {
501
+ "title": "Set Sensor Two CT",
502
+ "main_caption": "Select the AC Current probe type for Input 2."
503
+ },
504
+ "default_value": 0,
505
+ "validator": {
506
+ "type": "uint8",
507
+ "min": 0,
508
+ "max": 3,
509
+ "generated": true
510
+ },
511
+ "options": {
512
+ "0": "100A",
513
+ "1": "200A",
514
+ "2": "600A",
515
+ "3": "1000A"
516
+ },
517
+ "html_id": "probe_two_126"
518
+ },
519
+ "current_sensor_3_ct": {
520
+ "read_index": 47,
521
+ "write_index": 36,
522
+ "descriptions": {
523
+ "title": "Set Sensor Three CT",
524
+ "main_caption": "Select the AC Current probe type for Input 3."
525
+ },
526
+ "default_value": 0,
527
+ "validator": {
528
+ "type": "uint8",
529
+ "min": 0,
530
+ "max": 3,
531
+ "generated": true
532
+ },
533
+ "options": {
534
+ "0": "100A",
535
+ "1": "200A",
536
+ "2": "600A",
537
+ "3": "1000A"
538
+ },
539
+ "html_id": "probe_three_126"
540
+ },
541
+ "threshold_current_sensor_1": {
542
+ "read_index": 48,
543
+ "write_index": 37,
544
+ "descriptions": {
545
+ "title": "Set AC Current Threshold One",
546
+ "main_caption": "The sensor increments the cycle counter and calculates uptime once the measured AC Current exceeds this threshold."
547
+ },
548
+ "default_value": 3,
549
+ "validator": {
550
+ "type": "uint16be",
551
+ "min": 0,
552
+ "max": 65000,
553
+ "generated": true
554
+ },
555
+ "html_id": "threshold_probe_one_126"
556
+ },
557
+ "threshold_current_sensor_2": {
558
+ "read_index": 50,
559
+ "write_index": 39,
560
+ "descriptions": {
561
+ "title": "Set AC Current Threshold Two",
562
+ "main_caption": "The sensor increments the cycle counter and calculates uptime once the measured AC Current exceeds this threshold."
563
+ },
564
+ "default_value": 3,
565
+ "validator": {
566
+ "type": "uint16be",
567
+ "min": 0,
568
+ "max": 65000,
569
+ "generated": true
570
+ },
571
+ "html_id": "threshold_probe_two_126"
572
+ },
573
+ "threshold_current_sensor_3": {
574
+ "read_index": 52,
575
+ "write_index": 41,
576
+ "descriptions": {
577
+ "title": "Set AC Current Threshold Three",
578
+ "main_caption": "The sensor increments the cycle counter and calculates uptime once the measured AC Current exceeds this threshold."
579
+ },
580
+ "default_value": 3,
581
+ "validator": {
582
+ "type": "uint16be",
583
+ "min": 0,
584
+ "max": 65000,
585
+ "generated": true
586
+ },
587
+ "html_id": "threshold_probe_three_126"
588
+ }
589
+ };
590
+ };
591
+
592
+ const sync_parse = (rep_buffer) => {
593
+ let response = {};
594
+
595
+ // Get the map based on the sensor type byte
596
+ const sync_map = get_config_map(rep_buffer[4]);
597
+
598
+ for (const [key, config] of Object.entries(sync_map)) {
599
+ // Destructure 'type' from inside 'validator' and rename 'read_index' to 'idx'
600
+ const { read_index: idx, length, validator: { type } = {} } = config;
601
+
602
+ // If for some reason a config doesn't have a validator/type, skip it
603
+ if (!type) continue;
604
+
605
+ switch (type) {
606
+ case 'uint8':
607
+ response[key] = rep_buffer[idx];
608
+ break;
609
+ case 'uint16be':
610
+ response[key] = rep_buffer.readUInt16BE(idx);
611
+ break;
612
+ case 'uint32be':
613
+ response[key] = rep_buffer.readUInt32BE(idx);
614
+ break;
615
+ case 'buffer':
616
+ response[key] = rep_buffer.subarray(idx, idx + length);
617
+ break;
618
+ case 'hex':
619
+ response[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
620
+ break;
621
+ case 'mac':
622
+ response[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
623
+ break;
624
+ }
625
+ }
626
+ // if(Object.hasOwn(response, 'destination_address') && response.destination_address.toLowerCase() === '00000000') {
627
+ // console.log('##############################');
628
+ // console.log('#########Dest Override########');
629
+ // console.log('##############################');
630
+ // response.destination_address = "0000ffff";
631
+ // response.auto_raw_destination_address = "0000ffff";
632
+ // };
633
+ return response;
634
+ };
635
+
636
+ const parse = (d, payload) => {
637
+ let report_type = "Regular";
638
+ switch(d[25]){
639
+ case 0:
640
+ report_type = "Regular";
641
+ break;
642
+ case 1:
643
+ report_type = "Shift end";
644
+ break;
645
+ case 2:
646
+ report_type = "Interrupt";
647
+ break;
648
+ case 3:
649
+ report_type = "Threshold";
650
+ break;
651
+ }
652
+ return {
653
+ input_1_counter: d.slice(0, 4).reduce(msbLsb),
654
+ input_1_uptime: d.slice(4, 8).reduce(msbLsb),
655
+ input_2_counter: d.slice(8, 12).reduce(msbLsb),
656
+ input_2_uptime: d.slice(12, 16).reduce(msbLsb),
657
+ input_3_counter: d.slice(16, 20).reduce(msbLsb),
658
+ input_3_uptime: d.slice(20, 24).reduce(msbLsb),
659
+ input_1: d[24] & 1 ? 1 : 0,
660
+ input_2: d[24] & 2 ? 1 : 0,
661
+ input_3: d[24] & 4 ? 1 : 0,
662
+ report_type: report_type,
663
+ rtc: [
664
+ String(d[26]).padStart(2, '0'),
665
+ String(d[27]).padStart(2, '0'),
666
+ String(d[28]).padStart(2, '0')
667
+ ].join(':')
668
+ };
669
+ };
670
+
671
+ // --- 2. EXPORT THE MODULE ---
672
+ return {
673
+ type: 126,
674
+ name: '3 Channel OEE AC Current Production Monitor Sensor',
675
+ parse,
676
+ get_write_buffer_size,
677
+ get_config_map,
678
+ sync_parse
679
+ };
680
+ };
package/lib/utils.js ADDED
@@ -0,0 +1,27 @@
1
+ // lib/utils.js
2
+
3
+ module.exports = {
4
+ /**
5
+ * Converts a buffer or array to a colon-separated MAC string
6
+ */
7
+ toMac: (data) => {
8
+ // Ensure we are working with a Buffer for consistent hex conversion
9
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
10
+ return buf.toString('hex').match(/.{1,2}/g).join(':');
11
+ },
12
+
13
+ /**
14
+ * Common bit-shifting for legacy MSB/LSB math if needed
15
+ */
16
+ msbLsb: (msb, lsb) => (msb << 8) | lsb,
17
+
18
+ /**
19
+ * Formats battery voltage from raw value
20
+ */
21
+ formatBattery: (val) => (val / 100).toFixed(2) + 'V',
22
+
23
+ signInt(i, b){
24
+ if(i.toString(2).length != b) return i;
25
+ return -(((~i) & ((1 << (b-1))-1))+1);
26
+ }
27
+ };