@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/lib/WirelessGateway.js +128 -1661
- package/lib/sensors/1.js +36 -21
- package/lib/sensors/103.js +38 -23
- package/lib/sensors/110.js +1320 -0
- package/lib/sensors/111.js +1623 -0
- package/lib/sensors/114.js +68 -22
- package/lib/sensors/125.js +40 -28
- package/lib/sensors/126.js +37 -22
- package/lib/sensors/128.js +281 -0
- package/lib/sensors/33.js +581 -0
- package/lib/sensors/554.js +247 -0
- package/lib/sensors/93.js +257 -0
- package/package.json +41 -41
- package/wireless.html +50 -1
- package/wireless.js +182 -86
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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:
|
|
253
|
-
this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'FLY', lastHeard: Date.now(), reported_config:
|
|
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
|
-
|
|
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:
|
|
268
|
-
this.gateway._emitter.emit('sensor_mode-'+addr, {mac: addr, type: sensor_type, nodeId: payload.node_id, mode: 'OTF', lastHeard: Date.now(), reported_config:
|
|
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:
|
|
278
|
-
this.gateway._emitter.emit('sensor_mode-'+
|
|
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
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
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
|
-
|
|
4433
|
-
|
|
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({
|
|
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({
|
|
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]);
|