@ncd-io/node-red-enterprise-sensors 2.0.2 → 2.0.4

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,708 @@
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 52;
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
+ "report_rate": {
138
+ "read_index": 21,
139
+ "write_index": 10,
140
+ "descriptions": {
141
+ "title": "Delay",
142
+ "main_caption": ""
143
+ },
144
+ "default_value": 3,
145
+ "validator": {
146
+ "type": "uint32be"
147
+ },
148
+ "html_id": "delay"
149
+ },
150
+ "oxygen_bootup_time": {
151
+ "read_index": 25,
152
+ "write_index": 14,
153
+ "descriptions": {
154
+ "title": "Sensor Boot Time",
155
+ "main_caption": "This value represents the number of seconds to wait after applying power to the Oxygen sensor before taking a reading."
156
+ },
157
+ "default_value": 3,
158
+ "validator": {
159
+ "type": "uint8",
160
+ "min": 1,
161
+ "max": 100
162
+ },
163
+ "html_id": "oxygen_boot_time_536"
164
+ },
165
+ "flow_bootup_time": {
166
+ "read_index": 26,
167
+ "write_index": 15,
168
+ "descriptions": {
169
+ "title": "Set Flow Boot Time",
170
+ "main_caption": "This value represents the number of seconds to wait after applying power to the Flow sensor before taking a reading."
171
+ },
172
+ "default_value": 3,
173
+ "validator": {
174
+ "type": "uint8",
175
+ "min": 1,
176
+ "max": 100
177
+ },
178
+ "html_id": "flow_boot_time_536"
179
+ },
180
+ "s1_oxygen_addr": {
181
+ "read_index": 27,
182
+ "write_index": 16,
183
+ "descriptions": {
184
+ "title": "Set Oxygen Sensors Addresses",
185
+ "main_caption": "Set the Modbus Slave device address connected to this device"
186
+ },
187
+ "default_value": 0,
188
+ "validator": {
189
+ "type": "uint8",
190
+ "min": 0,
191
+ "max": 255
192
+ },
193
+ "html_id": "oxygen_addr_1_536",
194
+ "html_active_id": "oxygen_dev_addr_536_active"
195
+ },
196
+ "s2_oxygen_addr": {
197
+ "read_index": 28,
198
+ "write_index": 17,
199
+ "descriptions": {
200
+ "title": "Set Oxygen Sensors Addresses",
201
+ "main_caption": "Set the Modbus Slave device address connected to this device"
202
+ },
203
+ "default_value": 0,
204
+ "validator": {
205
+ "type": "uint8",
206
+ "min": 0,
207
+ "max": 255
208
+ },
209
+ "html_id": "oxygen_addr_2_536",
210
+ "html_active_id": "oxygen_dev_addr_536_active"
211
+ },
212
+ "s3_oxygen_addr": {
213
+ "read_index": 29,
214
+ "write_index": 18,
215
+ "descriptions": {
216
+ "title": "Set Oxygen Sensors Addresses",
217
+ "main_caption": "Set the Modbus Slave device address connected to this device"
218
+ },
219
+ "default_value": 0,
220
+ "validator": {
221
+ "type": "uint8",
222
+ "min": 0,
223
+ "max": 255
224
+ },
225
+ "html_id": "oxygen_addr_3_536",
226
+ "html_active_id": "oxygen_dev_addr_536_active"
227
+ },
228
+ "s4_oxygen_addr": {
229
+ "read_index": 30,
230
+ "write_index": 19,
231
+ "descriptions": {
232
+ "title": "Set Oxygen Sensors Addresses",
233
+ "main_caption": "Set the Modbus Slave device address connected to this device"
234
+ },
235
+ "default_value": 0,
236
+ "validator": {
237
+ "type": "uint8",
238
+ "min": 0,
239
+ "max": 255
240
+ },
241
+ "html_id": "oxygen_addr_4_536",
242
+ "html_active_id": "oxygen_dev_addr_536_active"
243
+ },
244
+ "s1_flow_addr": {
245
+ "read_index": 31,
246
+ "write_index": 20,
247
+ "descriptions": {
248
+ "title": "Set Flow Sensors Addresses",
249
+ "main_caption": "Set the Modbus Slave device address connected to this device"
250
+ },
251
+ "default_value": 0,
252
+ "validator": {
253
+ "type": "uint8",
254
+ "min": 0,
255
+ "max": 255
256
+ },
257
+ "html_id": "flow_addr_1_536",
258
+ "html_active_id": "flow_dev_addr_536_active"
259
+ },
260
+ "s2_flow_addr": {
261
+ "read_index": 32,
262
+ "write_index": 21,
263
+ "descriptions": {
264
+ "title": "Set Flow Sensors Addresses",
265
+ "main_caption": "Set the Modbus Slave device address connected to this device"
266
+ },
267
+ "default_value": 0,
268
+ "validator": {
269
+ "type": "uint8",
270
+ "min": 0,
271
+ "max": 255
272
+ },
273
+ "html_id": "flow_addr_2_536",
274
+ "html_active_id": "flow_dev_addr_536_active"
275
+ },
276
+ "s3_flow_addr": {
277
+ "read_index": 33,
278
+ "write_index": 22,
279
+ "descriptions": {
280
+ "title": "Set Flow Sensors Addresses",
281
+ "main_caption": "Set the Modbus Slave device address connected to this device"
282
+ },
283
+ "default_value": 0,
284
+ "validator": {
285
+ "type": "uint8",
286
+ "min": 0,
287
+ "max": 255
288
+ },
289
+ "html_id": "flow_addr_3_536",
290
+ "html_active_id": "flow_dev_addr_536_active"
291
+ },
292
+ "s4_flow_addr": {
293
+ "read_index": 34,
294
+ "write_index": 23,
295
+ "descriptions": {
296
+ "title": "Set Flow Sensors Addresses",
297
+ "main_caption": "Set the Modbus Slave device address connected to this device"
298
+ },
299
+ "default_value": 0,
300
+ "validator": {
301
+ "type": "uint8",
302
+ "min": 0,
303
+ "max": 255
304
+ },
305
+ "html_id": "flow_addr_4_536",
306
+ "html_active_id": "flow_dev_addr_536_active"
307
+ },
308
+ "oxygen_max_threshold_sensor_1": {
309
+ "read_index": 35,
310
+ "write_index": 24,
311
+ "descriptions": {
312
+ "title": "Set Oxygen Max Threshold Sensor 1",
313
+ "main_caption": "Valid range: 0 - 2000"
314
+ },
315
+ "default_value": 1200,
316
+ "validator": {
317
+ "type": "uint16be",
318
+ "min": 0,
319
+ "max": 2000
320
+ },
321
+ "converter": {
322
+ "units": "dg/l"
323
+ },
324
+ "html_id": "oxygen_max_threshold_s1_536"
325
+ },
326
+ "oxygen_max_threshold_sensor_2": {
327
+ "read_index": 37,
328
+ "write_index": 26,
329
+ "descriptions": {
330
+ "title": "Set Oxygen Max Threshold Sensor 2",
331
+ "main_caption": "Valid range: 0 - 2000"
332
+ },
333
+ "default_value": 1200,
334
+ "validator": {
335
+ "type": "uint16be",
336
+ "min": 0,
337
+ "max": 2000
338
+ },
339
+ "converter": {
340
+ "units": "dg/l"
341
+ },
342
+ "html_id": "oxygen_max_threshold_s2_536"
343
+ },
344
+ "oxygen_max_threshold_sensor_3": {
345
+ "read_index": 39,
346
+ "write_index": 28,
347
+ "descriptions": {
348
+ "title": "Set Oxygen Max Threshold Sensor 3",
349
+ "main_caption": "Valid range: 0 - 2000"
350
+ },
351
+ "default_value": 1200,
352
+ "validator": {
353
+ "type": "uint16be",
354
+ "min": 0,
355
+ "max": 2000
356
+ },
357
+ "converter": {
358
+ "units": "dg/l"
359
+ },
360
+ "html_id": "oxygen_max_threshold_s3_536"
361
+ },
362
+ "oxygen_max_threshold_sensor_4": {
363
+ "read_index": 41,
364
+ "write_index": 30,
365
+ "descriptions": {
366
+ "title": "Set Oxygen Max Threshold Sensor 4",
367
+ "main_caption": "Valid range: 0 - 2000"
368
+ },
369
+ "default_value": 1200,
370
+ "validator": {
371
+ "type": "uint16be",
372
+ "min": 0,
373
+ "max": 2000
374
+ },
375
+ "converter": {
376
+ "units": "dg/l"
377
+ },
378
+ "html_id": "oxygen_max_threshold_s4_536"
379
+ },
380
+ "oxygen_min_threshold_sensor_1": {
381
+ "read_index": 43,
382
+ "write_index": 32,
383
+ "descriptions": {
384
+ "title": "Set Oxygen Min Threshold Sensor 1",
385
+ "main_caption": "Valid range: 0 - 2000"
386
+ },
387
+ "default_value": 1200,
388
+ "validator": {
389
+ "type": "uint16be",
390
+ "min": 0,
391
+ "max": 2000
392
+ },
393
+ "converter": {
394
+ "units": "dg/l"
395
+ },
396
+ "html_id": "oxygen_min_threshold_s1_536"
397
+ },
398
+ "oxygen_min_threshold_sensor_2": {
399
+ "read_index": 45,
400
+ "write_index": 34,
401
+ "descriptions": {
402
+ "title": "Set Oxygen Min Threshold Sensor 2",
403
+ "main_caption": "Valid range: 0 - 2000"
404
+ },
405
+ "default_value": 1200,
406
+ "validator": {
407
+ "type": "uint16be",
408
+ "min": 0,
409
+ "max": 2000
410
+ },
411
+ "converter": {
412
+ "units": "dg/l"
413
+ },
414
+ "html_id": "oxygen_min_threshold_s2_536"
415
+ },
416
+ "oxygen_min_threshold_sensor_3": {
417
+ "read_index": 47,
418
+ "write_index": 36,
419
+ "descriptions": {
420
+ "title": "Set Oxygen Min Threshold Sensor 3",
421
+ "main_caption": "Valid range: 0 - 2000"
422
+ },
423
+ "default_value": 1200,
424
+ "validator": {
425
+ "type": "uint16be",
426
+ "min": 0,
427
+ "max": 2000
428
+ },
429
+ "converter": {
430
+ "units": "dg/l"
431
+ },
432
+ "html_id": "oxygen_min_threshold_s3_536"
433
+ },
434
+ "oxygen_min_threshold_sensor_4": {
435
+ "read_index": 49,
436
+ "write_index": 38,
437
+ "descriptions": {
438
+ "title": "Set Oxygen Min Threshold Sensor 4",
439
+ "main_caption": "Valid range: 0 - 2000"
440
+ },
441
+ "default_value": 1200,
442
+ "validator": {
443
+ "type": "uint16be",
444
+ "min": 0,
445
+ "max": 2000
446
+ },
447
+ "converter": {
448
+ "units": "dg/l"
449
+ },
450
+ "html_id": "oxygen_min_threshold_s4_536"
451
+ },
452
+ "oxygen_sensor_baud_rate": {
453
+ "read_index": 51,
454
+ "write_index": 40,
455
+ "descriptions": {
456
+ "title": "Set Oxygen Sensor Baud Rate",
457
+ "main_caption": ""
458
+ },
459
+ "default_value": 0,
460
+ "validator": {
461
+ "type": "uint32be",
462
+ "min": 0,
463
+ "max": 115200,
464
+ "generated": true
465
+ },
466
+ "html_id": "oxygen_sensor_baud_rate_536"
467
+ },
468
+ "oxygen_sensor_parity_bits": {
469
+ "read_index": 55,
470
+ "write_index": 44,
471
+ "descriptions": {
472
+ "title": "Set Oxygen Sensor Parity Bits",
473
+ "main_caption": ""
474
+ },
475
+ "default_value": 0,
476
+ "validator": {
477
+ "type": "uint8",
478
+ "min": 0,
479
+ "max": 2,
480
+ "generated": true
481
+ },
482
+ "options": {
483
+ "0": "none",
484
+ "1": "odd",
485
+ "2": "Even"
486
+ },
487
+ "html_id": "oxygen_sensor_parity_bits_536"
488
+ },
489
+ "oxygen_sensor_stop_bits": {
490
+ "read_index": 56,
491
+ "write_index": 45,
492
+ "descriptions": {
493
+ "title": "Set Oxygen Sensor Stop Bits",
494
+ "main_caption": ""
495
+ },
496
+ "default_value": 0,
497
+ "validator": {
498
+ "type": "uint8",
499
+ "min": 0,
500
+ "max": 3,
501
+ "generated": true
502
+ },
503
+ "options": {
504
+ "0": "Half bits",
505
+ "1": "1 bit",
506
+ "2": "1.5 bits",
507
+ "3": "2 bits"
508
+ },
509
+ "html_id": "oxygen_sensor_stop_bits_536"
510
+ },
511
+ "flow_sensor_baud_rate": {
512
+ "read_index": 57,
513
+ "write_index": 46,
514
+ "descriptions": {
515
+ "title": "Set Flow Sensor Baud Rate",
516
+ "main_caption": ""
517
+ },
518
+ "default_value": 0,
519
+ "validator": {
520
+ "type": "uint32be",
521
+ "min": 0,
522
+ "max": 115200,
523
+ "generated": true
524
+ },
525
+ "html_id": "flow_sensor_baud_rate_536"
526
+ },
527
+ "flow_sensor_parity_bits": {
528
+ "read_index": 61,
529
+ "write_index": 50,
530
+ "descriptions": {
531
+ "title": "Set Flow Sensor Parity Bits",
532
+ "main_caption": ""
533
+ },
534
+ "default_value": 0,
535
+ "validator": {
536
+ "type": "uint8",
537
+ "min": 0,
538
+ "max": 2,
539
+ "generated": true
540
+ },
541
+ "options": {
542
+ "0": "none",
543
+ "1": "odd",
544
+ "2": "Even"
545
+ },
546
+ "html_id": "flow_sensor_parity_bits_536"
547
+ },
548
+ "flow_sensor_stop_bits": {
549
+ "read_index": 62,
550
+ "write_index": 51,
551
+ "descriptions": {
552
+ "title": "Set Flow Sensor Stop Bits",
553
+ "main_caption": ""
554
+ },
555
+ "default_value": 0,
556
+ "validator": {
557
+ "type": "uint8",
558
+ "min": 0,
559
+ "max": 3,
560
+ "generated": true
561
+ },
562
+ "options": {
563
+ "0": "Half bits",
564
+ "1": "1 bit",
565
+ "2": "1.5 bits",
566
+ "3": "2 bits"
567
+ },
568
+ "html_id": "flow_sensor_stop_bits_536"
569
+ }
570
+ };
571
+ };
572
+
573
+ const sync_parse = (rep_buffer) => {
574
+ let response = {
575
+ 'human_readable': {},
576
+ 'machine_values': {}
577
+ };
578
+
579
+ // Get the map based on the sensor type byte
580
+ const sync_map = get_config_map(rep_buffer[4]);
581
+
582
+ for (const [key, config] of Object.entries(sync_map)) {
583
+ // Destructure 'type' from inside 'validator' and rename 'read_index' to 'idx'
584
+ const { read_index: idx, length, validator: { type } = {}, converter, options } = config;
585
+
586
+ // If for some reason a config doesn't have a validator/type, skip it
587
+ if (!type) continue;
588
+
589
+ switch (type) {
590
+ case 'uint8':
591
+ response.machine_values[key] = rep_buffer[idx];
592
+ break;
593
+ case 'uint16be':
594
+ response.machine_values[key] = rep_buffer.readUInt16BE(idx);
595
+ break;
596
+ case 'uint32be':
597
+ response.machine_values[key] = rep_buffer.readUInt32BE(idx);
598
+ break;
599
+ case 'buffer':
600
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length);
601
+ break;
602
+ case 'hex':
603
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
604
+ break;
605
+ case 'mac':
606
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
607
+ break;
608
+ }
609
+ let human_value = response.machine_values[key];
610
+ if(options && options[response.machine_values[key]]){
611
+ human_value = options[response.machine_values[key]];
612
+ }else{
613
+ if(converter && converter.multiplier){
614
+ human_value = human_value * converter.multiplier;
615
+ }
616
+ if(converter && converter.units){
617
+ human_value = human_value + converter.units;
618
+ }
619
+ }
620
+ response.human_readable[key] = human_value;
621
+ }
622
+ if (Object.hasOwn(response.machine_values, 'destination_address') && response.machine_values.destination_address.toLowerCase() === '00000000') {
623
+ console.log('##############################');
624
+ console.log('#########Dest Override########');
625
+ console.log('##############################');
626
+ response.destination_address = "0000ffff";
627
+ };
628
+ return response;
629
+ };
630
+
631
+ const parse_fly = (frame) => {
632
+ return {
633
+ 'firmware': frame[2],
634
+ 'oxygen_bootup_time': frame[12] + 'sec',
635
+ 'flow_bootup_time': frame[13]+ 'sec',
636
+ 's1_oxygen_addr': frame[14],
637
+ 's2_oxygen_addr': frame[15],
638
+ 's3_oxygen_addr': frame[16],
639
+ 's4_oxygen_addr': frame[17],
640
+ 's1_flow_addr': frame[18],
641
+ 's2_flow_addr': frame[19],
642
+ 's3_flow_addr': frame[20],
643
+ 's4_flow_addr': frame[21],
644
+ 'hardware_id': frame.slice(22, 25),
645
+ 'report_rate': frame.slice(25, 29).reduce(msbLsb) + 'sec',
646
+ 'tx_life_counter': frame.slice(29, 33).reduce(msbLsb),
647
+ 'machine_values': {
648
+ 'firmware': frame[2],
649
+ 'oxygen_bootup_time': frame[12],
650
+ 'flow_bootup_time': frame[13],
651
+ 's1_oxygen_addr': frame[14],
652
+ 's2_oxygen_addr': frame[15],
653
+ 's3_oxygen_addr': frame[16],
654
+ 's4_oxygen_addr': frame[17],
655
+ 's1_flow_addr': frame[18],
656
+ 's2_flow_addr': frame[19],
657
+ 's3_flow_addr': frame[20],
658
+ 's4_flow_addr': frame[21],
659
+ 'hardware_id': frame.slice(22, 25),
660
+ 'report_rate': frame.slice(25, 29),
661
+ 'tx_life_counter': frame.slice(29, 33)
662
+ }
663
+ }
664
+ };
665
+
666
+ const parse = (payload, parsed) => {
667
+ return {
668
+ error_status: payload[0],
669
+ s1_oxygen_temp: payload.slice(1, 3).reduce(msbLsb)/100,
670
+ s2_oxygen_temp: payload.slice(3, 5).reduce(msbLsb)/100,
671
+ s3_oxygen_temp: payload.slice(5, 7).reduce(msbLsb)/100,
672
+ s4_oxygen_temp: payload.slice(7, 9).reduce(msbLsb)/100,
673
+ s1_saturation_percent: payload.slice(9, 13).reduce(msbLsb)/100,
674
+ s2_saturation_percent: payload.slice(13, 17).reduce(msbLsb)/100,
675
+ s3_saturation_percent: payload.slice(17, 21).reduce(msbLsb)/100,
676
+ s4_saturation_percent: payload.slice(21, 25).reduce(msbLsb)/100,
677
+ s1_oxigen_ppm: payload.slice(25, 29).reduce(msbLsb)/100,
678
+ s2_oxigen_ppm: payload.slice(29, 33).reduce(msbLsb)/100,
679
+ s3_oxigen_ppm: payload.slice(33, 37).reduce(msbLsb)/100,
680
+ s4_oxigen_ppm: payload.slice(37, 41).reduce(msbLsb)/100,
681
+ s1_oxigen_mg_l: payload.slice(41, 45).reduce(msbLsb)/100,
682
+ s2_oxigen_mg_l: payload.slice(45, 49).reduce(msbLsb)/100,
683
+ s3_oxigen_mg_l: payload.slice(49, 53).reduce(msbLsb)/100,
684
+ s4_oxigen_mg_l: payload.slice(53, 57).reduce(msbLsb)/100,
685
+ s1_flow_rate: payload.slice(57, 61).reduce(msbLsb)/100,
686
+ s2_flow_rate: payload.slice(61, 65).reduce(msbLsb)/100,
687
+ s3_flow_rate: payload.slice(65, 69).reduce(msbLsb)/100,
688
+ s4_flow_rate: payload.slice(69, 73).reduce(msbLsb)/100,
689
+ s1_solenoid_status: payload[73],
690
+ s2_solenoid_status: payload[74],
691
+ s3_solenoid_status: payload[75],
692
+ s4_solenoid_status: payload[76]
693
+ }
694
+ };
695
+
696
+ // --- 2. EXPORT THE MODULE ---
697
+ // Export the module with all the necessary functions and properties
698
+ // that need to be called from outside the scrip
699
+ return {
700
+ type: 536,
701
+ name: 'Wireless Oxygen Flow Meter',
702
+ parse,
703
+ get_write_buffer_size,
704
+ get_config_map,
705
+ sync_parse,
706
+ parse_fly
707
+ };
708
+ };