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

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,419 @@
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 20;
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
+ "sensor_interface_ch1": {
151
+ "read_index": 25,
152
+ "write_index": 14,
153
+ "descriptions": {
154
+ "title": "Set RTD Wire Type",
155
+ "main_caption": "The wire type of RTD Sensor Probe to be connected."
156
+ },
157
+ "default_value": 0,
158
+ "validator": {
159
+ "type": "uint8",
160
+ "min": 0,
161
+ "max": 2,
162
+ "generated": true
163
+ },
164
+ "options": {
165
+ "0": "2 Wires",
166
+ "1": "3 Wires",
167
+ "2": "4 Wires"
168
+ },
169
+ "html_id": "rtd_type_39"
170
+ },
171
+ "sensor_range_ch1": {
172
+ "read_index": 26,
173
+ "write_index": 15,
174
+ "descriptions": {
175
+ "title": "Set RTD Range",
176
+ "main_caption": "Type of PT Sensor Probe to be connected."
177
+ },
178
+ "default_value": 0,
179
+ "validator": {
180
+ "type": "uint8",
181
+ "min": 0,
182
+ "max": 1,
183
+ "generated": true
184
+ },
185
+ "options": {
186
+ "0": "PT 100",
187
+ "1": "PT 1000"
188
+ },
189
+ "html_id": "rtd_range_39"
190
+ },
191
+ "sensor_interface_ch2": {
192
+ "read_index": 25,
193
+ "write_index": 16,
194
+ "descriptions": {
195
+ "title": "Set RTD Wire Type - Channel 2",
196
+ "main_caption": "The wire type of RTD Sensor Probe to be connected in Channel 2."
197
+ },
198
+ "default_value": 0,
199
+ "validator": {
200
+ "type": "uint8",
201
+ "min": 0,
202
+ "max": 2,
203
+ "generated": true
204
+ },
205
+ "options": {
206
+ "0": "2 Wires",
207
+ "1": "3 Wires",
208
+ "2": "4 Wires"
209
+ },
210
+ "html_id": "rtd_wire_type_ch2_54"
211
+ },
212
+ "sensor_range_ch2": {
213
+ "read_index": 26,
214
+ "write_index": 17,
215
+ "descriptions": {
216
+ "title": "Set RTD Range - Channel 2",
217
+ "main_caption": "Type of PT Sensor Probe to be connected in Channel 2."
218
+ },
219
+ "default_value": 0,
220
+ "validator": {
221
+ "type": "uint8",
222
+ "min": 0,
223
+ "max": 1,
224
+ "generated": true
225
+ },
226
+ "options": {
227
+ "0": "PT 100",
228
+ "1": "PT 1000"
229
+ },
230
+ "html_id": "rtd_range_ch2_54"
231
+ },
232
+ "sensor_interface_ch3": {
233
+ "read_index": 27,
234
+ "write_index": 18,
235
+ "descriptions": {
236
+ "title": "Set RTD Wire Type - Channel 3",
237
+ "main_caption": "The wire type of RTD Sensor Probe to be connected in Channel 3."
238
+ },
239
+ "default_value": 0,
240
+ "validator": {
241
+ "type": "uint8",
242
+ "min": 0,
243
+ "max": 2,
244
+ "generated": true
245
+ },
246
+ "options": {
247
+ "0": "2 Wires",
248
+ "1": "3 Wires",
249
+ "2": "4 Wires"
250
+ },
251
+ "html_id": "rtd_wire_type_ch3_55"
252
+ },
253
+ "sensor_range_ch3": {
254
+ "read_index": 28,
255
+ "write_index": 19,
256
+ "descriptions": {
257
+ "title": "Set RTD Range - Channel 3",
258
+ "main_caption": "Type of PT Sensor Probe to be connected in Channel 3."
259
+ },
260
+ "default_value": 0,
261
+ "validator": {
262
+ "type": "uint8",
263
+ "min": 0,
264
+ "max": 1,
265
+ "generated": true
266
+ },
267
+ "options": {
268
+ "0": "PT 100",
269
+ "1": "PT 1000"
270
+ },
271
+ "html_id": "rtd_range_ch3_55"
272
+ }
273
+ };
274
+ };
275
+
276
+ const sync_parse = (rep_buffer) => {
277
+ let response = {
278
+ 'human_readable': {},
279
+ 'machine_values': {}
280
+ };
281
+
282
+ // Get the map based on the sensor type byte
283
+ const sync_map = get_config_map(rep_buffer[4]);
284
+
285
+ for (const [key, config] of Object.entries(sync_map)) {
286
+ // Destructure 'type' from inside 'validator' and rename 'read_index' to 'idx'
287
+ const { read_index: idx, length, validator: { type } = {}, converter, options } = config;
288
+
289
+ // If for some reason a config doesn't have a validator/type, skip it
290
+ if (!type) continue;
291
+
292
+ switch (type) {
293
+ case 'uint8':
294
+ response.machine_values[key] = rep_buffer[idx];
295
+ break;
296
+ case 'uint16be':
297
+ response.machine_values[key] = rep_buffer.readUInt16BE(idx);
298
+ break;
299
+ case 'uint32be':
300
+ response.machine_values[key] = rep_buffer.readUInt32BE(idx);
301
+ break;
302
+ case 'buffer':
303
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length);
304
+ break;
305
+ case 'hex':
306
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
307
+ break;
308
+ case 'mac':
309
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
310
+ break;
311
+ }
312
+ let human_value = response.machine_values[key];
313
+ if(options && options[response.machine_values[key]]){
314
+ human_value = options[response.machine_values[key]];
315
+ }else{
316
+ if(converter && converter.multiplier){
317
+ human_value = human_value * converter.multiplier;
318
+ }
319
+ if(converter && converter.units){
320
+ human_value = human_value + converter.units;
321
+ }
322
+ }
323
+ response.human_readable[key] = human_value;
324
+ }
325
+ if (Object.hasOwn(response.machine_values, 'destination_address') && response.machine_values.destination_address.toLowerCase() === '00000000') {
326
+ console.log('##############################');
327
+ console.log('#########Dest Override########');
328
+ console.log('##############################');
329
+ response.destination_address = "0000ffff";
330
+ };
331
+ return response;
332
+ };
333
+
334
+ const parse_fly = (frame) => {
335
+ const interface_types = ["rtd_2_wire", "rtd_3_wire", "rtd_4_wire"];
336
+ const rtd_types = ["rtd_pt_100", "rtd_pt_1000"];
337
+ return {
338
+ 'firmware': frame[2],
339
+ 'sensor_interface_ch1': interface_types[frame[12]],
340
+ 'sensor_type_ch1': rtd_types[frame[13]],
341
+ 'sensor_interface_ch2': interface_types[frame[14]],
342
+ 'sensor_type_ch2': rtd_types[frame[15]],
343
+ 'sensor_interface_ch3': interface_types[frame[16]],
344
+ 'sensor_type_ch3': rtd_types[frame[17]],
345
+ 'hardware_id': frame.slice(18, 21),
346
+ 'report_rate': frame.slice(21, 25).reduce(msbLsb) + " sec",
347
+ 'tx_life_counter': frame.slice(25, 29).reduce(msbLsb),
348
+ 'machine_values': {
349
+ 'firmware': frame[2],
350
+ 'sensor_interface_ch1': frame[12],
351
+ 'sensor_type_ch1': frame[13],
352
+ 'sensor_interface_ch2': frame[14],
353
+ 'sensor_type_ch2': frame[15],
354
+ 'sensor_interface_ch3': frame[16],
355
+ 'sensor_type_ch3': frame[17],
356
+ 'hardware_id': frame.slice(18, 21),
357
+ 'report_rate': frame.slice(21, 25),
358
+ 'tx_life_counter': frame.slice(25, 29)
359
+ }
360
+ }
361
+ };
362
+
363
+ const parse = (payload, parsed, mac) => {
364
+ let reserved = payload[7] >> 1; // Fault status (1-bit left shifted)
365
+ let fault_status = '';
366
+ if (reserved === 0) {
367
+ fault_status = 'data_valid';
368
+ } else if (reserved === 15) {
369
+ fault_status = 'data_invalid';
370
+ } else {
371
+ const fault_bits = (reserved >> 2) & 0b00001111;
372
+ switch (fault_bits) {
373
+ case 8:
374
+ fault_status = 'ref_in_vbias';
375
+ break;
376
+ case 4:
377
+ fault_status = 'ref_in_force_close';
378
+ break;
379
+ case 2:
380
+ fault_status = 'rtd_in_force_open';
381
+ break;
382
+ case 1:
383
+ fault_status = 'over_under_voltage';
384
+ break;
385
+ }
386
+ const channel_bits = reserved & 0b00000011;
387
+ switch (channel_bits) {
388
+ case 1:
389
+ fault_status = fault_status + '_ch1';
390
+ break;
391
+ case 2:
392
+ fault_status = fault_status + '_ch2';
393
+ break;
394
+ case 3:
395
+ fault_status = fault_status + '_ch3';
396
+ break;
397
+ }
398
+ }
399
+ return {
400
+ fault_status: fault_status,
401
+ temperature_1: signInt(payload.slice(8, 12).reduce(msbLsb), 32) / 100,
402
+ temperature_2: signInt(payload.slice(12, 16).reduce(msbLsb), 32) / 100,
403
+ temperature_3: signInt(payload.slice(16, 20).reduce(msbLsb), 32) / 100
404
+ };
405
+ };
406
+
407
+ // --- 2. EXPORT THE MODULE ---
408
+ // Export the module with all the necessary functions and properties
409
+ // that need to be called from outside the scrip
410
+ return {
411
+ type: 55,
412
+ name: '3-Channel RTD Temperature Sensor',
413
+ parse,
414
+ get_write_buffer_size,
415
+ get_config_map,
416
+ sync_parse,
417
+ parse_fly
418
+ };
419
+ };
@@ -210,7 +210,7 @@ module.exports = (globalDevices) => {
210
210
  console.log('#########Dest Override########');
211
211
  console.log('##############################');
212
212
  response.destination_address = "0000ffff";
213
- response.auto_raw_destination_address = "0000ffff";
213
+ //response.auto_raw_destination_address = "0000ffff";
214
214
  };
215
215
  return response;
216
216
  };