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

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/wireless.js CHANGED
@@ -7,6 +7,8 @@ const fs = require('fs');
7
7
  const path = require('path');
8
8
  const home_dir = require('os').homedir;
9
9
  const { isDeepStrictEqual } = require('util');
10
+ // We're using v8 to handle deep cloning of objects with buffer data.
11
+ const v8 = require('v8');
10
12
 
11
13
 
12
14
  module.exports = function(RED) {
@@ -142,14 +144,20 @@ module.exports = function(RED) {
142
144
  });
143
145
  // Event listener to make sure this only triggers once no matter how many gateway nodes there are
144
146
  node.gateway.on('sync', (d) => {
145
- // console.log('Sync Received in Config Node');
146
- // console.log(d);
147
- // const payload = structuredClone(d.payload);
148
- const payload = JSON.parse(JSON.stringify(d.payload));
149
- const addr = payload.address;
150
- const sensor_type = payload.sensor_type;
151
- const type = payload.type;
152
- if(payload.type == 'sync_check_in' || payload.type == 'sync_end' || payload.type == 'manual_sync_check_in'){
147
+ if(d.type == 'sync_check_in' || d.type == 'sync_end' || d.type == 'manual_sync_check_in' || d.type == 'sync_acknowledgment'){
148
+ // TODO replace with deepclone once we update node version on Gateway.
149
+ const cloned_payload = v8.deserialize(v8.serialize(d.payload));
150
+ // const payload = structuredClone(d.payload);
151
+ const {
152
+ machine_values: { sensor_type, ...actual_values},
153
+ human_readable,
154
+ address: addr,
155
+ type,
156
+ ...remaining
157
+ } = cloned_payload;
158
+
159
+ const payload = { ...remaining, ...actual_values, sensor_type };
160
+
153
161
  if(Object.hasOwn(node.sensor_list, addr) && Object.hasOwn(node.sensor_list[addr], 'update_request')){
154
162
  node.request_manifest(addr);
155
163
  }else if(Object.hasOwn(this.gateway.sensor_libs, sensor_type)){
@@ -158,6 +166,31 @@ module.exports = function(RED) {
158
166
  const config_map = this.gateway.sensor_libs[sensor_type].get_config_map(payload.firmware_version);
159
167
  let store_flag = false;
160
168
 
169
+ let fly_payload = null;
170
+
171
+ if(config.enable_fly_compatibility){
172
+ fly_payload = {
173
+ ...human_readable,
174
+ 'machine_values': {...actual_values}
175
+ };
176
+ for (const [new_key, conf] of Object.entries(config_map)) {
177
+ if (conf.old_fly_id) {
178
+ const old_key = conf.old_fly_id;
179
+ // Make sure a small slipup in the config map doesn't cause issues with the payload
180
+ if(old_key !== new_key){
181
+ if (Object.hasOwn(fly_payload, new_key)) {
182
+ fly_payload[old_key] = fly_payload[new_key];
183
+ delete fly_payload[new_key];
184
+ }
185
+ // Alias the machine value (inside machine_values)
186
+ if (Object.hasOwn(fly_payload.machine_values, new_key)) {
187
+ fly_payload.machine_values[old_key] = fly_payload.machine_values[new_key];
188
+ delete fly_payload.machine_values[new_key];
189
+ }
190
+ }
191
+ }
192
+ };
193
+ }
161
194
 
162
195
  if(!Object.hasOwn(node.sensor_configs, addr)){
163
196
  node.sensor_configs[addr] = {};
@@ -249,13 +282,14 @@ module.exports = function(RED) {
249
282
  if(type == 'sync_check_in'){
250
283
  // TODO add backwards compatibility
251
284
  if(config.enable_fly_compatibility){
252
- this.gateway._emitter.emit('sensor_mode', {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'FLY', lastHeard: Date.now(), reported_config: payload, sync: true});
253
- this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'FLY', lastHeard: Date.now(), reported_config: payload, sync: true});
285
+ this.gateway._emitter.emit('sensor_mode', {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'FLY', lastHeard: Date.now(), reported_config: fly_payload, sync: true});
286
+ this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'FLY', lastHeard: Date.now(), reported_config: fly_payload, sync: true});
254
287
  }
255
288
  if(Object.hasOwn(node.sensor_configs[addr], 'desired_configs') && Object.hasOwn(node.sensor_configs[addr], 'api_config_override') && !isDeepStrictEqual(node.sensor_configs[addr].reported_configs, node.sensor_configs[addr].desired_configs)){
256
289
  store_flag = true;
257
290
  var tout = setTimeout(() => {
258
- this.sync_init(addr, sensor_type);
291
+ node.configure(d.address, d.payload.sensor_type);
292
+ // this.sync_init(addr, sensor_type);
259
293
  }, 100);
260
294
  }
261
295
  }else if(type == 'manual_sync_check_in'){
@@ -264,22 +298,22 @@ module.exports = function(RED) {
264
298
  }
265
299
  }else if(type == 'sync_end'){
266
300
  if(config.enable_fly_compatibility){
267
- this.gateway._emitter.emit('sensor_mode', {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'OTF', lastHeard: Date.now(), reported_config: payload, sync: true});
268
- this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'OTF', lastHeard: Date.now(), reported_config: payload, sync: true});
301
+ this.gateway._emitter.emit('sensor_mode', {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'OTF', lastHeard: Date.now(), reported_config: fly_payload, sync: true});
302
+ this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'OTF', lastHeard: Date.now(), reported_config: fly_payload, sync: true});
269
303
  }
270
304
  }
271
305
  if(store_flag){
272
306
  node.store_sensor_configs(JSON.stringify(node.sensor_configs));
273
307
  }
274
308
  }
275
- }else if(type == 'sync_init'){
309
+ }else if(d.type == 'sync_init'){
276
310
  if(config.enable_fly_compatibility){
277
- this.gateway._emitter.emit('sensor_mode', {mac: addr, type: sensor_type, nodeId: d.payload.node_id, mode: 'OTN', lastHeard: Date.now(), reported_config: d.payload, sync: true});
278
- this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: d.payload.node_id, mode: 'OTN', lastHeard: Date.now(), reported_config: d.payload, sync: true});
279
- }
280
- if(node.sensor_configs[addr] && node.sensor_configs[addr].api_config_override){
281
- node.configure(addr, sensor_type);
311
+ this.gateway._emitter.emit('sensor_mode', {mac: d.address, type: d.payload.sensor_type, nodeId: d.payload.node_id, mode: 'OTN', lastHeard: Date.now(), sync: true});
312
+ this.gateway._emitter.emit('sensor_mode-'+d.address, {mac: d.address, type: d.payload.sensor_type, nodeId: d.payload.node_id, mode: 'OTN', lastHeard: Date.now(), sync: true});
282
313
  }
314
+ // if(node.sensor_configs[d.address] && node.sensor_configs[d.address].api_config_override){
315
+ // node.configure(d.address, d.payload.sensor_type);
316
+ // }
283
317
  }
284
318
  });
285
319
  node.gateway.on('manifest_received', (manifest_data) => {
@@ -1421,6 +1455,10 @@ module.exports = function(RED) {
1421
1455
  this.config_gateway = this.config_gateway_node.gateway;
1422
1456
  dedicated_config = true;
1423
1457
  }
1458
+ this.config_sync_listener;
1459
+
1460
+
1461
+
1424
1462
  // this.queue = new Queue(1);
1425
1463
  var node = this;
1426
1464
  var modes = {
@@ -3693,6 +3731,17 @@ module.exports = function(RED) {
3693
3731
  promises.threshold_probe_three_126 = node.config_gateway.config_set_probe_three_current_threshold_126(mac, parseInt(config.threshold_probe_three_126));
3694
3732
  }
3695
3733
  break;
3734
+ case 128:
3735
+ if(config.adc_threshold_128_active){
3736
+ promises.adc_threshold_128 = node.config_gateway.config_set_adc_threshold_128(mac, parseInt(config.adc_threshold_128));
3737
+ }
3738
+ if(config.auto_check_interval_128_active){
3739
+ promises.auto_check_interval_128 = node.config_gateway.config_set_auto_check_interval_128(mac, parseInt(config.auto_check_interval_128));
3740
+ }
3741
+ if(config.auto_calibration_128){
3742
+ promises.auto_calibration_128 = node.config_gateway.config_set_auto_calibration_128(mac);
3743
+ }
3744
+ break;
3696
3745
  case 180:
3697
3746
  if(config.output_data_rate_101_active){
3698
3747
  promises.output_data_rate_101 = node.config_gateway.config_set_output_data_rate_101(mac, parseInt(config.output_data_rate_101));
@@ -4393,69 +4442,15 @@ module.exports = function(RED) {
4393
4442
  });
4394
4443
  }
4395
4444
  node._sensor_config = _config;
4396
- if(config.addr){
4397
- config.addr = config.addr.toLowerCase();
4398
-
4399
- RED.nodes.getNode(config.connection).sensor_pool.push(config.addr);
4400
- this.gtw_on('sensor_data-'+config.addr, (data) => {
4401
- node.status(modes.RUN);
4402
- data.modem_mac = this.gateway.modem_mac;
4403
- node.send({
4404
- topic: 'sensor_data',
4405
- data: data,
4406
- payload: data.sensor_data,
4407
- time: Date.now()
4408
- });
4409
- });
4410
- this.gtw_on('converter_response-'+config.addr, (data) => {
4411
- node.status(modes.RUN);
4412
- data.modem_mac = this.gateway.modem_mac;
4413
- data.topic = 'converter_response';
4414
- data.time = Date.now();
4415
- node.send(data);
4416
- });
4417
- this.gtw_on('set_destination_address'+config.addr, (d) => {
4418
- if(config.auto_config){
4419
- node.warn('Setting destination address');
4420
- return new Promise((top_fulfill, top_reject) => {
4421
- var msg = {};
4422
- setTimeout(() => {
4423
- var tout = setTimeout(() => {
4424
- node.status(modes.PGM_ERR);
4425
- node.send({topic: 'FLY Set Destination Address', payload: msg, time: Date.now()});
4426
- }, 10000);
4427
-
4428
- var promises = {};
4429
-
4430
- promises.config_dest_address_fly = node.config_gateway.config_set_destination(d, parseInt(config.destination, 16));
4445
+ let sync_topic = '';
4446
+ if(Object.hasOwn(config, 'addr') && config.addr != ''){
4447
+ sync_topic = 'sync-'+config.addr;
4448
+ }else{
4449
+ sync_topic = 'sync';
4450
+ }
4431
4451
 
4432
- promises.finish = new Promise((fulfill, reject) => {
4433
- node.config_gateway.queue.add(() => {
4434
- return new Promise((f, r) => {
4435
- clearTimeout(tout);
4436
- fulfill();
4437
- f();
4438
- });
4439
- });
4440
- });
4441
- for(var i in promises){
4442
- (function(name){
4443
- promises[name].then((f) => {
4444
- if(name != 'finish') msg[name] = true;
4445
- else{
4446
- node.send({topic: 'FLY Set Destination Address', payload: msg, time: Date.now()});
4447
- top_fulfill(msg);
4448
- }
4449
- }).catch((err) => {
4450
- msg[name] = err;
4451
- });
4452
- })(i);
4453
- }
4454
- });
4455
- });
4456
- }
4457
- });
4458
- this.pgm_on('sync-'+config.addr, (data) => {
4452
+ this.pgm_on(sync_topic, (data) => {
4453
+ if(data.sensor_type == config.sensor_type){
4459
4454
  let message = {
4460
4455
  topic: 'sync',
4461
4456
  type: data.payload.type,
@@ -4483,6 +4478,8 @@ module.exports = function(RED) {
4483
4478
  if(Object.hasOwn(this.gateway_node.sensor_configs, data.payload.address) && !Object.hasOwn(this.gateway_node.sensor_configs[data.payload.address], 'api_config_override')){
4484
4479
  const html_map = this.config_gateway.get_intended_wireless_node_configs(data, config);
4485
4480
 
4481
+ console.log(html_map);
4482
+
4486
4483
  let update_flag = false;
4487
4484
  for(let key in html_map){
4488
4485
  if(html_map[key].html_value != node.gateway_node.sensor_configs[data.payload.address].reported_configs[key]){
@@ -4521,9 +4518,9 @@ module.exports = function(RED) {
4521
4518
  if(name != 'finish'){
4522
4519
  let fail_flag = false;
4523
4520
  for(const key in html_map){
4524
- if(Object.hasOwn(f.payload, key) && f.payload[key] == html_map[key].html_value){
4521
+ if(Object.hasOwn(f.payload.machine_values, key) && f.payload.machine_values[key] == html_map[key].html_value){
4525
4522
  msg.pass[key] = true;
4526
- msg.values[key] = f.payload[key];
4523
+ msg.values[key] = f.payload.human_readable[key];
4527
4524
  }else{
4528
4525
  msg.pass[key] = false;
4529
4526
  msg.values[key] = f.payload[key];
@@ -4537,7 +4534,18 @@ module.exports = function(RED) {
4537
4534
  }
4538
4535
  }
4539
4536
  else{
4540
- node.send({topic: 'sync', type: 'sync_response', payload: msg, time: Date.now()});
4537
+ node.send({
4538
+ topic: 'sync',
4539
+ type: 'sync_response',
4540
+ address: data.address,
4541
+ sensor_type: data.sensor_type,
4542
+ payload: {
4543
+ address: data.address,
4544
+ sensor_type: data.sensor_type,
4545
+ ...msg
4546
+ },
4547
+ time: Date.now()
4548
+ });
4541
4549
  // top_fulfill(msg);
4542
4550
  }
4543
4551
  }).catch((err) => {
@@ -4546,15 +4554,103 @@ module.exports = function(RED) {
4546
4554
  })(i);
4547
4555
  }
4548
4556
  });
4549
- }else{
4557
+ } else if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 103 || config.sensor_type == 202){
4558
+ // type 101, 102, 103, 202 sensors broadcast handling. Requires setting RTC every checkin although we can skip it if there are configs
4559
+ if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
4560
+ this.gateway.fly_101_in_progress = true;
4561
+ node.warn('Starting RTC Timer ' + Date.now());
4562
+ node.warn('Sensor checked in for RTC: ' + data.payload.address + ' at ' + Date.now());
4563
+ var broadcast_tout = setTimeout(() => {
4564
+ node.warn('Sending RTC Broadcast ' + Date.now());
4565
+ _broadcast_rtc(data);
4566
+ }, 2000);
4567
+ }else{
4568
+ node.warn('Sensor checked in for RTC: ' + data.payload.address + ' at ' + Date.now());
4569
+ }
4570
+ } else{
4550
4571
  // console.log('No Config Differences Detected, Skipping Sync Configs');
4551
- node.send({topic: 'sync', type: 'sync_response', payload: {info: "Reported configurations match desired configurations. Skipping Sync."}, time: Date.now()});
4572
+ node.send({
4573
+ topic: 'sync',
4574
+ type: 'sync_response',
4575
+ address: data.address,
4576
+ sensor_type: data.sensor_type,
4577
+ payload: {
4578
+ address: data.address,
4579
+ sensor_type: data.sensor_type,
4580
+ info: "Reported configurations match desired configurations. Skipping Sync."
4581
+ },
4582
+ time: Date.now()
4583
+ });
4552
4584
  }
4553
4585
  }
4554
4586
  }
4555
4587
  }
4556
4588
  node.send(message);
4589
+ }
4590
+ });
4591
+ if(config.addr){
4592
+ config.addr = config.addr.toLowerCase();
4593
+
4594
+ RED.nodes.getNode(config.connection).sensor_pool.push(config.addr);
4595
+ this.gtw_on('sensor_data-'+config.addr, (data) => {
4596
+ node.status(modes.RUN);
4597
+ data.modem_mac = this.gateway.modem_mac;
4598
+ node.send({
4599
+ topic: 'sensor_data',
4600
+ data: data,
4601
+ payload: data.sensor_data,
4602
+ time: Date.now()
4603
+ });
4557
4604
  });
4605
+ this.gtw_on('converter_response-'+config.addr, (data) => {
4606
+ node.status(modes.RUN);
4607
+ data.modem_mac = this.gateway.modem_mac;
4608
+ data.topic = 'converter_response';
4609
+ data.time = Date.now();
4610
+ node.send(data);
4611
+ });
4612
+ this.gtw_on('set_destination_address'+config.addr, (d) => {
4613
+ if(config.auto_config){
4614
+ node.warn('Setting destination address');
4615
+ return new Promise((top_fulfill, top_reject) => {
4616
+ var msg = {};
4617
+ setTimeout(() => {
4618
+ var tout = setTimeout(() => {
4619
+ node.status(modes.PGM_ERR);
4620
+ node.send({topic: 'FLY Set Destination Address', payload: msg, time: Date.now()});
4621
+ }, 10000);
4622
+
4623
+ var promises = {};
4624
+
4625
+ promises.config_dest_address_fly = node.config_gateway.config_set_destination(d, parseInt(config.destination, 16));
4626
+
4627
+ promises.finish = new Promise((fulfill, reject) => {
4628
+ node.config_gateway.queue.add(() => {
4629
+ return new Promise((f, r) => {
4630
+ clearTimeout(tout);
4631
+ fulfill();
4632
+ f();
4633
+ });
4634
+ });
4635
+ });
4636
+ for(var i in promises){
4637
+ (function(name){
4638
+ promises[name].then((f) => {
4639
+ if(name != 'finish') msg[name] = true;
4640
+ else{
4641
+ node.send({topic: 'FLY Set Destination Address', payload: msg, time: Date.now()});
4642
+ top_fulfill(msg);
4643
+ }
4644
+ }).catch((err) => {
4645
+ msg[name] = err;
4646
+ });
4647
+ })(i);
4648
+ }
4649
+ });
4650
+ });
4651
+ }
4652
+ });
4653
+
4558
4654
  this.pgm_on('sensor_mode-'+config.addr, (sensor) => {
4559
4655
  if(sensor.mode in modes){
4560
4656
  node.status(modes[sensor.mode]);