@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,404 @@
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 23;
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
+ "thermocouple_type": {
151
+ "read_index": 25,
152
+ "write_index": 14,
153
+ "descriptions": {
154
+ "title": "Set Thermocouple Type",
155
+ "main_caption": "Set the type of thermocouple being used, this device supports eight thermocouple types (e.g., K, J, T, N, S, E, B, R)."
156
+ },
157
+ "default_value": 0,
158
+ "validator": {
159
+ "type": "uint8",
160
+ "min": 0,
161
+ "max": 112,
162
+ "generated": true
163
+ },
164
+ "options": {
165
+ "0": "Type K",
166
+ "16": "Type J",
167
+ "32": "Type T",
168
+ "48": "Type N",
169
+ "64": "Type S",
170
+ "80": "Type E",
171
+ "96": "Type B",
172
+ "112": "Type R"
173
+ },
174
+ "html_id": "thermocouple_type_23"
175
+ },
176
+ "filter_coefficient": {
177
+ "read_index": 26,
178
+ "write_index": 15,
179
+ "descriptions": {
180
+ "title": "Set Filter Level",
181
+ "main_caption": "The sensor applies the selected filter level by averaging multiple temperature readings over time."
182
+ },
183
+ "default_value": 0,
184
+ "validator": {
185
+ "type": "uint8",
186
+ "min": 0,
187
+ "max": 7,
188
+ "generated": true
189
+ },
190
+ "options": {
191
+ "0": "Level 0",
192
+ "1": "Level 1",
193
+ "2": "Level 2",
194
+ "3": "Level 3",
195
+ "4": "Level 4",
196
+ "5": "Level 5",
197
+ "6": "Level 6",
198
+ "7": "Level 7"
199
+ },
200
+ "html_id": "filter_thermocouple"
201
+ },
202
+ "cold_junction_resolution": {
203
+ "read_index": 27,
204
+ "write_index": 16,
205
+ "descriptions": {
206
+ "title": "Set Cold Junction Resolution",
207
+ "main_caption": "The internal chip integrates an ambient temperature sensor which can be used to measure the thermocouple cold-junction temperature."
208
+ },
209
+ "default_value": 0,
210
+ "validator": {
211
+ "type": "uint8",
212
+ "min": 0,
213
+ "max": 128,
214
+ "generated": true
215
+ },
216
+ "options": {
217
+ "0": "0.0625⁰C",
218
+ "128": "0.25⁰C"
219
+ },
220
+ "html_id": "cold_junction_thermocouple"
221
+ },
222
+ "adc_resolution": {
223
+ "read_index": 28,
224
+ "write_index": 17,
225
+ "descriptions": {
226
+ "title": "Set ADC Resolution",
227
+ "main_caption": "The ADC measurement resolution is selectable, which enables the user to choose faster conversion times with reduced resolution."
228
+ },
229
+ "default_value": 0,
230
+ "validator": {
231
+ "type": "uint8",
232
+ "min": 0,
233
+ "max": 96,
234
+ "generated": true
235
+ },
236
+ "options": {
237
+ "0": "18 Bits",
238
+ "32": "16 Bits",
239
+ "64": "14 Bits",
240
+ "96": "12 Bits"
241
+ },
242
+ "html_id": "sample_resolution_thermocouple"
243
+ },
244
+ "number_of_samples": {
245
+ "read_index": 29,
246
+ "write_index": 18,
247
+ "descriptions": {
248
+ "title": "Set Number of Samples",
249
+ "main_caption": "Specifies how many temperature samples are taken per measurement, in addition, if the filter option is enabled, then the filter engine is applied to each temperature sample."
250
+ },
251
+ "default_value": 0,
252
+ "validator": {
253
+ "type": "uint8",
254
+ "min": 0,
255
+ "max": 28,
256
+ "generated": true
257
+ },
258
+ "options": {
259
+ "0": "1 Sample",
260
+ "4": "2 Samples",
261
+ "8": "4 Samples",
262
+ "12": "8 Samples",
263
+ "16": "16 Samples",
264
+ "20": "32 Samples",
265
+ "24": "64 Samples",
266
+ "28": "128 Samples"
267
+ },
268
+ "html_id": "number_of_samples_thermocouple"
269
+ },
270
+ "operation_mode": {
271
+ "read_index": 30,
272
+ "write_index": 19,
273
+ "descriptions": {
274
+ "title": "Set Operation Mode",
275
+ "main_caption": ""
276
+ },
277
+ "default_value": 0,
278
+ "validator": {
279
+ "type": "uint8",
280
+ "min": 0,
281
+ "max": 2,
282
+ "generated": true
283
+ },
284
+ "options": {
285
+ "0": "Normal",
286
+ "1": "Shutdown",
287
+ "2": "Burst"
288
+ },
289
+ "html_id": "operation_mode_4"
290
+ },
291
+ "measurement_type": {
292
+ "read_index": 31,
293
+ "write_index": 20,
294
+ "descriptions": {
295
+ "title": "Set Measurement Type",
296
+ "main_caption": "Configures the sensor to measure either the hot-junction temperature, cold-junction temperature, or the differential between them."
297
+ },
298
+ "default_value": 0,
299
+ "validator": {
300
+ "type": "uint8",
301
+ "min": 0,
302
+ "max": 28,
303
+ "generated": true
304
+ },
305
+ "options": {
306
+ "0": "Cold Junction",
307
+ "1": "Hot Junction",
308
+ "2": "Delta"
309
+ },
310
+ "html_id": "measurement_type_thermocouple"
311
+ },
312
+ "boot_time": {
313
+ "read_index": 32,
314
+ "write_index": 21,
315
+ "descriptions": {
316
+ "title": "Set Boot Time",
317
+ "main_caption": "Sets the time (in milliseconds) taken for sensor to be ready for use after it's powered on."
318
+ },
319
+ "default_value": 1500,
320
+ "validator": {
321
+ "type": "uint16be"
322
+ },
323
+ "html_id": "boot_time_4"
324
+ }
325
+ };
326
+ };
327
+
328
+ const sync_parse = (rep_buffer) => {
329
+ let response = {
330
+ 'human_readable': {},
331
+ 'machine_values': {}
332
+ };
333
+
334
+ // Get the map based on the sensor type byte
335
+ const sync_map = get_config_map(rep_buffer[4]);
336
+
337
+ for (const [key, config] of Object.entries(sync_map)) {
338
+ // Destructure 'type' from inside 'validator' and rename 'read_index' to 'idx'
339
+ const { read_index: idx, length, validator: { type } = {}, converter, options } = config;
340
+
341
+ // If for some reason a config doesn't have a validator/type, skip it
342
+ if (!type) continue;
343
+
344
+ switch (type) {
345
+ case 'uint8':
346
+ response.machine_values[key] = rep_buffer[idx];
347
+ break;
348
+ case 'uint16be':
349
+ response.machine_values[key] = rep_buffer.readUInt16BE(idx);
350
+ break;
351
+ case 'uint32be':
352
+ response.machine_values[key] = rep_buffer.readUInt32BE(idx);
353
+ break;
354
+ case 'buffer':
355
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length);
356
+ break;
357
+ case 'hex':
358
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
359
+ break;
360
+ case 'mac':
361
+ response.machine_values[key] = rep_buffer.subarray(idx, idx + length).toString('hex');
362
+ break;
363
+ }
364
+ let human_value = response.machine_values[key];
365
+ if(options && options[response.machine_values[key]]){
366
+ human_value = options[response.machine_values[key]];
367
+ }else{
368
+ if(converter && converter.multiplier){
369
+ human_value = human_value * converter.multiplier;
370
+ }
371
+ if(converter && converter.units){
372
+ human_value = human_value + converter.units;
373
+ }
374
+ }
375
+ response.human_readable[key] = human_value;
376
+ }
377
+ if (Object.hasOwn(response.machine_values, 'destination_address') && response.machine_values.destination_address.toLowerCase() === '00000000') {
378
+ console.log('##############################');
379
+ console.log('#########Dest Override########');
380
+ console.log('##############################');
381
+ response.destination_address = "0000ffff";
382
+ };
383
+ return response;
384
+ };
385
+
386
+ const parse = (d) => {
387
+ return {
388
+ channel_1: signInt(d.slice(0, 4).reduce(msbLsb), 32) / 100,
389
+ channel_2: signInt(d.slice(4, 8).reduce(msbLsb), 32) / 100,
390
+ };
391
+ };
392
+
393
+ // --- 2. EXPORT THE MODULE ---
394
+ // Export the module with all the necessary functions and properties
395
+ // that need to be called from outside the scrip
396
+ return {
397
+ type: 23,
398
+ name: '2-Channel Thermocouple',
399
+ parse,
400
+ get_write_buffer_size,
401
+ get_config_map,
402
+ sync_parse
403
+ };
404
+ };