@ncd-io/node-red-enterprise-sensors 1.6.3 → 2.0.0
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 +2342 -3011
- package/lib/sensors/1.js +215 -0
- package/lib/sensors/103.js +1024 -0
- package/lib/sensors/114.js +1342 -0
- package/lib/sensors/125.js +619 -0
- package/lib/sensors/126.js +680 -0
- package/lib/utils.js +27 -0
- package/package.json +4 -1
- package/wireless.html +431 -82
- package/wireless.js +820 -219
package/wireless.js
CHANGED
|
@@ -28,8 +28,6 @@ module.exports = function(RED) {
|
|
|
28
28
|
const configuration_map_location = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/data/configuration_map.json';
|
|
29
29
|
const sensor_type_map_location = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/data/sensor_type_map.json';
|
|
30
30
|
|
|
31
|
-
this.config_node_capable = [114];
|
|
32
|
-
|
|
33
31
|
// comms_timer object var added to clear the time to prevent issues with rapid redeploy
|
|
34
32
|
this.comms_timer;
|
|
35
33
|
|
|
@@ -134,114 +132,154 @@ module.exports = function(RED) {
|
|
|
134
132
|
node.gateway.digi.serial.reconnect();
|
|
135
133
|
});
|
|
136
134
|
}
|
|
137
|
-
//
|
|
135
|
+
// Listen for FLY messages to run FOTA updates on older FLY messages
|
|
138
136
|
node.gateway.on('sensor_mode', (d) => {
|
|
139
|
-
if(d.mode == "FLY"
|
|
137
|
+
if(d.mode == "FLY" && !Object.hasOwn(d, 'sync')){
|
|
140
138
|
if(Object.hasOwn(node.sensor_list, d.mac) && Object.hasOwn(node.sensor_list[d.mac], 'update_request') && d.mode == "FLY"){
|
|
141
139
|
node.request_manifest(d.mac);
|
|
142
|
-
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
// Event listener to make sure this only triggers once no matter how many gateway nodes there are
|
|
144
|
+
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'){
|
|
153
|
+
if(Object.hasOwn(node.sensor_list, addr) && Object.hasOwn(node.sensor_list[addr], 'update_request')){
|
|
154
|
+
node.request_manifest(addr);
|
|
155
|
+
}else if(Object.hasOwn(this.gateway.sensor_libs, sensor_type)){
|
|
143
156
|
// API CONFIGURATION NODE
|
|
144
|
-
let values = d.reported_config.machine_values;
|
|
145
|
-
|
|
146
|
-
if(Object.hasOwn(values, 'tx_lifetime_counter')) delete values.tx_lifetime_counter;
|
|
147
|
-
if(Object.hasOwn(values, 'reserved')) delete values.reserved;
|
|
148
|
-
|
|
157
|
+
// let values = d.reported_config.machine_values;
|
|
158
|
+
const config_map = this.gateway.sensor_libs[sensor_type].get_config_map(payload.firmware_version);
|
|
149
159
|
let store_flag = false;
|
|
150
160
|
|
|
151
|
-
|
|
152
|
-
|
|
161
|
+
|
|
162
|
+
if(!Object.hasOwn(node.sensor_configs, addr)){
|
|
163
|
+
node.sensor_configs[addr] = {};
|
|
153
164
|
store_flag = true;
|
|
154
165
|
}
|
|
166
|
+
|
|
167
|
+
// delete so we don't have to consider it for storage
|
|
168
|
+
// TODO re-add, but remove from storage consideration for mapping
|
|
169
|
+
// if(Object.hasOwn(d.payload, 'tx_lifetime_counter')){
|
|
170
|
+
// delete d.payload.tx_lifetime_counter;
|
|
171
|
+
// }
|
|
172
|
+
|
|
155
173
|
// Store hardware_id outside of reported_configs
|
|
156
|
-
if(!Object.hasOwn(node.sensor_configs[
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
// if(!Object.hasOwn(node.sensor_configs[addr], 'hardware_id') && Object.hasOwn(d.payload, 'hardware_id')){
|
|
175
|
+
// node.sensor_configs[addr].hardware_id = d.payload.hardware_id;
|
|
176
|
+
// delete d.payload.hardware_id;
|
|
177
|
+
// store_flag = true;
|
|
178
|
+
// }
|
|
179
|
+
|
|
180
|
+
// Store core_version outside of reported_configs
|
|
181
|
+
// if(Object.hasOwn(d.payload, 'core_version')){
|
|
182
|
+
// node.sensor_configs[addr].core_version = d.payload.core_version;
|
|
183
|
+
// store_flag = true;
|
|
184
|
+
// }
|
|
185
|
+
|
|
161
186
|
// Loop through and translate and validate values.
|
|
162
187
|
// We want to allow passing in integers instead of byte arrays etc.
|
|
163
188
|
// This the FLY so we don't need to validate.
|
|
164
|
-
values.network_id = config.pan_id;
|
|
165
|
-
if(Object.hasOwn(d, '
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
for(let key in
|
|
169
|
-
if(Object.hasOwn(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if(Object.hasOwn(node.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// values[key] = values[key].reduce(msbLsb);
|
|
178
|
-
// break;
|
|
179
|
-
case 'uint16':
|
|
180
|
-
values[key] = values[key].reduce(msbLsb);
|
|
181
|
-
break;
|
|
182
|
-
case 'uint24':
|
|
183
|
-
values[key] = values[key].reduce(msbLsb);
|
|
184
|
-
break;
|
|
185
|
-
case 'uint32':
|
|
186
|
-
values[key] = values[key].reduce(msbLsb);
|
|
187
|
-
break;
|
|
188
|
-
case 'hexString':
|
|
189
|
-
values[key] = values[key].toLowerCase();
|
|
190
|
-
break;
|
|
189
|
+
// values.network_id = config.pan_id;
|
|
190
|
+
// if(Object.hasOwn(d, 'node_id')){
|
|
191
|
+
// values.node_id = d.nodeId;
|
|
192
|
+
// }
|
|
193
|
+
for(let key in payload){
|
|
194
|
+
if(Object.hasOwn(config_map, key)){
|
|
195
|
+
if(!Object.hasOwn(config_map[key], 'write_index')){
|
|
196
|
+
// TODO
|
|
197
|
+
if(!Object.hasOwn(node.sensor_configs[addr], key) || Object.hasOwn(node.sensor_configs[addr], key) && node.sensor_configs[addr][key] != payload[key]){
|
|
198
|
+
// console.log('Config '+key+' is read only, moving from payload');
|
|
199
|
+
node.sensor_configs[addr][key] = payload[key];
|
|
200
|
+
if(key !== 'tx_lifetime_counter'){
|
|
201
|
+
store_flag = true;
|
|
191
202
|
}
|
|
192
203
|
}
|
|
204
|
+
delete payload[key];
|
|
193
205
|
}
|
|
206
|
+
}else{
|
|
207
|
+
// console.log('Not in config map, deleting key: '+key);
|
|
208
|
+
delete payload[key];
|
|
194
209
|
}
|
|
195
210
|
}
|
|
196
211
|
// If object has no reported configs, instantiate them
|
|
197
|
-
if(!Object.hasOwn(node.sensor_configs[
|
|
198
|
-
node.sensor_configs[d.mac].reported_configs = {};
|
|
212
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'reported_configs')){
|
|
213
|
+
// node.sensor_configs[d.mac].reported_configs = {};
|
|
214
|
+
node.sensor_configs[addr].reported_configs = payload;
|
|
199
215
|
store_flag = true;
|
|
200
216
|
}
|
|
201
217
|
// If object has no desired configs, add them
|
|
202
|
-
if(!Object.hasOwn(node.sensor_configs[
|
|
203
|
-
node.sensor_configs[
|
|
204
|
-
store_flag = true;
|
|
205
|
-
}
|
|
206
|
-
if(!Object.hasOwn(node.sensor_configs[d.mac], 'type')){
|
|
207
|
-
node.sensor_configs[d.mac].type = d.type;
|
|
208
|
-
store_flag = true;
|
|
209
|
-
}else if(node.sensor_configs[d.mac].type != d.type){
|
|
210
|
-
// This code is only called when the type doesn't match what the sensor reports, only foreseeable if user swaps sensor modules OR preloads configs for wrong sensor type
|
|
211
|
-
delete node.sensor_configs[d.mac].desired_configs;
|
|
212
|
-
node.sensor_configs[d.mac].type = d.type;
|
|
213
|
-
node._emitter.emit('config_node_error', {topic: 'sensor_type_error', payload: {'error': "Sensor type used for desired configs does not match sensor type reported by sensor. Deleting desired configs"}, addr: d.mac, time: Date.now()});
|
|
218
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'desired_configs')){
|
|
219
|
+
node.sensor_configs[addr].desired_configs = payload;
|
|
214
220
|
store_flag = true;
|
|
215
221
|
}
|
|
216
|
-
|
|
222
|
+
|
|
223
|
+
// We're setting sensor_type above, so we can remove this.
|
|
224
|
+
// if(!Object.hasOwn(node.sensor_configs[addr], 'type')){
|
|
225
|
+
// node.sensor_configs[addr].type = d.type;
|
|
226
|
+
// store_flag = true;
|
|
227
|
+
// }else if(node.sensor_configs[d.mac].type != d.type){
|
|
228
|
+
// // This code is only called when the type doesn't match what the sensor reports, only foreseeable if user swaps sensor modules OR preloads configs for wrong sensor type
|
|
229
|
+
// delete node.sensor_configs[d.mac].desired_configs;
|
|
230
|
+
// node.sensor_configs[d.mac].type = d.type;
|
|
231
|
+
// node._emitter.emit('config_node_error', {topic: 'sensor_type_error', payload: {'error': "Sensor type used for desired configs does not match sensor type reported by sensor. Deleting desired configs"}, addr: d.mac, time: Date.now()});
|
|
232
|
+
// store_flag = true;
|
|
233
|
+
// }
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
if(!isDeepStrictEqual(node.sensor_configs[addr].reported_configs, payload)){
|
|
217
237
|
// Values are different, update the stored configs and write to file
|
|
218
|
-
node.sensor_configs[
|
|
238
|
+
node.sensor_configs[addr].reported_configs = payload;
|
|
219
239
|
// If reported configs change, but the auto config does not control configs, update automatically
|
|
220
240
|
// Will duplicate setting desired configs on first run, but only once or if user clear desired_configs
|
|
221
|
-
if(!Object.hasOwn(node.sensor_configs[
|
|
222
|
-
node.sensor_configs[
|
|
241
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'api_config_override')){
|
|
242
|
+
node.sensor_configs[addr].desired_configs = payload;
|
|
223
243
|
}
|
|
224
244
|
store_flag = true;
|
|
225
|
-
node._emitter.emit('config_node_msg', {topic: 'sensor_configs_update', payload: node.sensor_configs[
|
|
245
|
+
node._emitter.emit('config_node_msg', {topic: 'sensor_configs_update', payload: node.sensor_configs[addr], address: addr, time: Date.now()});
|
|
226
246
|
// node.send({topic: 'sensor_configs_update', payload: node.sensor_configs[d.mac], time: Date.now()});
|
|
227
247
|
}
|
|
228
248
|
|
|
229
|
-
if(
|
|
230
|
-
|
|
231
|
-
if(
|
|
232
|
-
|
|
249
|
+
if(type == 'sync_check_in'){
|
|
250
|
+
// TODO add backwards compatibility
|
|
251
|
+
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});
|
|
254
|
+
}
|
|
255
|
+
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)){
|
|
233
256
|
store_flag = true;
|
|
234
257
|
var tout = setTimeout(() => {
|
|
235
|
-
this.
|
|
258
|
+
this.sync_init(addr, sensor_type);
|
|
236
259
|
}, 100);
|
|
237
260
|
}
|
|
261
|
+
}else if(type == 'manual_sync_check_in'){
|
|
262
|
+
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)){
|
|
263
|
+
node.configure(addr, sensor_type);
|
|
264
|
+
}
|
|
265
|
+
}else if(type == 'sync_end'){
|
|
266
|
+
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});
|
|
269
|
+
}
|
|
238
270
|
}
|
|
239
271
|
if(store_flag){
|
|
240
272
|
node.store_sensor_configs(JSON.stringify(node.sensor_configs));
|
|
241
273
|
}
|
|
242
274
|
}
|
|
243
|
-
}else if(
|
|
244
|
-
|
|
275
|
+
}else if(type == 'sync_init'){
|
|
276
|
+
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);
|
|
282
|
+
}
|
|
245
283
|
}
|
|
246
284
|
});
|
|
247
285
|
node.gateway.on('manifest_received', (manifest_data) => {
|
|
@@ -327,6 +365,58 @@ module.exports = function(RED) {
|
|
|
327
365
|
}
|
|
328
366
|
};
|
|
329
367
|
|
|
368
|
+
this.sync_init = function(addr, type){
|
|
369
|
+
// console.log('!!!! Sync Init for sensor '+addr);
|
|
370
|
+
return new Promise((top_fulfill, top_reject) => {
|
|
371
|
+
var msg = {};
|
|
372
|
+
setTimeout(() => {
|
|
373
|
+
var tout = setTimeout(() => {
|
|
374
|
+
// switch to emitter for this
|
|
375
|
+
// node.status(modes.PGM_ERR);
|
|
376
|
+
// node.send({topic: 'OTN Request Results', payload: msg, time: Date.now()});
|
|
377
|
+
console.log('Sync Request Timed Out');
|
|
378
|
+
}, 10000);
|
|
379
|
+
|
|
380
|
+
var promises = {};
|
|
381
|
+
// This command is used for OTF on types 53, 80,81,82,83,84, 101, 102, 110, 111, 518, 519
|
|
382
|
+
let original_otf_devices = [53, 80, 81, 82, 83, 84, 87, 101, 102, 103, 110, 111, 112, 114, 117, 180, 181, 518, 519, 520, 538, 543];
|
|
383
|
+
if(original_otf_devices.includes(type)){
|
|
384
|
+
console.log('!!!! Entering Sync mode with original command');
|
|
385
|
+
// This command is used for OTF on types 53, 80, 81, 82, 83, 84, 101, 102, 110, 111, 518, 519
|
|
386
|
+
promises.config_enter_otn_mode = node.gateway.config_enter_otn_mode(addr);
|
|
387
|
+
}else{
|
|
388
|
+
console.log('!!!! Entering Sync mode with other command');
|
|
389
|
+
// This command is used for OTF on types not 53, 80, 81, 82, 83, 84, 101, 102, 110, 111, 518, 519
|
|
390
|
+
promises.config_enter_otn_mode = node.gateway.config_enter_otn_mode_common(addr);
|
|
391
|
+
}
|
|
392
|
+
promises.finish = new Promise((fulfill, reject) => {
|
|
393
|
+
node.gateway.queue.add(() => {
|
|
394
|
+
return new Promise((f, r) => {
|
|
395
|
+
clearTimeout(tout);
|
|
396
|
+
// node.status(modes.FLY);
|
|
397
|
+
fulfill();
|
|
398
|
+
f();
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
for(var i in promises){
|
|
403
|
+
(function(name){
|
|
404
|
+
promises[name].then((f) => {
|
|
405
|
+
if(name != 'finish') msg[name] = true;
|
|
406
|
+
else{
|
|
407
|
+
// #OTF
|
|
408
|
+
node.send({topic: 'OTN Request Results', payload: msg, time: Date.now()});
|
|
409
|
+
top_fulfill(msg);
|
|
410
|
+
}
|
|
411
|
+
}).catch((err) => {
|
|
412
|
+
msg[name] = err;
|
|
413
|
+
});
|
|
414
|
+
})(i);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
};
|
|
419
|
+
|
|
330
420
|
this.get_required_configs = function(desired_configs, reported_configs){
|
|
331
421
|
const mismatched = {};
|
|
332
422
|
for (const key in desired_configs) {
|
|
@@ -340,8 +430,15 @@ module.exports = function(RED) {
|
|
|
340
430
|
return mismatched;
|
|
341
431
|
};
|
|
342
432
|
|
|
343
|
-
|
|
344
|
-
|
|
433
|
+
this.sync_check_reboot = function(addr){
|
|
434
|
+
if(node.sensor_configs[addr].reported_configs.network_id != node.sensor_configs[addr].desired_configs.network_id){
|
|
435
|
+
return true;
|
|
436
|
+
}else{
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
this.configure = function(addr, type){
|
|
345
442
|
return new Promise((top_fulfill, top_reject) => {
|
|
346
443
|
var success = {};
|
|
347
444
|
setTimeout(() => {
|
|
@@ -352,50 +449,23 @@ module.exports = function(RED) {
|
|
|
352
449
|
// node.send({topic: 'Config Results', payload: success, time: Date.now(), addr: sensor.mac});
|
|
353
450
|
}, 60000);
|
|
354
451
|
// node.status(modes.PGM_NOW);
|
|
355
|
-
var mac =
|
|
452
|
+
var mac = addr;
|
|
356
453
|
var promises = {};
|
|
357
|
-
var reboot =
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
for (const key in configs) {
|
|
361
|
-
let config_obj = node.configuration_map[node.sensor_type_map[sensor.type].configs[key]];
|
|
362
|
-
if(Object.hasOwn(config_obj, 'validator') && Object.hasOwn(config_obj.validator, 'type')){
|
|
363
|
-
if(key == 'node_id' || key == 'delay'){
|
|
364
|
-
// TODO expand this logic in the future for cases where sensor doesn't report delay.
|
|
365
|
-
if(Object.hasOwn(configs, 'node_id') && Object.hasOwn(configs, 'delay') && Object.hasOwn(config_obj, "delay") && Object.hasOwn(config_obj, "node_id")){
|
|
366
|
-
// If the sensor has and should have node id and delay (standard sensor)
|
|
367
|
-
promises['node_id_and_delay'] = node.gateway.config_node_id_and_delay(sensor.mac, parseInt(configs['node_id']), parseInt(configs['delay']));
|
|
368
|
-
}else if(Object.hasOwn(configs, 'node_id') && Object.hasOwn(config_obj, "node_id") && !Object.hasOwn(config_obj, "delay")){
|
|
369
|
-
// If the sensor has and should have node id but should not have delay (special sensor)
|
|
370
|
-
// We will ignore delay setting in this case and set it to 0
|
|
371
|
-
promises['node_id_and_delay'] = node.gateway.config_node_id_and_delay(sensor.mac, parseInt(configs['node_id']), 0);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
switch(config_obj.validator.type){
|
|
375
|
-
case 'hexString':
|
|
376
|
-
console.log('Configuring hexString '+key+' to '+configs[key] + ' eval as '+parseInt(configs[key], 16));
|
|
377
|
-
promises[key] = node.gateway[config_obj.call](sensor.mac, parseInt(configs[key], 16));
|
|
378
|
-
break;
|
|
379
|
-
default:
|
|
380
|
-
promises[key] = node.gateway[config_obj.call](sensor.mac, parseInt(configs[key]));
|
|
381
|
-
break;
|
|
382
|
-
}
|
|
383
|
-
}else{
|
|
384
|
-
promises[key] = node.gateway[config_obj.call](sensor.mac, parseInt(configs[key]));
|
|
385
|
-
}
|
|
386
|
-
}
|
|
454
|
+
var reboot = this.sync_check_reboot(addr);
|
|
455
|
+
|
|
456
|
+
promises.sync_command = node.gateway.send_sync_configs(addr, node.sensor_configs[addr]);
|
|
387
457
|
|
|
388
458
|
// These sensors listed in original_otf_devices use a different OTF code.
|
|
389
459
|
let original_otf_devices = [53, 80, 81, 82, 83, 84, 87, 101, 102, 103, 110, 111, 112, 114, 117, 180, 181, 518, 519, 520, 538];
|
|
390
460
|
// If we changed the network ID reboot the sensor to take effect.
|
|
391
461
|
// TODO if we add the encryption key command to node-red we need to reboot for it as well.
|
|
392
462
|
if(reboot){
|
|
393
|
-
promises.reboot_sensor = node.gateway.config_reboot_sensor(
|
|
463
|
+
promises.reboot_sensor = node.gateway.config_reboot_sensor(addr);
|
|
394
464
|
} else {
|
|
395
|
-
if(original_otf_devices.includes(
|
|
396
|
-
promises.exit_otn_mode = node.gateway.config_exit_otn_mode(
|
|
465
|
+
if(original_otf_devices.includes(type)){
|
|
466
|
+
promises.exit_otn_mode = node.gateway.config_exit_otn_mode(addr);
|
|
397
467
|
}else{
|
|
398
|
-
promises.config_exit_otn_mode_common = node.gateway.config_exit_otn_mode_common(
|
|
468
|
+
promises.config_exit_otn_mode_common = node.gateway.config_exit_otn_mode_common(addr);
|
|
399
469
|
}
|
|
400
470
|
}
|
|
401
471
|
promises.finish = new Promise((fulfill, reject) => {
|
|
@@ -416,7 +486,6 @@ module.exports = function(RED) {
|
|
|
416
486
|
switch(f.result){
|
|
417
487
|
case 255:
|
|
418
488
|
success[name] = true;
|
|
419
|
-
delete node.sensor_configs[mac].temp_required_configs[name];
|
|
420
489
|
break;
|
|
421
490
|
default:
|
|
422
491
|
success[name] = {
|
|
@@ -442,7 +511,7 @@ module.exports = function(RED) {
|
|
|
442
511
|
// TODO turn into event emitter.
|
|
443
512
|
node._emitter.emit('config_node_msg', {topic: 'Config Results', payload: success, addr: mac, time: Date.now()});
|
|
444
513
|
// node.send({topic: 'Config Results', payload: success, time: Date.now(), addr: mac});
|
|
445
|
-
top_fulfill(success);
|
|
514
|
+
// top_fulfill(success);
|
|
446
515
|
}
|
|
447
516
|
}).catch((err) => {
|
|
448
517
|
success[name] = err;
|
|
@@ -903,6 +972,7 @@ module.exports = function(RED) {
|
|
|
903
972
|
this.gateway._emitter.removeAllListeners('link_info');
|
|
904
973
|
this.gateway._emitter.removeAllListeners('converter_response');
|
|
905
974
|
this.gateway._emitter.removeAllListeners('manifest_received');
|
|
975
|
+
this.gateway._emitter.removeAllListeners('sync');
|
|
906
976
|
// console.log(this.gateway._emitter.eventNames());
|
|
907
977
|
});
|
|
908
978
|
|
|
@@ -1278,6 +1348,28 @@ module.exports = function(RED) {
|
|
|
1278
1348
|
node.set_status();
|
|
1279
1349
|
node.send({topic: 'sensor_data', payload: d, time: Date.now()});
|
|
1280
1350
|
});
|
|
1351
|
+
node.gateway.on('sync', (d) => {
|
|
1352
|
+
switch (d.payload.type){
|
|
1353
|
+
case 'sync_check_in':
|
|
1354
|
+
node.set_status();
|
|
1355
|
+
node.send({
|
|
1356
|
+
'topic': 'sync',
|
|
1357
|
+
'type': d.payload.type,
|
|
1358
|
+
...d,
|
|
1359
|
+
'time': Date.now()
|
|
1360
|
+
});
|
|
1361
|
+
break;
|
|
1362
|
+
case 'sync_init':
|
|
1363
|
+
node.set_status();
|
|
1364
|
+
node.send({
|
|
1365
|
+
'topic': 'sync',
|
|
1366
|
+
'type': d.payload.type,
|
|
1367
|
+
...d,
|
|
1368
|
+
'time': Date.now()
|
|
1369
|
+
});
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
});
|
|
1281
1373
|
node.gateway.on('sensor_mode', (d) => {
|
|
1282
1374
|
node.set_status();
|
|
1283
1375
|
node.send({topic: 'sensor_mode', payload: d, time: Date.now()});
|
|
@@ -1344,6 +1436,8 @@ module.exports = function(RED) {
|
|
|
1344
1436
|
// OTN: {fill:"yellow",shape:"ring",text:"OTN Received, OTF Configuration Initiated"},
|
|
1345
1437
|
// OFF: {fill:"green",shape:"dot",text:"OFF Recieved, OTF Configuration Completed"}
|
|
1346
1438
|
FLY: {fill:"yellow",shape:"ring",text:"FLY"},
|
|
1439
|
+
INI: {fill:"yellow",shape:"ring",text:"Sync-Init"},
|
|
1440
|
+
END: {fill:"yellow",shape:"ring",text:"Sync-End"},
|
|
1347
1441
|
OTN: {fill:"yellow",shape:"ring",text:"OTN Received, Config Entered"},
|
|
1348
1442
|
OTF: {fill:"green",shape:"dot",text:"OTF Received, Config Complete"},
|
|
1349
1443
|
UPTHWRN: {fill:"yellow",shape:"ring",text:"Threshold is low"}
|
|
@@ -1842,29 +1936,119 @@ module.exports = function(RED) {
|
|
|
1842
1936
|
}
|
|
1843
1937
|
break;
|
|
1844
1938
|
case 33:
|
|
1845
|
-
if(config.
|
|
1846
|
-
promises.
|
|
1939
|
+
if(config.debounce_time_108_active){
|
|
1940
|
+
promises.debounce_time_33 = node.config_gateway.config_set_debounce_time_108(mac, parseInt(config.debounce_time_108));
|
|
1847
1941
|
}
|
|
1848
1942
|
if(config.input_two_33_active){
|
|
1849
|
-
promises.
|
|
1943
|
+
promises.input_detection_33 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_33));
|
|
1944
|
+
}
|
|
1945
|
+
if(config.debounce_time_123_active){
|
|
1946
|
+
promises.debounce_time_2byte_33 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
1850
1947
|
}
|
|
1851
1948
|
if(config.counter_threshold_108_active){
|
|
1852
|
-
promises.
|
|
1949
|
+
promises.counter_threshold_33 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
1853
1950
|
}
|
|
1854
|
-
if(config.
|
|
1855
|
-
promises.
|
|
1951
|
+
if(config.transmission_interval_108_active){
|
|
1952
|
+
promises.transmission_interval_33 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
1856
1953
|
}
|
|
1857
|
-
if(config.
|
|
1858
|
-
promises.
|
|
1954
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
1955
|
+
promises.reset_mode_33 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
1859
1956
|
}
|
|
1860
|
-
|
|
1957
|
+
if(config.reset_timeout_108_active){
|
|
1958
|
+
promises.reset_timeout_33 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
1959
|
+
}
|
|
1960
|
+
if(config.shift_one_108_active){
|
|
1961
|
+
promises.shift_time1_33 = node.config_gateway.config_set_shift_one_108(mac, parseInt(config.shift_one_hours_108), parseInt(config.shift_one_minutes_108));
|
|
1962
|
+
}
|
|
1963
|
+
if(config.shift_two_108_active){
|
|
1964
|
+
promises.shift_time2_33 = node.config_gateway.config_set_shift_two_108(mac, parseInt(config.shift_two_hours_108), parseInt(config.shift_two_minutes_108));
|
|
1965
|
+
}
|
|
1966
|
+
if(config.shift_three_108_active){
|
|
1967
|
+
promises.shift_time3_33 = node.config_gateway.config_set_shift_three_108(mac, parseInt(config.shift_three_hours_108), parseInt(config.shift_three_minutes_108));
|
|
1968
|
+
}
|
|
1969
|
+
if(config.shift_four_108_active){
|
|
1970
|
+
promises.shift_time4_33 = node.config_gateway.config_set_shift_four_108(mac, parseInt(config.shift_four_hours_108), parseInt(config.shift_four_minutes_108));
|
|
1971
|
+
}
|
|
1972
|
+
if(config.quality_of_service_108_active){
|
|
1973
|
+
promises.quality_of_service_33 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
1974
|
+
}
|
|
1975
|
+
if(config.rtc_108){
|
|
1976
|
+
promises.rtc_33 = node.config_gateway.config_set_rtc_108(mac);
|
|
1977
|
+
}
|
|
1978
|
+
if(config.clear_timers_35){
|
|
1979
|
+
promises.clear_counters_33 = node.config_gateway.config_set_clear_timers_35(mac);
|
|
1980
|
+
}
|
|
1981
|
+
if(config.push_notification_35_active){
|
|
1982
|
+
promises.push_notification_33 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_35));
|
|
1983
|
+
}
|
|
1984
|
+
if(config.interrupt_timeout_35_active){
|
|
1985
|
+
promises.interrupt_timeout_33 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_35));
|
|
1986
|
+
}
|
|
1987
|
+
if(config.probe_one_126_active){
|
|
1988
|
+
promises.probe_one_33 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
1989
|
+
}
|
|
1990
|
+
if(config.threshold_probe_one_126_active){
|
|
1991
|
+
promises.threshold_probe_one_33 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
1992
|
+
}
|
|
1993
|
+
break;
|
|
1861
1994
|
case 35:
|
|
1862
1995
|
if(config.counter_threshold_35_active){
|
|
1863
1996
|
promises.config_set_counter_threshold_35 = node.config_gateway.config_set_counter_threshold_35(mac, parseInt(config.counter_threshold_35));
|
|
1864
1997
|
}
|
|
1998
|
+
if(config.counter_threshold_35_gen2_active){
|
|
1999
|
+
promises.config_set_counter_threshold_35_gen2 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_35_gen2));
|
|
2000
|
+
}
|
|
1865
2001
|
if(config.debounce_time_2_active){
|
|
1866
2002
|
promises.config_set_debounce_time_35 = node.config_gateway.config_set_debounce_time_35(mac, parseInt(config.debounce_time_2));
|
|
1867
2003
|
}
|
|
2004
|
+
if(config.debounce_time_123_active){
|
|
2005
|
+
promises.debounce_time_35 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
2006
|
+
}
|
|
2007
|
+
if(config.input_one_123_active){
|
|
2008
|
+
promises.input_one_35 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
2009
|
+
}
|
|
2010
|
+
if(config.counter_threshold_108_active){
|
|
2011
|
+
promises.counter_threshold_35 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
2012
|
+
}
|
|
2013
|
+
if(config.reset_timeout_108_active){
|
|
2014
|
+
promises.reset_timeout_35 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
2015
|
+
}
|
|
2016
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
2017
|
+
promises.reset_mode_35 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
2018
|
+
}
|
|
2019
|
+
if(config.rtc_108){
|
|
2020
|
+
promises.rtc_35 = node.config_gateway.config_set_rtc_108(mac);
|
|
2021
|
+
}
|
|
2022
|
+
if(config.transmission_interval_108_active){
|
|
2023
|
+
promises.transmission_interval_35 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
2024
|
+
}
|
|
2025
|
+
if(config.shift_one_108_active){
|
|
2026
|
+
promises.shift_time1_35 = node.config_gateway.config_set_shift_one_108(mac, parseInt(config.shift_one_hours_108), parseInt(config.shift_one_minutes_108));
|
|
2027
|
+
}
|
|
2028
|
+
if(config.shift_two_108_active){
|
|
2029
|
+
promises.shift_time2_35 = node.config_gateway.config_set_shift_two_108(mac, parseInt(config.shift_two_hours_108), parseInt(config.shift_two_minutes_108));
|
|
2030
|
+
}
|
|
2031
|
+
if(config.shift_three_108_active){
|
|
2032
|
+
promises.shift_time3_35 = node.config_gateway.config_set_shift_three_108(mac, parseInt(config.shift_three_hours_108), parseInt(config.shift_three_minutes_108));
|
|
2033
|
+
}
|
|
2034
|
+
if(config.shift_four_108_active){
|
|
2035
|
+
promises.shift_time4_35 = node.config_gateway.config_set_shift_four_108(mac, parseInt(config.shift_four_hours_108), parseInt(config.shift_four_minutes_108));
|
|
2036
|
+
}
|
|
2037
|
+
if(config.quality_of_service_108_active){
|
|
2038
|
+
promises.quality_of_service_35 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
2039
|
+
}
|
|
2040
|
+
if(config.fly_interval_108_active){
|
|
2041
|
+
promises.fly_interval_35 = node.config_gateway.config_set_fly_interval_108(mac, parseInt(config.fly_interval_108));
|
|
2042
|
+
}
|
|
2043
|
+
if(config.clear_timers_35){
|
|
2044
|
+
promises.clear_timers_35 = node.config_gateway.config_set_clear_timers_35(mac);
|
|
2045
|
+
}
|
|
2046
|
+
if(config.push_notification_35_active){
|
|
2047
|
+
promises.push_notification_35 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_35));
|
|
2048
|
+
}
|
|
2049
|
+
if(config.interrupt_timeout_35_active){
|
|
2050
|
+
promises.interrupt_timeout_35 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_35));
|
|
2051
|
+
}
|
|
1868
2052
|
break;
|
|
1869
2053
|
case 36:
|
|
1870
2054
|
if(config.counter_threshold_35_active){
|
|
@@ -2451,6 +2635,11 @@ module.exports = function(RED) {
|
|
|
2451
2635
|
promises.sensor_boot_time_78 = node.config_gateway.config_set_sensor_boot_time_78(mac, parseInt(config.sensor_boot_time_78));
|
|
2452
2636
|
}
|
|
2453
2637
|
break;
|
|
2638
|
+
case 93:
|
|
2639
|
+
if(config.sensor_boot_time_78_active){
|
|
2640
|
+
promises.sensor_boot_time_93 = node.config_gateway.config_set_sensor_boot_time_78(mac, parseInt(config.sensor_boot_time_78));
|
|
2641
|
+
}
|
|
2642
|
+
break;
|
|
2454
2643
|
case 95:
|
|
2455
2644
|
if(config.sensor_boot_time_420ma_active){
|
|
2456
2645
|
promises.sensor_boot_time_420ma = node.config_gateway.config_set_sensor_boot_time_420ma(mac, parseInt(config.sensor_boot_time_420ma));
|
|
@@ -2644,6 +2833,9 @@ module.exports = function(RED) {
|
|
|
2644
2833
|
if(config.set_rtc_101){
|
|
2645
2834
|
promises.set_rtc_103 = node.config_gateway.config_set_rtc_101(mac);
|
|
2646
2835
|
}
|
|
2836
|
+
if(config.send_raw_on_motion_only_103_active){
|
|
2837
|
+
promises.send_raw_on_motion_only_103 = node.config_gateway.config_set_send_raw_on_motion_only_103(mac, parseInt(config.send_raw_on_motion_only_103));
|
|
2838
|
+
}
|
|
2647
2839
|
break;
|
|
2648
2840
|
case 105:
|
|
2649
2841
|
if(config.sensor_boot_time_420ma_active){
|
|
@@ -3281,8 +3473,8 @@ module.exports = function(RED) {
|
|
|
3281
3473
|
}
|
|
3282
3474
|
break;
|
|
3283
3475
|
case 123:
|
|
3284
|
-
if(config.
|
|
3285
|
-
promises.clear_timers_123 = node.config_gateway.config_set_clear_timers_108(mac,
|
|
3476
|
+
if(config.clear_timers_123){
|
|
3477
|
+
promises.clear_timers_123 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3286
3478
|
}
|
|
3287
3479
|
if(config.debounce_time_123_active){
|
|
3288
3480
|
promises.debounce_time_123 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
@@ -3368,6 +3560,139 @@ module.exports = function(RED) {
|
|
|
3368
3560
|
promises.reset_all_totalizers_124 = node.config_gateway.config_set_reset_all_totalizers_124(mac);
|
|
3369
3561
|
}
|
|
3370
3562
|
break;
|
|
3563
|
+
case 125:
|
|
3564
|
+
if(config.clear_timers_123){
|
|
3565
|
+
promises.clear_timers_125 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3566
|
+
}
|
|
3567
|
+
if(config.debounce_time_123_active){
|
|
3568
|
+
promises.debounce_time_125 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
3569
|
+
}
|
|
3570
|
+
if(config.input_one_123_active){
|
|
3571
|
+
promises.input_one_125 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
3572
|
+
}
|
|
3573
|
+
if(config.input_two_123_active){
|
|
3574
|
+
promises.input_two_125 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_123));
|
|
3575
|
+
}
|
|
3576
|
+
if(config.counter_threshold_108_active){
|
|
3577
|
+
promises.counter_threshold_125 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
3578
|
+
}
|
|
3579
|
+
if(config.push_notification_125_active){
|
|
3580
|
+
promises.push_notification_125 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_125));
|
|
3581
|
+
}
|
|
3582
|
+
if(config.reset_timeout_108_active){
|
|
3583
|
+
promises.reset_timeout_125 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
3584
|
+
}
|
|
3585
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
3586
|
+
promises.reset_mode_125 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
3587
|
+
}
|
|
3588
|
+
if(config.rtc_108){
|
|
3589
|
+
promises.rtc_125 = node.config_gateway.config_set_rtc_108(mac);
|
|
3590
|
+
}
|
|
3591
|
+
if(config.transmission_interval_108_active){
|
|
3592
|
+
promises.transmission_interval_125 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
3593
|
+
}
|
|
3594
|
+
if(config.shift_one_108_active){
|
|
3595
|
+
promises.shift_time1_125 = node.config_gateway.config_set_shift_one_108(mac, parseInt(config.shift_one_hours_108), parseInt(config.shift_one_minutes_108));
|
|
3596
|
+
}
|
|
3597
|
+
if(config.shift_two_108_active){
|
|
3598
|
+
promises.shift_time2_125 = node.config_gateway.config_set_shift_two_108(mac, parseInt(config.shift_two_hours_108), parseInt(config.shift_two_minutes_108));
|
|
3599
|
+
}
|
|
3600
|
+
if(config.shift_three_108_active){
|
|
3601
|
+
promises.shift_time3_125 = node.config_gateway.config_set_shift_three_108(mac, parseInt(config.shift_three_hours_108), parseInt(config.shift_three_minutes_108));
|
|
3602
|
+
}
|
|
3603
|
+
if(config.shift_four_108_active){
|
|
3604
|
+
promises.shift_time4_125 = node.config_gateway.config_set_shift_four_108(mac, parseInt(config.shift_four_hours_108), parseInt(config.shift_four_minutes_108));
|
|
3605
|
+
}
|
|
3606
|
+
if(config.quality_of_service_108_active){
|
|
3607
|
+
promises.quality_of_service_125 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
3608
|
+
}
|
|
3609
|
+
if(config.interrupt_timeout_108_active){
|
|
3610
|
+
promises.interrupt_timeout_125 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_108));
|
|
3611
|
+
}
|
|
3612
|
+
if(config.probe_one_126_active){
|
|
3613
|
+
promises.probe_one_125 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
3614
|
+
}
|
|
3615
|
+
if(config.probe_two_126_active){
|
|
3616
|
+
promises.probe_two_125 = node.config_gateway.config_set_probe_two_ct_126(mac, parseInt(config.probe_two_126));
|
|
3617
|
+
}
|
|
3618
|
+
if(config.threshold_probe_one_126_active){
|
|
3619
|
+
promises.threshold_probe_one_125 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
3620
|
+
}
|
|
3621
|
+
if(config.threshold_probe_two_126_active){
|
|
3622
|
+
promises.threshold_probe_two_125 = node.config_gateway.config_set_probe_two_current_threshold_126(mac, parseInt(config.threshold_probe_two_126));
|
|
3623
|
+
}
|
|
3624
|
+
break;
|
|
3625
|
+
case 126:
|
|
3626
|
+
if(config.clear_timers_123){
|
|
3627
|
+
promises.clear_timers_126 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3628
|
+
}
|
|
3629
|
+
if(config.debounce_time_123_active){
|
|
3630
|
+
promises.debounce_time_126 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
3631
|
+
}
|
|
3632
|
+
if(config.input_one_123_active){
|
|
3633
|
+
promises.input_one_126 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
3634
|
+
}
|
|
3635
|
+
if(config.input_two_123_active){
|
|
3636
|
+
promises.input_two_126 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_123));
|
|
3637
|
+
}
|
|
3638
|
+
if(config.input_three_123_active){
|
|
3639
|
+
promises.input_three_126 = node.config_gateway.config_set_input_three_108(mac, parseInt(config.input_three_123));
|
|
3640
|
+
}
|
|
3641
|
+
if(config.counter_threshold_108_active){
|
|
3642
|
+
promises.counter_threshold_126 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
3643
|
+
}
|
|
3644
|
+
if(config.push_notification_123_active){
|
|
3645
|
+
promises.push_notification_126 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_123));
|
|
3646
|
+
}
|
|
3647
|
+
if(config.reset_timeout_108_active){
|
|
3648
|
+
promises.reset_timeout_126 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
3649
|
+
}
|
|
3650
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
3651
|
+
promises.reset_mode_126 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
3652
|
+
}
|
|
3653
|
+
if(config.rtc_108){
|
|
3654
|
+
promises.rtc_126 = node.config_gateway.config_set_rtc_108(mac);
|
|
3655
|
+
}
|
|
3656
|
+
if(config.transmission_interval_108_active){
|
|
3657
|
+
promises.transmission_interval_126 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
3658
|
+
}
|
|
3659
|
+
if(config.shift_one_108_active){
|
|
3660
|
+
promises.shift_time1_126 = node.config_gateway.config_set_shift_one_108(mac, parseInt(config.shift_one_hours_108), parseInt(config.shift_one_minutes_108));
|
|
3661
|
+
}
|
|
3662
|
+
if(config.shift_two_108_active){
|
|
3663
|
+
promises.shift_time2_126 = node.config_gateway.config_set_shift_two_108(mac, parseInt(config.shift_two_hours_108), parseInt(config.shift_two_minutes_108));
|
|
3664
|
+
}
|
|
3665
|
+
if(config.shift_three_108_active){
|
|
3666
|
+
promises.shift_time3_126 = node.config_gateway.config_set_shift_three_108(mac, parseInt(config.shift_three_hours_108), parseInt(config.shift_three_minutes_108));
|
|
3667
|
+
}
|
|
3668
|
+
if(config.shift_four_108_active){
|
|
3669
|
+
promises.shift_time4_126 = node.config_gateway.config_set_shift_four_108(mac, parseInt(config.shift_four_hours_108), parseInt(config.shift_four_minutes_108));
|
|
3670
|
+
}
|
|
3671
|
+
if(config.quality_of_service_108_active){
|
|
3672
|
+
promises.quality_of_service_126 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
3673
|
+
}
|
|
3674
|
+
if(config.interrupt_timeout_108_active){
|
|
3675
|
+
promises.interrupt_timeout_126 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_108));
|
|
3676
|
+
}
|
|
3677
|
+
if(config.probe_one_126_active){
|
|
3678
|
+
promises.probe_one_126 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
3679
|
+
}
|
|
3680
|
+
if(config.probe_two_126_active){
|
|
3681
|
+
promises.probe_two_126 = node.config_gateway.config_set_probe_two_ct_126(mac, parseInt(config.probe_two_126));
|
|
3682
|
+
}
|
|
3683
|
+
if(config.probe_three_126_active){
|
|
3684
|
+
promises.probe_three_126 = node.config_gateway.config_set_probe_three_ct_126(mac, parseInt(config.probe_three_126));
|
|
3685
|
+
}
|
|
3686
|
+
if(config.threshold_probe_one_126_active){
|
|
3687
|
+
promises.threshold_probe_one_126 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
3688
|
+
}
|
|
3689
|
+
if(config.threshold_probe_two_126_active){
|
|
3690
|
+
promises.threshold_probe_two_126 = node.config_gateway.config_set_probe_two_current_threshold_126(mac, parseInt(config.threshold_probe_two_126));
|
|
3691
|
+
}
|
|
3692
|
+
if(config.threshold_probe_three_126_active){
|
|
3693
|
+
promises.threshold_probe_three_126 = node.config_gateway.config_set_probe_three_current_threshold_126(mac, parseInt(config.threshold_probe_three_126));
|
|
3694
|
+
}
|
|
3695
|
+
break;
|
|
3371
3696
|
case 180:
|
|
3372
3697
|
if(config.output_data_rate_101_active){
|
|
3373
3698
|
promises.output_data_rate_101 = node.config_gateway.config_set_output_data_rate_101(mac, parseInt(config.output_data_rate_101));
|
|
@@ -4033,8 +4358,6 @@ module.exports = function(RED) {
|
|
|
4033
4358
|
(function(name){
|
|
4034
4359
|
promises[name].then((f) => {
|
|
4035
4360
|
if(name != 'finish'){
|
|
4036
|
-
// console.log('IN PROMISE RESOLVE');
|
|
4037
|
-
// console.log(f);
|
|
4038
4361
|
// success[name] = true;
|
|
4039
4362
|
if(Object.hasOwn(f, 'result')){
|
|
4040
4363
|
switch(f.result){
|
|
@@ -4132,6 +4455,106 @@ module.exports = function(RED) {
|
|
|
4132
4455
|
});
|
|
4133
4456
|
}
|
|
4134
4457
|
});
|
|
4458
|
+
this.pgm_on('sync-'+config.addr, (data) => {
|
|
4459
|
+
let message = {
|
|
4460
|
+
topic: 'sync',
|
|
4461
|
+
type: data.payload.type,
|
|
4462
|
+
...data,
|
|
4463
|
+
time: Date.now()
|
|
4464
|
+
};
|
|
4465
|
+
|
|
4466
|
+
// switch(data.type){
|
|
4467
|
+
// case 'sync_check_in':
|
|
4468
|
+
// break;
|
|
4469
|
+
// case 'sync_init':
|
|
4470
|
+
// break;
|
|
4471
|
+
// case 'sync_acknowledgment':
|
|
4472
|
+
// break;
|
|
4473
|
+
// case 'sync_acknowledgment_error':
|
|
4474
|
+
// break;
|
|
4475
|
+
// case 'sync_end':
|
|
4476
|
+
// break;
|
|
4477
|
+
// default:
|
|
4478
|
+
// console.log('Default in device node sync');
|
|
4479
|
+
// console.log(data.type);
|
|
4480
|
+
// }
|
|
4481
|
+
if(data.type == 'sync_check_in' || data.type == 'manual_sync_check_in'){
|
|
4482
|
+
if(config.auto_config && config.on_the_fly_enable || data.type == 'manual_sync_check_in' && config.auto_config){
|
|
4483
|
+
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
|
+
const html_map = this.config_gateway.get_intended_wireless_node_configs(data, config);
|
|
4485
|
+
|
|
4486
|
+
let update_flag = false;
|
|
4487
|
+
for(let key in html_map){
|
|
4488
|
+
if(html_map[key].html_value != node.gateway_node.sensor_configs[data.payload.address].reported_configs[key]){
|
|
4489
|
+
// console.log('Comparing ' + html_map[key].html_value + ' to ' + node.gateway_node.sensor_configs[data.payload.address].reported_configs[key]);
|
|
4490
|
+
// console.log('Value is different, updating config for ' + key);
|
|
4491
|
+
update_flag = true;
|
|
4492
|
+
break;
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4495
|
+
if(update_flag){
|
|
4496
|
+
promises = {};
|
|
4497
|
+
setTimeout(() => {
|
|
4498
|
+
let msg = {
|
|
4499
|
+
values: {},
|
|
4500
|
+
pass: {},
|
|
4501
|
+
status: 'Configuring'
|
|
4502
|
+
};
|
|
4503
|
+
var tout = setTimeout(() => {
|
|
4504
|
+
console.log('Sync Request Timed Out');
|
|
4505
|
+
}, 20000);
|
|
4506
|
+
promises.send_sync_configs = this.config_gateway.send_sync_config_wireless_node(data, html_map, node.gateway_node.sensor_configs[data.payload.address]);
|
|
4507
|
+
|
|
4508
|
+
promises.finish = new Promise((fulfill, reject) => {
|
|
4509
|
+
node.config_gateway.queue.add(() => {
|
|
4510
|
+
return new Promise((f, r) => {
|
|
4511
|
+
clearTimeout(tout);
|
|
4512
|
+
node.status(modes.FLY);
|
|
4513
|
+
fulfill();
|
|
4514
|
+
f();
|
|
4515
|
+
});
|
|
4516
|
+
});
|
|
4517
|
+
});
|
|
4518
|
+
for(var i in promises){
|
|
4519
|
+
(function(name){
|
|
4520
|
+
promises[name].then((f) => {
|
|
4521
|
+
if(name != 'finish'){
|
|
4522
|
+
let fail_flag = false;
|
|
4523
|
+
for(const key in html_map){
|
|
4524
|
+
if(Object.hasOwn(f.payload, key) && f.payload[key] == html_map[key].html_value){
|
|
4525
|
+
msg.pass[key] = true;
|
|
4526
|
+
msg.values[key] = f.payload[key];
|
|
4527
|
+
}else{
|
|
4528
|
+
msg.pass[key] = false;
|
|
4529
|
+
msg.values[key] = f.payload[key];
|
|
4530
|
+
fail_flag = true;
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
if(fail_flag){
|
|
4534
|
+
msg.status = 'Error';
|
|
4535
|
+
}else{
|
|
4536
|
+
msg.status = 'Success';
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
4539
|
+
else{
|
|
4540
|
+
node.send({topic: 'sync', type: 'sync_response', payload: msg, time: Date.now()});
|
|
4541
|
+
// top_fulfill(msg);
|
|
4542
|
+
}
|
|
4543
|
+
}).catch((err) => {
|
|
4544
|
+
msg[name] = err;
|
|
4545
|
+
});
|
|
4546
|
+
})(i);
|
|
4547
|
+
}
|
|
4548
|
+
});
|
|
4549
|
+
}else{
|
|
4550
|
+
// 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()});
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
node.send(message);
|
|
4557
|
+
});
|
|
4135
4558
|
this.pgm_on('sensor_mode-'+config.addr, (sensor) => {
|
|
4136
4559
|
if(sensor.mode in modes){
|
|
4137
4560
|
node.status(modes[sensor.mode]);
|
|
@@ -4141,7 +4564,7 @@ module.exports = function(RED) {
|
|
|
4141
4564
|
}
|
|
4142
4565
|
if(config.auto_config && sensor.mode == "PGM"){
|
|
4143
4566
|
_config(sensor);
|
|
4144
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY"){
|
|
4567
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync')){
|
|
4145
4568
|
// _send_otn_request(sensor);
|
|
4146
4569
|
// Sensors having issues seeing OTN request sent too quickly
|
|
4147
4570
|
// Added timeout to fix issue
|
|
@@ -4155,11 +4578,11 @@ module.exports = function(RED) {
|
|
|
4155
4578
|
}else{
|
|
4156
4579
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4157
4580
|
}
|
|
4158
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN"){
|
|
4159
|
-
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 202){
|
|
4581
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN" && !Object.hasOwn(sensor, 'sync')){
|
|
4582
|
+
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 103 || config.sensor_type == 202){
|
|
4160
4583
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4161
4584
|
this.gateway.fly_101_in_progress = true;
|
|
4162
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4585
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4163
4586
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4164
4587
|
var broadcast_tout = setTimeout(() => {
|
|
4165
4588
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4181,10 +4604,10 @@ module.exports = function(RED) {
|
|
|
4181
4604
|
}else{
|
|
4182
4605
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4183
4606
|
};
|
|
4184
|
-
} else if(config.sensor_type == 101 && sensor.mode == "FLY" || config.sensor_type == 102 && sensor.mode == "FLY" || config.sensor_type == 202 && sensor.mode == "FLY"){
|
|
4607
|
+
} else if(config.sensor_type == 101 && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync') || config.sensor_type == 102 && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync') || config.sensor_type == 103 && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync') || config.sensor_type == 202 && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync')){
|
|
4185
4608
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4186
4609
|
this.gateway.fly_101_in_progress = true;
|
|
4187
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4610
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4188
4611
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4189
4612
|
var broadcast_tout = setTimeout(() => {
|
|
4190
4613
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4257,7 +4680,7 @@ module.exports = function(RED) {
|
|
|
4257
4680
|
}
|
|
4258
4681
|
if(config.auto_config && sensor.mode == 'PGM'){
|
|
4259
4682
|
_config(sensor);
|
|
4260
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY"){
|
|
4683
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync')){
|
|
4261
4684
|
// _send_otn_request(sensor);
|
|
4262
4685
|
// Sensors having issues seeing OTN request sent too quickly
|
|
4263
4686
|
// Added timeout to fix issue
|
|
@@ -4271,8 +4694,8 @@ module.exports = function(RED) {
|
|
|
4271
4694
|
}else{
|
|
4272
4695
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4273
4696
|
}
|
|
4274
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN"){
|
|
4275
|
-
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 202){
|
|
4697
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN" && !Object.hasOwn(sensor, 'sync')){
|
|
4698
|
+
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 103|| config.sensor_type == 202){
|
|
4276
4699
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4277
4700
|
this.gateway.fly_101_in_progress = true;
|
|
4278
4701
|
node.warn('Starting RTC Timer' + Date.now());
|
|
@@ -4299,10 +4722,10 @@ module.exports = function(RED) {
|
|
|
4299
4722
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4300
4723
|
};
|
|
4301
4724
|
|
|
4302
|
-
}else if(sensor.mode == "FLY" && config.sensor_type == 101 || sensor.mode == "FLY" && config.sensor_type == 102 || sensor.mode == "FLY" && config.sensor_type == 202){
|
|
4725
|
+
}else if(sensor.mode == "FLY" && config.sensor_type == 101 && !Object.hasOwn(sensor, 'sync') || sensor.mode == "FLY" && config.sensor_type == 102 && !Object.hasOwn(sensor, 'sync') || sensor.mode == "FLY" && config.sensor_type == 103 && !Object.hasOwn(sensor, 'sync') || sensor.mode == "FLY" && config.sensor_type == 202 && !Object.hasOwn(sensor, 'sync')){
|
|
4303
4726
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4304
4727
|
this.gateway.fly_101_in_progress = true;
|
|
4305
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4728
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4306
4729
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4307
4730
|
var broadcast_tout = setTimeout(() => {
|
|
4308
4731
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4513,15 +4936,17 @@ module.exports = function(RED) {
|
|
|
4513
4936
|
break;
|
|
4514
4937
|
case 'sensor_config_options':
|
|
4515
4938
|
msg.request = msg.payload;
|
|
4516
|
-
//
|
|
4517
|
-
|
|
4518
|
-
|
|
4939
|
+
// console.log(typeof msg.payload == 'object');
|
|
4940
|
+
// console.log(Object.hasOwn(msg.payload, 'sensor_type'));
|
|
4941
|
+
// console.log(Object.hasOwn(this.gateway.sensor_libs, msg.payload.sensor_type));
|
|
4942
|
+
if(typeof msg.payload == 'object' && Object.hasOwn(msg.payload, 'sensor_type') && Object.hasOwn(this.gateway.sensor_libs, msg.payload.sensor_type)){
|
|
4943
|
+
let options = this.get_config_options(msg.payload.sensor_type, msg.payload.firmware_version);
|
|
4519
4944
|
msg.payload = options;
|
|
4520
4945
|
msg.status = 200;
|
|
4521
4946
|
msg.time = Date.now();
|
|
4522
4947
|
send(msg);
|
|
4523
4948
|
}else{
|
|
4524
|
-
msg.payload = {error: 'get_config_options error:
|
|
4949
|
+
msg.payload = {error: 'get_config_options error: msg.payload must be object with sensor_type property corresponding to a valid sensor type number. e.g. {sensor_type: 114}. Optionally pass in firmware_version property to get options for specific firmware version e.g. {sensor_type: 114, firmware_version: 2}.'};
|
|
4525
4950
|
msg.status = 500;
|
|
4526
4951
|
msg.time = Date.now();
|
|
4527
4952
|
send(msg);
|
|
@@ -4582,48 +5007,36 @@ module.exports = function(RED) {
|
|
|
4582
5007
|
return response;
|
|
4583
5008
|
};
|
|
4584
5009
|
|
|
4585
|
-
this.get_config_options = function(sensor_type){
|
|
4586
|
-
if(Object.hasOwn(
|
|
4587
|
-
const config_list =
|
|
5010
|
+
this.get_config_options = function(sensor_type, firmware_version = 1){
|
|
5011
|
+
if(Object.hasOwn(this.gateway.sensor_libs, sensor_type)){
|
|
5012
|
+
const config_list = this.gateway.sensor_libs[sensor_type].get_config_map(firmware_version);
|
|
4588
5013
|
let response = {};
|
|
4589
5014
|
for (const key in config_list){
|
|
4590
|
-
const info =
|
|
5015
|
+
const info = config_list[key];
|
|
4591
5016
|
// If sensors actually reports and supports the listed config
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
5017
|
+
// console.log(key);
|
|
5018
|
+
// console.log(info);
|
|
5019
|
+
if(Object.hasOwn(info, 'write_index') && !Object.hasOwn(info, 'read_only')){
|
|
5020
|
+
response[key] = {
|
|
5021
|
+
title: info.descriptions.title,
|
|
5022
|
+
default_value: info.default_value,
|
|
5023
|
+
};
|
|
5024
|
+
if(Object.hasOwn(info.descriptions, 'main_caption')){
|
|
5025
|
+
response[key].description = info.descriptions.main_caption;
|
|
5026
|
+
}
|
|
5027
|
+
if(Object.hasOwn(info.descriptions, 'sub_caption')){
|
|
5028
|
+
response[key].description = info.descriptions.main_caption;
|
|
5029
|
+
}
|
|
5030
|
+
if(Object.hasOwn(info, 'validator')){
|
|
5031
|
+
if(Object.hasOwn(info.validator, 'generated')){
|
|
5032
|
+
delete info.validator.generated;
|
|
5033
|
+
}
|
|
5034
|
+
response[key] = {...response[key], ...info.validator};
|
|
5035
|
+
}
|
|
5036
|
+
if(Object.hasOwn(info, 'options')){
|
|
5037
|
+
response[key].options = info.options;
|
|
4605
5038
|
}
|
|
4606
|
-
response[key] = {...response[key], ...info.validator};
|
|
4607
|
-
}
|
|
4608
|
-
if(Object.hasOwn(info, 'options')){
|
|
4609
|
-
response[key].options = info.options;
|
|
4610
5039
|
}
|
|
4611
|
-
|
|
4612
|
-
// if(Object.hasOwn(info, 'validator') && Object.hasOwn(info.validator, 'type')){
|
|
4613
|
-
|
|
4614
|
-
// response[key].value_type = info.validator.type;
|
|
4615
|
-
// }
|
|
4616
|
-
// if(Object.hasOwn(info, 'options')){
|
|
4617
|
-
// response[key].options = info.options;
|
|
4618
|
-
// }else{
|
|
4619
|
-
// if(Object.hasOwn(info, 'validator') && Object.hasOwn(info.validator, 'min')){
|
|
4620
|
-
// response[key].minimum_value = info.validator.min;
|
|
4621
|
-
// }
|
|
4622
|
-
// if(Object.hasOwn(info, 'validator') && Object.hasOwn(info.validator, 'max')){
|
|
4623
|
-
// response[key].maximum_value = info.validator.max;
|
|
4624
|
-
// }
|
|
4625
|
-
// }
|
|
4626
|
-
// node.warn(info);
|
|
4627
5040
|
}
|
|
4628
5041
|
return response;
|
|
4629
5042
|
}else{
|
|
@@ -4636,12 +5049,96 @@ module.exports = function(RED) {
|
|
|
4636
5049
|
var response = {};
|
|
4637
5050
|
let error_msg = {};
|
|
4638
5051
|
let warning_msg = {};
|
|
5052
|
+
|
|
4639
5053
|
if(desired_configs == null || typeof desired_configs == 'undefined'){
|
|
4640
5054
|
return {error: 'msg.payload is required. It must be an array of sensor configuration objects. Each object in the array must have addr, type, and configs properties i.e. [{addr: "sensor_mac_address", type: sensor_type_number, configs: {config_name: desired_value}}]'};
|
|
4641
5055
|
}else if(!Array.isArray(desired_configs) || desired_configs.length == 0){
|
|
4642
5056
|
return {error: 'msg.payload must be an array of sensor configuration objects. Each object in the array must have addr, type, and configs properties i.e. [{addr: "sensor_mac_address", type: sensor_type_number, configs: {config_name: desired_value}}]'};
|
|
4643
5057
|
}
|
|
5058
|
+
|
|
5059
|
+
const build_error = (sensor, key, detail) => {
|
|
5060
|
+
return {
|
|
5061
|
+
type: 'error',
|
|
5062
|
+
message: `${detail.text} for ${key} on sensor ${sensor.addr}.`,
|
|
5063
|
+
detail: {
|
|
5064
|
+
config_name: key,
|
|
5065
|
+
...detail // Merges everything: received, help, expected, etc.
|
|
5066
|
+
}
|
|
5067
|
+
};
|
|
5068
|
+
};
|
|
5069
|
+
|
|
5070
|
+
const build_warning = (sensor, key, detail) => {
|
|
5071
|
+
return {
|
|
5072
|
+
type: 'warning',
|
|
5073
|
+
message: `${detail.text} for ${key} on sensor ${sensor.addr}.`,
|
|
5074
|
+
detail: {
|
|
5075
|
+
config_name: key,
|
|
5076
|
+
...detail,
|
|
5077
|
+
help: detail.help || "This warning does not prevent the configuration from going through."
|
|
5078
|
+
}
|
|
5079
|
+
};
|
|
5080
|
+
};
|
|
5081
|
+
|
|
5082
|
+
const validation_methods = {
|
|
5083
|
+
// HEX: Strict, no colons allowed
|
|
5084
|
+
hex: (val, validator, configName, sensor) => {
|
|
5085
|
+
const strVal = String(val);
|
|
5086
|
+
if (!/^[0-9a-f]+$/i.test(strVal)) {
|
|
5087
|
+
return { error: this.build_error(sensor, configName, val, "Invalid hex string", "Hex string should only contain 0-9 and a-f.") };
|
|
5088
|
+
}
|
|
5089
|
+
if (validator.length && strVal.length !== validator.length) {
|
|
5090
|
+
return { error: this.build_error(sensor, configName, val, "Invalid length for hex string", `Expected ${validator.length}, got ${strVal.length}`) };
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
const result = { value: strVal.toLowerCase() };
|
|
5094
|
+
if (!validator.length) {
|
|
5095
|
+
result.warning = this.build_warning(sensor, configName, "Missing length validator", "hexString");
|
|
5096
|
+
}
|
|
5097
|
+
return result;
|
|
5098
|
+
},
|
|
5099
|
+
|
|
5100
|
+
// MAC: Flexible, strips colons first
|
|
5101
|
+
mac: (val, validator, configName, sensor) => {
|
|
5102
|
+
const clean = String(val).replace(/:/g, '');
|
|
5103
|
+
if (!/^[0-9a-f]+$/i.test(clean)) {
|
|
5104
|
+
return { error: this.build_error(sensor, configName, val, "Invalid MAC format", "MAC string should only contain 0-9, a-f, and colons.") };
|
|
5105
|
+
}
|
|
5106
|
+
if (validator.length && clean.length !== validator.length) {
|
|
5107
|
+
return { error: this.build_error(sensor, configName, clean, "Invalid length for MAC", `Expected ${validator.length}, got ${clean.length}`) };
|
|
5108
|
+
}
|
|
5109
|
+
return { value: clean.toLowerCase() };
|
|
5110
|
+
},
|
|
5111
|
+
|
|
5112
|
+
// NUMBERS: uint8, uint16be, uint32be
|
|
5113
|
+
number: (val, validator, configName, sensor, options) => {
|
|
5114
|
+
const num = parseInt(val);
|
|
5115
|
+
if (isNaN(num)) {
|
|
5116
|
+
return { error: this.build_error(sensor, configName, val, "Integer value expected", "Ensure the value is a valid number.") };
|
|
5117
|
+
}
|
|
5118
|
+
|
|
5119
|
+
// Check Min/Max
|
|
5120
|
+
if (validator.min !== undefined && num < validator.min) {
|
|
5121
|
+
return { error: this.build_error(sensor, configName, num, "Value below minimum", `Min allowed: ${validator.min}`) };
|
|
5122
|
+
}
|
|
5123
|
+
if (validator.max !== undefined && num > validator.max) {
|
|
5124
|
+
return { error: this.build_error(sensor, configName, num, "Value above maximum", `Max allowed: ${validator.max}`) };
|
|
5125
|
+
}
|
|
5126
|
+
|
|
5127
|
+
// Check Options
|
|
5128
|
+
if (options && !Object.keys(options).includes(String(num))) {
|
|
5129
|
+
return { error: this.build_error(sensor, configName, num, "Invalid option", `Valid options: ${JSON.stringify(options)}`) };
|
|
5130
|
+
}
|
|
5131
|
+
|
|
5132
|
+
const result = { value: num };
|
|
5133
|
+
if (validator.min === undefined || validator.max === undefined) {
|
|
5134
|
+
result.warning = this.build_warning(sensor, configName, "Missing min/max validator", "number");
|
|
5135
|
+
}
|
|
5136
|
+
return result;
|
|
5137
|
+
}
|
|
5138
|
+
};
|
|
5139
|
+
|
|
4644
5140
|
for (const sensor of desired_configs){
|
|
5141
|
+
|
|
4645
5142
|
// TODO validate sensor object
|
|
4646
5143
|
// must have sensor.addr, sensor.type, sensor.configs
|
|
4647
5144
|
// sensor.configs is an object with key value pairs of config name and desired value
|
|
@@ -4674,6 +5171,21 @@ module.exports = function(RED) {
|
|
|
4674
5171
|
// error_msg[sensor.addr].syntax_error = 'Invalid sensor object in array. Each object in the array must have addr, type, and configs properties i.e. [{addr: "sensor_mac_address", type: sensor_type_number, configs: {config_name: desired_value}}]';
|
|
4675
5172
|
continue;
|
|
4676
5173
|
}
|
|
5174
|
+
if(!Object.hasOwn(node.gateway.sensor_libs, sensor.type)){
|
|
5175
|
+
error_msg.syntax_error ||= {};
|
|
5176
|
+
error_msg.syntax_error = {
|
|
5177
|
+
type: 'error',
|
|
5178
|
+
message: `Invalid sensor type ${sensor.type} for sensor ${sensor.addr}. See detail.valid_sensor in this message for a list of valid sensors.`,
|
|
5179
|
+
detail: {
|
|
5180
|
+
"text": "Invlalid sensor type",
|
|
5181
|
+
"received": sensor.type,
|
|
5182
|
+
"help": "The following properties are required for each sensor: addr, type, configs i.e. [{addr: 'sensor_mac_address', type: sensor_type_number, configs: {config_name: desired_value}}]",
|
|
5183
|
+
"valid_sensors": Object.keys(node.gateway.sensor_libs)
|
|
5184
|
+
}
|
|
5185
|
+
};
|
|
5186
|
+
continue;
|
|
5187
|
+
}
|
|
5188
|
+
|
|
4677
5189
|
// Force lowercase for consistency
|
|
4678
5190
|
sensor.addr = sensor.addr.toLowerCase();
|
|
4679
5191
|
// force configs values lowercase for consistency
|
|
@@ -4698,31 +5210,20 @@ module.exports = function(RED) {
|
|
|
4698
5210
|
node._gateway_node.sensor_configs[sensor.addr].type = sensor.type;
|
|
4699
5211
|
_requires_file_update = true;
|
|
4700
5212
|
}
|
|
5213
|
+
|
|
5214
|
+
const config_map = node.gateway.sensor_libs[sensor.type].get_config_map();
|
|
5215
|
+
|
|
4701
5216
|
// Validate configs
|
|
4702
5217
|
for (const config_name in sensor.configs){
|
|
4703
5218
|
// Check config is valid for sensor type
|
|
4704
|
-
if(Object.hasOwn(
|
|
4705
|
-
let map_key =
|
|
4706
|
-
if(Object.hasOwn(
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
message: `Configuration ${config_name} is not supported for sensor type ${sensor.type} for sensor ${sensor.addr}. This configuration is not reported by the sensor and cannot be programmatically set through the configuration node.`,
|
|
4713
|
-
detail: {
|
|
4714
|
-
"text": "Configuration not supported due to reported configurations",
|
|
4715
|
-
"sensor_type": sensor.type,
|
|
4716
|
-
"config_name": config_name,
|
|
4717
|
-
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4718
|
-
}
|
|
4719
|
-
};
|
|
4720
|
-
delete sensor.configs[config_name];
|
|
4721
|
-
continue;
|
|
4722
|
-
}
|
|
4723
|
-
if(Object.hasOwn(node._gateway_node.configuration_map[map_key].validator, 'type')){
|
|
4724
|
-
switch(node._gateway_node.configuration_map[map_key].validator.type){
|
|
4725
|
-
case 'hexString':
|
|
5219
|
+
if(Object.hasOwn(config_map, config_name)){
|
|
5220
|
+
let map_key = config_map[config_name];
|
|
5221
|
+
if(Object.hasOwn(map_key, 'validator')){
|
|
5222
|
+
if(Object.hasOwn(map_key.validator, 'type')){
|
|
5223
|
+
|
|
5224
|
+
// TODO replace with validation_methods object approach for cleaner code
|
|
5225
|
+
switch(map_key.validator.type){
|
|
5226
|
+
case 'hex':
|
|
4726
5227
|
// Remove colons from string
|
|
4727
5228
|
sensor.configs[config_name] = sensor.configs[config_name].replace(/:/g, '');
|
|
4728
5229
|
|
|
@@ -4743,7 +5244,7 @@ module.exports = function(RED) {
|
|
|
4743
5244
|
continue;
|
|
4744
5245
|
}
|
|
4745
5246
|
// Invalid length error
|
|
4746
|
-
if(Object.hasOwn(
|
|
5247
|
+
if(Object.hasOwn(map_key.validator, 'length') && sensor.configs[config_name].length != map_key.validator.length){
|
|
4747
5248
|
error_msg[sensor.addr] ||= {};
|
|
4748
5249
|
error_msg[sensor.addr][config_name] = {
|
|
4749
5250
|
type: 'error',
|
|
@@ -4759,7 +5260,57 @@ module.exports = function(RED) {
|
|
|
4759
5260
|
continue;
|
|
4760
5261
|
}
|
|
4761
5262
|
// Warning for missing length validator
|
|
4762
|
-
if (!Object.hasOwn(
|
|
5263
|
+
if (!Object.hasOwn(map_key.validator, 'length')) {
|
|
5264
|
+
warning_msg[sensor.addr] ||= {};
|
|
5265
|
+
warning_msg[sensor.addr][config_name] = {
|
|
5266
|
+
type: 'warning',
|
|
5267
|
+
message: `No length validator defined for hex string ${config_name} for sensor ${sensor.addr}.`,
|
|
5268
|
+
detail: {
|
|
5269
|
+
"text": "Missing length validator",
|
|
5270
|
+
"type": "hexString",
|
|
5271
|
+
"help": "This warning does not prevent the configuration from going through."
|
|
5272
|
+
}
|
|
5273
|
+
};
|
|
5274
|
+
}
|
|
5275
|
+
break;
|
|
5276
|
+
case 'mac':
|
|
5277
|
+
// Remove colons from string
|
|
5278
|
+
sensor.configs[config_name] = sensor.configs[config_name].replace(/:/g, '');
|
|
5279
|
+
|
|
5280
|
+
// Invalid hex string error
|
|
5281
|
+
if (!/^[0-9a-f]+$/.test(sensor.configs[config_name])) {
|
|
5282
|
+
error_msg[sensor.addr] ||= {};
|
|
5283
|
+
error_msg[sensor.addr][config_name] = {
|
|
5284
|
+
type: 'error',
|
|
5285
|
+
message: `Invalid hex string for configuration ${config_name} for sensor ${sensor.addr}. Received value: ${sensor.configs[config_name]}`,
|
|
5286
|
+
detail: {
|
|
5287
|
+
"text": "Invalid hex string",
|
|
5288
|
+
"regex_validator": "/^[0-9a-f]+$/",
|
|
5289
|
+
"received": sensor.configs[config_name],
|
|
5290
|
+
"help": "Hex string should only contain characters 0-9 and a-f. Colons are removed during validation."
|
|
5291
|
+
}
|
|
5292
|
+
};
|
|
5293
|
+
delete sensor.configs[config_name];
|
|
5294
|
+
continue;
|
|
5295
|
+
}
|
|
5296
|
+
// Invalid length error
|
|
5297
|
+
if(Object.hasOwn(map_key.validator, 'length') && sensor.configs[config_name].length != map_key.validator.length){
|
|
5298
|
+
error_msg[sensor.addr] ||= {};
|
|
5299
|
+
error_msg[sensor.addr][config_name] = {
|
|
5300
|
+
type: 'error',
|
|
5301
|
+
message: `Invalid length for configuration Hex String ${config_name} for sensor ${sensor.addr}. Expected length: ${node._gateway_node.configuration_map[map_key].validator.length}, Received length: ${sensor.configs[config_name].length}`,
|
|
5302
|
+
detail: {
|
|
5303
|
+
"text": "Invalid length for hex string",
|
|
5304
|
+
"expected_length": node._gateway_node.configuration_map[map_key].validator.length,
|
|
5305
|
+
"received_length": sensor.configs[config_name].length,
|
|
5306
|
+
"help": "Add leading or trailing zeros to meet length requirement."
|
|
5307
|
+
}
|
|
5308
|
+
};
|
|
5309
|
+
delete sensor.configs[config_name];
|
|
5310
|
+
continue;
|
|
5311
|
+
}
|
|
5312
|
+
// Warning for missing length validator
|
|
5313
|
+
if (!Object.hasOwn(map_key.validator, 'length')) {
|
|
4763
5314
|
warning_msg[sensor.addr] ||= {};
|
|
4764
5315
|
warning_msg[sensor.addr][config_name] = {
|
|
4765
5316
|
type: 'warning',
|
|
@@ -4794,14 +5345,14 @@ module.exports = function(RED) {
|
|
|
4794
5345
|
continue;
|
|
4795
5346
|
}
|
|
4796
5347
|
// Value below minimum error
|
|
4797
|
-
if(Object.hasOwn(
|
|
5348
|
+
if(Object.hasOwn(map_key.validator, 'min') && sensor.configs[config_name] < map_key.validator.min){
|
|
4798
5349
|
error_msg[sensor.addr] ||= {};
|
|
4799
5350
|
error_msg[sensor.addr][config_name] = {
|
|
4800
5351
|
type: 'error',
|
|
4801
5352
|
message: `Invalid value for configuration ${config_name} for sensor ${sensor.addr}. Value ${sensor.configs[config_name]} is less than minimum allowed value of ${node._gateway_node.configuration_map[map_key].validator.min}`,
|
|
4802
5353
|
detail: {
|
|
4803
5354
|
"text": "Value below minimum",
|
|
4804
|
-
"min_allowed":
|
|
5355
|
+
"min_allowed": map_key.validator.min,
|
|
4805
5356
|
"received": sensor.configs[config_name],
|
|
4806
5357
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4807
5358
|
}
|
|
@@ -4811,14 +5362,14 @@ module.exports = function(RED) {
|
|
|
4811
5362
|
// return {error: `Invalid value for configuration ${config_name} for sensor ${sensor.addr}. Value ${sensor.configs[config_name]} is less than minimum allowed value of ${node.configuration_map[map_key].validator.min}`};
|
|
4812
5363
|
}
|
|
4813
5364
|
// Value above maximum error
|
|
4814
|
-
if(Object.hasOwn(
|
|
5365
|
+
if(Object.hasOwn(map_key.validator, 'max') && sensor.configs[config_name] > map_key.validator.max){
|
|
4815
5366
|
error_msg[sensor.addr] ||= {};
|
|
4816
5367
|
error_msg[sensor.addr][config_name] = {
|
|
4817
5368
|
type: 'error',
|
|
4818
5369
|
message: `Invalid value for configuration ${config_name} for sensor ${sensor.addr}. Value ${sensor.configs[config_name]} is greater than maximum allowed value of ${node._gateway_node.configuration_map[map_key].validator.max}`,
|
|
4819
5370
|
detail: {
|
|
4820
5371
|
"text": "Value above maximum",
|
|
4821
|
-
"max_allowed":
|
|
5372
|
+
"max_allowed": map_key.validator.max,
|
|
4822
5373
|
"received": sensor.configs[config_name],
|
|
4823
5374
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4824
5375
|
}
|
|
@@ -4828,7 +5379,7 @@ module.exports = function(RED) {
|
|
|
4828
5379
|
// return {error: `Invalid value for configuration ${config_name} for sensor ${sensor.addr}. Value ${sensor.configs[config_name]} is greater than maximum allowed value of ${node.configuration_map[map_key].validator.max}`};
|
|
4829
5380
|
}
|
|
4830
5381
|
// Warning for missing min/max validators
|
|
4831
|
-
if(!Object.hasOwn(
|
|
5382
|
+
if(!Object.hasOwn(map_key.validator, 'min') || !Object.hasOwn(map_key.validator, 'max')){
|
|
4832
5383
|
warning_msg[sensor.addr] ||= {};
|
|
4833
5384
|
warning_msg[sensor.addr][config_name] = {
|
|
4834
5385
|
type: 'warning',
|
|
@@ -4843,15 +5394,15 @@ module.exports = function(RED) {
|
|
|
4843
5394
|
}
|
|
4844
5395
|
// If options exist, value must be one of the options
|
|
4845
5396
|
// This is assuming that all configs with options are number types
|
|
4846
|
-
if(Object.hasOwn(
|
|
4847
|
-
if(!Object.keys(
|
|
5397
|
+
if(Object.hasOwn(map_key, 'options')){
|
|
5398
|
+
if(!Object.keys(map_key.options).includes(String(sensor.configs[config_name]))){
|
|
4848
5399
|
error_msg[sensor.addr] ||= {};
|
|
4849
5400
|
error_msg[sensor.addr][config_name] = {
|
|
4850
5401
|
type: 'error',
|
|
4851
5402
|
message: `Invalid option for configuration ${config_name} for sensor ${sensor.addr}. Received value: ${sensor.configs[config_name]}`,
|
|
4852
5403
|
detail: {
|
|
4853
5404
|
"text": "Invalid option",
|
|
4854
|
-
"valid_options":
|
|
5405
|
+
"valid_options": map_key.options,
|
|
4855
5406
|
"received": sensor.configs[config_name],
|
|
4856
5407
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4857
5408
|
}
|
|
@@ -4933,29 +5484,78 @@ module.exports = function(RED) {
|
|
|
4933
5484
|
if(_requires_file_update){
|
|
4934
5485
|
node._gateway_node.store_sensor_configs(JSON.stringify(node._gateway_node.sensor_configs));
|
|
4935
5486
|
}
|
|
4936
|
-
console.log(Object.keys(warning_msg).length);
|
|
5487
|
+
// console.log(Object.keys(warning_msg).length);
|
|
4937
5488
|
if(Object.keys(warning_msg).length){
|
|
4938
5489
|
response.warnings = warning_msg;
|
|
4939
5490
|
}
|
|
4940
|
-
console.log(Object.keys(error_msg).length);
|
|
5491
|
+
// console.log(Object.keys(error_msg).length);
|
|
4941
5492
|
if(Object.keys(error_msg).length){
|
|
4942
5493
|
response.errors = error_msg;
|
|
4943
5494
|
}
|
|
4944
5495
|
return response;
|
|
4945
5496
|
};
|
|
4946
5497
|
|
|
4947
|
-
node.gateway.on('sensor_mode', (d) => {
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
5498
|
+
// node.gateway.on('sensor_mode', (d) => {
|
|
5499
|
+
// if(d.mode == 'FLY'){
|
|
5500
|
+
// if(Object.hasOwn(node._gateway_node.sensor_configs, d.mac) && Object.hasOwn(node._gateway_node.sensor_configs[d.mac], 'api_config_override')){
|
|
5501
|
+
// node.send({topic: 'sensor_report', payload: node._gateway_node.sensor_configs[d.mac], addr: d.mac, time: Date.now()});
|
|
5502
|
+
// }
|
|
5503
|
+
// }else if(d.mode == 'OTF'){
|
|
5504
|
+
// if(Object.hasOwn(node._gateway_node.sensor_configs, d.mac) && Object.hasOwn(node._gateway_node.sensor_configs[d.mac], 'api_config_override')){
|
|
5505
|
+
// node.send({topic: 'post_update_sensor_report', payload: node._gateway_node.sensor_configs[d.mac], addr: d.mac, time: Date.now()});
|
|
5506
|
+
// }
|
|
5507
|
+
// }
|
|
5508
|
+
// });
|
|
5509
|
+
|
|
5510
|
+
node.gateway.on('sync', (d) => {
|
|
5511
|
+
switch (d.payload.type){
|
|
5512
|
+
case 'sync_check_in':
|
|
5513
|
+
// node.set_status();
|
|
5514
|
+
node.send({
|
|
5515
|
+
'topic': 'sync',
|
|
5516
|
+
'type': d.payload.type,
|
|
5517
|
+
...d,
|
|
5518
|
+
'time': Date.now()
|
|
5519
|
+
});
|
|
5520
|
+
break;
|
|
5521
|
+
case 'sync_init':
|
|
5522
|
+
// node.set_status();
|
|
5523
|
+
node.send({
|
|
5524
|
+
'topic': 'sync',
|
|
5525
|
+
'type': d.payload.type,
|
|
5526
|
+
...d,
|
|
5527
|
+
'time': Date.now()
|
|
5528
|
+
});
|
|
5529
|
+
break;
|
|
5530
|
+
case 'sync_end':
|
|
5531
|
+
// node.set_status();
|
|
5532
|
+
node.send({
|
|
5533
|
+
'topic': 'sync',
|
|
5534
|
+
'type': d.payload.type,
|
|
5535
|
+
...d,
|
|
5536
|
+
'time': Date.now()
|
|
5537
|
+
});
|
|
5538
|
+
break;
|
|
5539
|
+
case 'manual_sync_check_in':
|
|
5540
|
+
// node.set_status();
|
|
5541
|
+
node.send({
|
|
5542
|
+
'topic': 'sync',
|
|
5543
|
+
'type': d.payload.type,
|
|
5544
|
+
...d,
|
|
5545
|
+
'time': Date.now()
|
|
5546
|
+
});
|
|
5547
|
+
break;
|
|
5548
|
+
case 'sync_acknowledgment':
|
|
5549
|
+
// node.set_status();
|
|
5550
|
+
node.send({
|
|
5551
|
+
'topic': 'sync',
|
|
5552
|
+
'type': d.payload.type,
|
|
5553
|
+
...d,
|
|
5554
|
+
'time': Date.now()
|
|
5555
|
+
});
|
|
5556
|
+
break;
|
|
4956
5557
|
}
|
|
4957
5558
|
});
|
|
4958
|
-
|
|
4959
5559
|
node._gateway_node.on('config_node_msg', (d) => {
|
|
4960
5560
|
node.send(d);
|
|
4961
5561
|
});
|
|
@@ -4967,13 +5567,14 @@ module.exports = function(RED) {
|
|
|
4967
5567
|
node._gateway_node.removeAllListeners('config_node_msg');
|
|
4968
5568
|
node._gateway_node.removeAllListeners('config_node_error');
|
|
4969
5569
|
node._gateway_node.removeAllListeners('sensor_mode');
|
|
5570
|
+
node._gateway_node.removeAllListeners('sync');
|
|
4970
5571
|
done();
|
|
4971
5572
|
});
|
|
4972
|
-
|
|
4973
5573
|
|
|
4974
5574
|
this.get_all_sensor_info = function(){
|
|
4975
5575
|
return node._gateway_node.sensor_configs;
|
|
4976
5576
|
};
|
|
5577
|
+
|
|
4977
5578
|
this.get_sensor_array_info = function(sensor_array){
|
|
4978
5579
|
let response = {
|
|
4979
5580
|
status: 0,
|