@ncd-io/node-red-enterprise-sensors 1.6.4 → 2.0.1
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 +2331 -4547
- package/lib/sensors/1.js +230 -0
- package/lib/sensors/103.js +1039 -0
- package/lib/sensors/110.js +1320 -0
- package/lib/sensors/111.js +1621 -0
- package/lib/sensors/114.js +1388 -0
- package/lib/sensors/125.js +631 -0
- package/lib/sensors/126.js +695 -0
- 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/lib/utils.js +27 -0
- package/package.json +44 -41
- package/wireless.html +480 -82
- package/wireless.js +916 -219
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) {
|
|
@@ -28,8 +30,6 @@ module.exports = function(RED) {
|
|
|
28
30
|
const configuration_map_location = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/data/configuration_map.json';
|
|
29
31
|
const sensor_type_map_location = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/data/sensor_type_map.json';
|
|
30
32
|
|
|
31
|
-
this.config_node_capable = [114];
|
|
32
|
-
|
|
33
33
|
// comms_timer object var added to clear the time to prevent issues with rapid redeploy
|
|
34
34
|
this.comms_timer;
|
|
35
35
|
|
|
@@ -134,114 +134,186 @@ module.exports = function(RED) {
|
|
|
134
134
|
node.gateway.digi.serial.reconnect();
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
|
-
//
|
|
137
|
+
// Listen for FLY messages to run FOTA updates on older FLY messages
|
|
138
138
|
node.gateway.on('sensor_mode', (d) => {
|
|
139
|
-
if(d.mode == "FLY"
|
|
139
|
+
if(d.mode == "FLY" && !Object.hasOwn(d, 'sync')){
|
|
140
140
|
if(Object.hasOwn(node.sensor_list, d.mac) && Object.hasOwn(node.sensor_list[d.mac], 'update_request') && d.mode == "FLY"){
|
|
141
141
|
node.request_manifest(d.mac);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
// Event listener to make sure this only triggers once no matter how many gateway nodes there are
|
|
146
|
+
node.gateway.on('sync', (d) => {
|
|
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;
|
|
148
158
|
|
|
159
|
+
const payload = { ...remaining, ...actual_values, sensor_type };
|
|
160
|
+
|
|
161
|
+
if(Object.hasOwn(node.sensor_list, addr) && Object.hasOwn(node.sensor_list[addr], 'update_request')){
|
|
162
|
+
node.request_manifest(addr);
|
|
163
|
+
}else if(Object.hasOwn(this.gateway.sensor_libs, sensor_type)){
|
|
164
|
+
// API CONFIGURATION NODE
|
|
165
|
+
// let values = d.reported_config.machine_values;
|
|
166
|
+
const config_map = this.gateway.sensor_libs[sensor_type].get_config_map(payload.firmware_version);
|
|
149
167
|
let store_flag = false;
|
|
150
168
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
+
};
|
|
154
193
|
}
|
|
155
|
-
|
|
156
|
-
if(!Object.hasOwn(node.sensor_configs
|
|
157
|
-
node.sensor_configs[
|
|
194
|
+
|
|
195
|
+
if(!Object.hasOwn(node.sensor_configs, addr)){
|
|
196
|
+
node.sensor_configs[addr] = {};
|
|
158
197
|
store_flag = true;
|
|
159
198
|
}
|
|
160
|
-
|
|
199
|
+
|
|
200
|
+
// delete so we don't have to consider it for storage
|
|
201
|
+
// TODO re-add, but remove from storage consideration for mapping
|
|
202
|
+
// if(Object.hasOwn(d.payload, 'tx_lifetime_counter')){
|
|
203
|
+
// delete d.payload.tx_lifetime_counter;
|
|
204
|
+
// }
|
|
205
|
+
|
|
206
|
+
// Store hardware_id outside of reported_configs
|
|
207
|
+
// if(!Object.hasOwn(node.sensor_configs[addr], 'hardware_id') && Object.hasOwn(d.payload, 'hardware_id')){
|
|
208
|
+
// node.sensor_configs[addr].hardware_id = d.payload.hardware_id;
|
|
209
|
+
// delete d.payload.hardware_id;
|
|
210
|
+
// store_flag = true;
|
|
211
|
+
// }
|
|
212
|
+
|
|
213
|
+
// Store core_version outside of reported_configs
|
|
214
|
+
// if(Object.hasOwn(d.payload, 'core_version')){
|
|
215
|
+
// node.sensor_configs[addr].core_version = d.payload.core_version;
|
|
216
|
+
// store_flag = true;
|
|
217
|
+
// }
|
|
218
|
+
|
|
161
219
|
// Loop through and translate and validate values.
|
|
162
220
|
// We want to allow passing in integers instead of byte arrays etc.
|
|
163
221
|
// 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;
|
|
222
|
+
// values.network_id = config.pan_id;
|
|
223
|
+
// if(Object.hasOwn(d, 'node_id')){
|
|
224
|
+
// values.node_id = d.nodeId;
|
|
225
|
+
// }
|
|
226
|
+
for(let key in payload){
|
|
227
|
+
if(Object.hasOwn(config_map, key)){
|
|
228
|
+
if(!Object.hasOwn(config_map[key], 'write_index')){
|
|
229
|
+
// TODO
|
|
230
|
+
if(!Object.hasOwn(node.sensor_configs[addr], key) || Object.hasOwn(node.sensor_configs[addr], key) && node.sensor_configs[addr][key] != payload[key]){
|
|
231
|
+
// console.log('Config '+key+' is read only, moving from payload');
|
|
232
|
+
node.sensor_configs[addr][key] = payload[key];
|
|
233
|
+
if(key !== 'tx_lifetime_counter'){
|
|
234
|
+
store_flag = true;
|
|
191
235
|
}
|
|
192
236
|
}
|
|
237
|
+
delete payload[key];
|
|
193
238
|
}
|
|
239
|
+
}else{
|
|
240
|
+
// console.log('Not in config map, deleting key: '+key);
|
|
241
|
+
delete payload[key];
|
|
194
242
|
}
|
|
195
243
|
}
|
|
196
244
|
// If object has no reported configs, instantiate them
|
|
197
|
-
if(!Object.hasOwn(node.sensor_configs[
|
|
198
|
-
node.sensor_configs[d.mac].reported_configs = {};
|
|
245
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'reported_configs')){
|
|
246
|
+
// node.sensor_configs[d.mac].reported_configs = {};
|
|
247
|
+
node.sensor_configs[addr].reported_configs = payload;
|
|
199
248
|
store_flag = true;
|
|
200
249
|
}
|
|
201
250
|
// 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()});
|
|
251
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'desired_configs')){
|
|
252
|
+
node.sensor_configs[addr].desired_configs = payload;
|
|
214
253
|
store_flag = true;
|
|
215
254
|
}
|
|
216
|
-
|
|
255
|
+
|
|
256
|
+
// We're setting sensor_type above, so we can remove this.
|
|
257
|
+
// if(!Object.hasOwn(node.sensor_configs[addr], 'type')){
|
|
258
|
+
// node.sensor_configs[addr].type = d.type;
|
|
259
|
+
// store_flag = true;
|
|
260
|
+
// }else if(node.sensor_configs[d.mac].type != d.type){
|
|
261
|
+
// // 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
|
|
262
|
+
// delete node.sensor_configs[d.mac].desired_configs;
|
|
263
|
+
// node.sensor_configs[d.mac].type = d.type;
|
|
264
|
+
// 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()});
|
|
265
|
+
// store_flag = true;
|
|
266
|
+
// }
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if(!isDeepStrictEqual(node.sensor_configs[addr].reported_configs, payload)){
|
|
217
270
|
// Values are different, update the stored configs and write to file
|
|
218
|
-
node.sensor_configs[
|
|
271
|
+
node.sensor_configs[addr].reported_configs = payload;
|
|
219
272
|
// If reported configs change, but the auto config does not control configs, update automatically
|
|
220
273
|
// 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[
|
|
274
|
+
if(!Object.hasOwn(node.sensor_configs[addr], 'api_config_override')){
|
|
275
|
+
node.sensor_configs[addr].desired_configs = payload;
|
|
223
276
|
}
|
|
224
277
|
store_flag = true;
|
|
225
|
-
node._emitter.emit('config_node_msg', {topic: 'sensor_configs_update', payload: node.sensor_configs[
|
|
278
|
+
node._emitter.emit('config_node_msg', {topic: 'sensor_configs_update', payload: node.sensor_configs[addr], address: addr, time: Date.now()});
|
|
226
279
|
// node.send({topic: 'sensor_configs_update', payload: node.sensor_configs[d.mac], time: Date.now()});
|
|
227
280
|
}
|
|
228
281
|
|
|
229
|
-
if(
|
|
230
|
-
|
|
231
|
-
if(
|
|
232
|
-
|
|
282
|
+
if(type == 'sync_check_in'){
|
|
283
|
+
// TODO add backwards compatibility
|
|
284
|
+
if(config.enable_fly_compatibility){
|
|
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});
|
|
287
|
+
}
|
|
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)){
|
|
233
289
|
store_flag = true;
|
|
234
290
|
var tout = setTimeout(() => {
|
|
235
|
-
|
|
291
|
+
node.configure(d.address, d.payload.sensor_type);
|
|
292
|
+
// this.sync_init(addr, sensor_type);
|
|
236
293
|
}, 100);
|
|
237
294
|
}
|
|
295
|
+
}else if(type == 'manual_sync_check_in'){
|
|
296
|
+
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)){
|
|
297
|
+
node.configure(addr, sensor_type);
|
|
298
|
+
}
|
|
299
|
+
}else if(type == 'sync_end'){
|
|
300
|
+
if(config.enable_fly_compatibility){
|
|
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});
|
|
303
|
+
}
|
|
238
304
|
}
|
|
239
305
|
if(store_flag){
|
|
240
306
|
node.store_sensor_configs(JSON.stringify(node.sensor_configs));
|
|
241
307
|
}
|
|
242
308
|
}
|
|
243
|
-
}else if(d.
|
|
244
|
-
|
|
309
|
+
}else if(d.type == 'sync_init'){
|
|
310
|
+
if(config.enable_fly_compatibility){
|
|
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});
|
|
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
|
+
// }
|
|
245
317
|
}
|
|
246
318
|
});
|
|
247
319
|
node.gateway.on('manifest_received', (manifest_data) => {
|
|
@@ -327,6 +399,58 @@ module.exports = function(RED) {
|
|
|
327
399
|
}
|
|
328
400
|
};
|
|
329
401
|
|
|
402
|
+
this.sync_init = function(addr, type){
|
|
403
|
+
// console.log('!!!! Sync Init for sensor '+addr);
|
|
404
|
+
return new Promise((top_fulfill, top_reject) => {
|
|
405
|
+
var msg = {};
|
|
406
|
+
setTimeout(() => {
|
|
407
|
+
var tout = setTimeout(() => {
|
|
408
|
+
// switch to emitter for this
|
|
409
|
+
// node.status(modes.PGM_ERR);
|
|
410
|
+
// node.send({topic: 'OTN Request Results', payload: msg, time: Date.now()});
|
|
411
|
+
console.log('Sync Request Timed Out');
|
|
412
|
+
}, 10000);
|
|
413
|
+
|
|
414
|
+
var promises = {};
|
|
415
|
+
// This command is used for OTF on types 53, 80,81,82,83,84, 101, 102, 110, 111, 518, 519
|
|
416
|
+
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];
|
|
417
|
+
if(original_otf_devices.includes(type)){
|
|
418
|
+
console.log('!!!! Entering Sync mode with original command');
|
|
419
|
+
// This command is used for OTF on types 53, 80, 81, 82, 83, 84, 101, 102, 110, 111, 518, 519
|
|
420
|
+
promises.config_enter_otn_mode = node.gateway.config_enter_otn_mode(addr);
|
|
421
|
+
}else{
|
|
422
|
+
console.log('!!!! Entering Sync mode with other command');
|
|
423
|
+
// This command is used for OTF on types not 53, 80, 81, 82, 83, 84, 101, 102, 110, 111, 518, 519
|
|
424
|
+
promises.config_enter_otn_mode = node.gateway.config_enter_otn_mode_common(addr);
|
|
425
|
+
}
|
|
426
|
+
promises.finish = new Promise((fulfill, reject) => {
|
|
427
|
+
node.gateway.queue.add(() => {
|
|
428
|
+
return new Promise((f, r) => {
|
|
429
|
+
clearTimeout(tout);
|
|
430
|
+
// node.status(modes.FLY);
|
|
431
|
+
fulfill();
|
|
432
|
+
f();
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
for(var i in promises){
|
|
437
|
+
(function(name){
|
|
438
|
+
promises[name].then((f) => {
|
|
439
|
+
if(name != 'finish') msg[name] = true;
|
|
440
|
+
else{
|
|
441
|
+
// #OTF
|
|
442
|
+
node.send({topic: 'OTN Request Results', payload: msg, time: Date.now()});
|
|
443
|
+
top_fulfill(msg);
|
|
444
|
+
}
|
|
445
|
+
}).catch((err) => {
|
|
446
|
+
msg[name] = err;
|
|
447
|
+
});
|
|
448
|
+
})(i);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
};
|
|
453
|
+
|
|
330
454
|
this.get_required_configs = function(desired_configs, reported_configs){
|
|
331
455
|
const mismatched = {};
|
|
332
456
|
for (const key in desired_configs) {
|
|
@@ -340,8 +464,15 @@ module.exports = function(RED) {
|
|
|
340
464
|
return mismatched;
|
|
341
465
|
};
|
|
342
466
|
|
|
343
|
-
|
|
344
|
-
|
|
467
|
+
this.sync_check_reboot = function(addr){
|
|
468
|
+
if(node.sensor_configs[addr].reported_configs.network_id != node.sensor_configs[addr].desired_configs.network_id){
|
|
469
|
+
return true;
|
|
470
|
+
}else{
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
this.configure = function(addr, type){
|
|
345
476
|
return new Promise((top_fulfill, top_reject) => {
|
|
346
477
|
var success = {};
|
|
347
478
|
setTimeout(() => {
|
|
@@ -352,50 +483,23 @@ module.exports = function(RED) {
|
|
|
352
483
|
// node.send({topic: 'Config Results', payload: success, time: Date.now(), addr: sensor.mac});
|
|
353
484
|
}, 60000);
|
|
354
485
|
// node.status(modes.PGM_NOW);
|
|
355
|
-
var mac =
|
|
486
|
+
var mac = addr;
|
|
356
487
|
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
|
-
}
|
|
488
|
+
var reboot = this.sync_check_reboot(addr);
|
|
489
|
+
|
|
490
|
+
promises.sync_command = node.gateway.send_sync_configs(addr, node.sensor_configs[addr]);
|
|
387
491
|
|
|
388
492
|
// These sensors listed in original_otf_devices use a different OTF code.
|
|
389
493
|
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
494
|
// If we changed the network ID reboot the sensor to take effect.
|
|
391
495
|
// TODO if we add the encryption key command to node-red we need to reboot for it as well.
|
|
392
496
|
if(reboot){
|
|
393
|
-
promises.reboot_sensor = node.gateway.config_reboot_sensor(
|
|
497
|
+
promises.reboot_sensor = node.gateway.config_reboot_sensor(addr);
|
|
394
498
|
} else {
|
|
395
|
-
if(original_otf_devices.includes(
|
|
396
|
-
promises.exit_otn_mode = node.gateway.config_exit_otn_mode(
|
|
499
|
+
if(original_otf_devices.includes(type)){
|
|
500
|
+
promises.exit_otn_mode = node.gateway.config_exit_otn_mode(addr);
|
|
397
501
|
}else{
|
|
398
|
-
promises.config_exit_otn_mode_common = node.gateway.config_exit_otn_mode_common(
|
|
502
|
+
promises.config_exit_otn_mode_common = node.gateway.config_exit_otn_mode_common(addr);
|
|
399
503
|
}
|
|
400
504
|
}
|
|
401
505
|
promises.finish = new Promise((fulfill, reject) => {
|
|
@@ -416,7 +520,6 @@ module.exports = function(RED) {
|
|
|
416
520
|
switch(f.result){
|
|
417
521
|
case 255:
|
|
418
522
|
success[name] = true;
|
|
419
|
-
delete node.sensor_configs[mac].temp_required_configs[name];
|
|
420
523
|
break;
|
|
421
524
|
default:
|
|
422
525
|
success[name] = {
|
|
@@ -442,7 +545,7 @@ module.exports = function(RED) {
|
|
|
442
545
|
// TODO turn into event emitter.
|
|
443
546
|
node._emitter.emit('config_node_msg', {topic: 'Config Results', payload: success, addr: mac, time: Date.now()});
|
|
444
547
|
// node.send({topic: 'Config Results', payload: success, time: Date.now(), addr: mac});
|
|
445
|
-
top_fulfill(success);
|
|
548
|
+
// top_fulfill(success);
|
|
446
549
|
}
|
|
447
550
|
}).catch((err) => {
|
|
448
551
|
success[name] = err;
|
|
@@ -903,6 +1006,7 @@ module.exports = function(RED) {
|
|
|
903
1006
|
this.gateway._emitter.removeAllListeners('link_info');
|
|
904
1007
|
this.gateway._emitter.removeAllListeners('converter_response');
|
|
905
1008
|
this.gateway._emitter.removeAllListeners('manifest_received');
|
|
1009
|
+
this.gateway._emitter.removeAllListeners('sync');
|
|
906
1010
|
// console.log(this.gateway._emitter.eventNames());
|
|
907
1011
|
});
|
|
908
1012
|
|
|
@@ -1278,6 +1382,28 @@ module.exports = function(RED) {
|
|
|
1278
1382
|
node.set_status();
|
|
1279
1383
|
node.send({topic: 'sensor_data', payload: d, time: Date.now()});
|
|
1280
1384
|
});
|
|
1385
|
+
node.gateway.on('sync', (d) => {
|
|
1386
|
+
switch (d.payload.type){
|
|
1387
|
+
case 'sync_check_in':
|
|
1388
|
+
node.set_status();
|
|
1389
|
+
node.send({
|
|
1390
|
+
'topic': 'sync',
|
|
1391
|
+
'type': d.payload.type,
|
|
1392
|
+
...d,
|
|
1393
|
+
'time': Date.now()
|
|
1394
|
+
});
|
|
1395
|
+
break;
|
|
1396
|
+
case 'sync_init':
|
|
1397
|
+
node.set_status();
|
|
1398
|
+
node.send({
|
|
1399
|
+
'topic': 'sync',
|
|
1400
|
+
'type': d.payload.type,
|
|
1401
|
+
...d,
|
|
1402
|
+
'time': Date.now()
|
|
1403
|
+
});
|
|
1404
|
+
break;
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1281
1407
|
node.gateway.on('sensor_mode', (d) => {
|
|
1282
1408
|
node.set_status();
|
|
1283
1409
|
node.send({topic: 'sensor_mode', payload: d, time: Date.now()});
|
|
@@ -1329,6 +1455,10 @@ module.exports = function(RED) {
|
|
|
1329
1455
|
this.config_gateway = this.config_gateway_node.gateway;
|
|
1330
1456
|
dedicated_config = true;
|
|
1331
1457
|
}
|
|
1458
|
+
this.config_sync_listener;
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
|
|
1332
1462
|
// this.queue = new Queue(1);
|
|
1333
1463
|
var node = this;
|
|
1334
1464
|
var modes = {
|
|
@@ -1344,6 +1474,8 @@ module.exports = function(RED) {
|
|
|
1344
1474
|
// OTN: {fill:"yellow",shape:"ring",text:"OTN Received, OTF Configuration Initiated"},
|
|
1345
1475
|
// OFF: {fill:"green",shape:"dot",text:"OFF Recieved, OTF Configuration Completed"}
|
|
1346
1476
|
FLY: {fill:"yellow",shape:"ring",text:"FLY"},
|
|
1477
|
+
INI: {fill:"yellow",shape:"ring",text:"Sync-Init"},
|
|
1478
|
+
END: {fill:"yellow",shape:"ring",text:"Sync-End"},
|
|
1347
1479
|
OTN: {fill:"yellow",shape:"ring",text:"OTN Received, Config Entered"},
|
|
1348
1480
|
OTF: {fill:"green",shape:"dot",text:"OTF Received, Config Complete"},
|
|
1349
1481
|
UPTHWRN: {fill:"yellow",shape:"ring",text:"Threshold is low"}
|
|
@@ -1842,29 +1974,119 @@ module.exports = function(RED) {
|
|
|
1842
1974
|
}
|
|
1843
1975
|
break;
|
|
1844
1976
|
case 33:
|
|
1845
|
-
if(config.
|
|
1846
|
-
promises.
|
|
1977
|
+
if(config.debounce_time_108_active){
|
|
1978
|
+
promises.debounce_time_33 = node.config_gateway.config_set_debounce_time_108(mac, parseInt(config.debounce_time_108));
|
|
1847
1979
|
}
|
|
1848
1980
|
if(config.input_two_33_active){
|
|
1849
|
-
promises.
|
|
1981
|
+
promises.input_detection_33 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_33));
|
|
1982
|
+
}
|
|
1983
|
+
if(config.debounce_time_123_active){
|
|
1984
|
+
promises.debounce_time_2byte_33 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
1850
1985
|
}
|
|
1851
1986
|
if(config.counter_threshold_108_active){
|
|
1852
|
-
promises.
|
|
1987
|
+
promises.counter_threshold_33 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
1853
1988
|
}
|
|
1854
|
-
if(config.
|
|
1855
|
-
promises.
|
|
1989
|
+
if(config.transmission_interval_108_active){
|
|
1990
|
+
promises.transmission_interval_33 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
1856
1991
|
}
|
|
1857
|
-
if(config.
|
|
1858
|
-
promises.
|
|
1992
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
1993
|
+
promises.reset_mode_33 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
1859
1994
|
}
|
|
1860
|
-
|
|
1995
|
+
if(config.reset_timeout_108_active){
|
|
1996
|
+
promises.reset_timeout_33 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
1997
|
+
}
|
|
1998
|
+
if(config.shift_one_108_active){
|
|
1999
|
+
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));
|
|
2000
|
+
}
|
|
2001
|
+
if(config.shift_two_108_active){
|
|
2002
|
+
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));
|
|
2003
|
+
}
|
|
2004
|
+
if(config.shift_three_108_active){
|
|
2005
|
+
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));
|
|
2006
|
+
}
|
|
2007
|
+
if(config.shift_four_108_active){
|
|
2008
|
+
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));
|
|
2009
|
+
}
|
|
2010
|
+
if(config.quality_of_service_108_active){
|
|
2011
|
+
promises.quality_of_service_33 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
2012
|
+
}
|
|
2013
|
+
if(config.rtc_108){
|
|
2014
|
+
promises.rtc_33 = node.config_gateway.config_set_rtc_108(mac);
|
|
2015
|
+
}
|
|
2016
|
+
if(config.clear_timers_35){
|
|
2017
|
+
promises.clear_counters_33 = node.config_gateway.config_set_clear_timers_35(mac);
|
|
2018
|
+
}
|
|
2019
|
+
if(config.push_notification_35_active){
|
|
2020
|
+
promises.push_notification_33 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_35));
|
|
2021
|
+
}
|
|
2022
|
+
if(config.interrupt_timeout_35_active){
|
|
2023
|
+
promises.interrupt_timeout_33 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_35));
|
|
2024
|
+
}
|
|
2025
|
+
if(config.probe_one_126_active){
|
|
2026
|
+
promises.probe_one_33 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
2027
|
+
}
|
|
2028
|
+
if(config.threshold_probe_one_126_active){
|
|
2029
|
+
promises.threshold_probe_one_33 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
2030
|
+
}
|
|
2031
|
+
break;
|
|
1861
2032
|
case 35:
|
|
1862
2033
|
if(config.counter_threshold_35_active){
|
|
1863
2034
|
promises.config_set_counter_threshold_35 = node.config_gateway.config_set_counter_threshold_35(mac, parseInt(config.counter_threshold_35));
|
|
1864
2035
|
}
|
|
2036
|
+
if(config.counter_threshold_35_gen2_active){
|
|
2037
|
+
promises.config_set_counter_threshold_35_gen2 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_35_gen2));
|
|
2038
|
+
}
|
|
1865
2039
|
if(config.debounce_time_2_active){
|
|
1866
2040
|
promises.config_set_debounce_time_35 = node.config_gateway.config_set_debounce_time_35(mac, parseInt(config.debounce_time_2));
|
|
1867
2041
|
}
|
|
2042
|
+
if(config.debounce_time_123_active){
|
|
2043
|
+
promises.debounce_time_35 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
2044
|
+
}
|
|
2045
|
+
if(config.input_one_123_active){
|
|
2046
|
+
promises.input_one_35 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
2047
|
+
}
|
|
2048
|
+
if(config.counter_threshold_108_active){
|
|
2049
|
+
promises.counter_threshold_35 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
2050
|
+
}
|
|
2051
|
+
if(config.reset_timeout_108_active){
|
|
2052
|
+
promises.reset_timeout_35 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
2053
|
+
}
|
|
2054
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
2055
|
+
promises.reset_mode_35 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
2056
|
+
}
|
|
2057
|
+
if(config.rtc_108){
|
|
2058
|
+
promises.rtc_35 = node.config_gateway.config_set_rtc_108(mac);
|
|
2059
|
+
}
|
|
2060
|
+
if(config.transmission_interval_108_active){
|
|
2061
|
+
promises.transmission_interval_35 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
2062
|
+
}
|
|
2063
|
+
if(config.shift_one_108_active){
|
|
2064
|
+
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));
|
|
2065
|
+
}
|
|
2066
|
+
if(config.shift_two_108_active){
|
|
2067
|
+
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));
|
|
2068
|
+
}
|
|
2069
|
+
if(config.shift_three_108_active){
|
|
2070
|
+
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));
|
|
2071
|
+
}
|
|
2072
|
+
if(config.shift_four_108_active){
|
|
2073
|
+
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));
|
|
2074
|
+
}
|
|
2075
|
+
if(config.quality_of_service_108_active){
|
|
2076
|
+
promises.quality_of_service_35 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
2077
|
+
}
|
|
2078
|
+
if(config.fly_interval_108_active){
|
|
2079
|
+
promises.fly_interval_35 = node.config_gateway.config_set_fly_interval_108(mac, parseInt(config.fly_interval_108));
|
|
2080
|
+
}
|
|
2081
|
+
if(config.clear_timers_35){
|
|
2082
|
+
promises.clear_timers_35 = node.config_gateway.config_set_clear_timers_35(mac);
|
|
2083
|
+
}
|
|
2084
|
+
if(config.push_notification_35_active){
|
|
2085
|
+
promises.push_notification_35 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_35));
|
|
2086
|
+
}
|
|
2087
|
+
if(config.interrupt_timeout_35_active){
|
|
2088
|
+
promises.interrupt_timeout_35 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_35));
|
|
2089
|
+
}
|
|
1868
2090
|
break;
|
|
1869
2091
|
case 36:
|
|
1870
2092
|
if(config.counter_threshold_35_active){
|
|
@@ -2451,6 +2673,11 @@ module.exports = function(RED) {
|
|
|
2451
2673
|
promises.sensor_boot_time_78 = node.config_gateway.config_set_sensor_boot_time_78(mac, parseInt(config.sensor_boot_time_78));
|
|
2452
2674
|
}
|
|
2453
2675
|
break;
|
|
2676
|
+
case 93:
|
|
2677
|
+
if(config.sensor_boot_time_78_active){
|
|
2678
|
+
promises.sensor_boot_time_93 = node.config_gateway.config_set_sensor_boot_time_78(mac, parseInt(config.sensor_boot_time_78));
|
|
2679
|
+
}
|
|
2680
|
+
break;
|
|
2454
2681
|
case 95:
|
|
2455
2682
|
if(config.sensor_boot_time_420ma_active){
|
|
2456
2683
|
promises.sensor_boot_time_420ma = node.config_gateway.config_set_sensor_boot_time_420ma(mac, parseInt(config.sensor_boot_time_420ma));
|
|
@@ -2644,6 +2871,9 @@ module.exports = function(RED) {
|
|
|
2644
2871
|
if(config.set_rtc_101){
|
|
2645
2872
|
promises.set_rtc_103 = node.config_gateway.config_set_rtc_101(mac);
|
|
2646
2873
|
}
|
|
2874
|
+
if(config.send_raw_on_motion_only_103_active){
|
|
2875
|
+
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));
|
|
2876
|
+
}
|
|
2647
2877
|
break;
|
|
2648
2878
|
case 105:
|
|
2649
2879
|
if(config.sensor_boot_time_420ma_active){
|
|
@@ -3281,8 +3511,8 @@ module.exports = function(RED) {
|
|
|
3281
3511
|
}
|
|
3282
3512
|
break;
|
|
3283
3513
|
case 123:
|
|
3284
|
-
if(config.
|
|
3285
|
-
promises.clear_timers_123 = node.config_gateway.config_set_clear_timers_108(mac,
|
|
3514
|
+
if(config.clear_timers_123){
|
|
3515
|
+
promises.clear_timers_123 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3286
3516
|
}
|
|
3287
3517
|
if(config.debounce_time_123_active){
|
|
3288
3518
|
promises.debounce_time_123 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
@@ -3368,6 +3598,150 @@ module.exports = function(RED) {
|
|
|
3368
3598
|
promises.reset_all_totalizers_124 = node.config_gateway.config_set_reset_all_totalizers_124(mac);
|
|
3369
3599
|
}
|
|
3370
3600
|
break;
|
|
3601
|
+
case 125:
|
|
3602
|
+
if(config.clear_timers_123){
|
|
3603
|
+
promises.clear_timers_125 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3604
|
+
}
|
|
3605
|
+
if(config.debounce_time_123_active){
|
|
3606
|
+
promises.debounce_time_125 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
3607
|
+
}
|
|
3608
|
+
if(config.input_one_123_active){
|
|
3609
|
+
promises.input_one_125 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
3610
|
+
}
|
|
3611
|
+
if(config.input_two_123_active){
|
|
3612
|
+
promises.input_two_125 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_123));
|
|
3613
|
+
}
|
|
3614
|
+
if(config.counter_threshold_108_active){
|
|
3615
|
+
promises.counter_threshold_125 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
3616
|
+
}
|
|
3617
|
+
if(config.push_notification_125_active){
|
|
3618
|
+
promises.push_notification_125 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_125));
|
|
3619
|
+
}
|
|
3620
|
+
if(config.reset_timeout_108_active){
|
|
3621
|
+
promises.reset_timeout_125 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
3622
|
+
}
|
|
3623
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
3624
|
+
promises.reset_mode_125 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
3625
|
+
}
|
|
3626
|
+
if(config.rtc_108){
|
|
3627
|
+
promises.rtc_125 = node.config_gateway.config_set_rtc_108(mac);
|
|
3628
|
+
}
|
|
3629
|
+
if(config.transmission_interval_108_active){
|
|
3630
|
+
promises.transmission_interval_125 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
3631
|
+
}
|
|
3632
|
+
if(config.shift_one_108_active){
|
|
3633
|
+
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));
|
|
3634
|
+
}
|
|
3635
|
+
if(config.shift_two_108_active){
|
|
3636
|
+
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));
|
|
3637
|
+
}
|
|
3638
|
+
if(config.shift_three_108_active){
|
|
3639
|
+
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));
|
|
3640
|
+
}
|
|
3641
|
+
if(config.shift_four_108_active){
|
|
3642
|
+
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));
|
|
3643
|
+
}
|
|
3644
|
+
if(config.quality_of_service_108_active){
|
|
3645
|
+
promises.quality_of_service_125 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
3646
|
+
}
|
|
3647
|
+
if(config.interrupt_timeout_108_active){
|
|
3648
|
+
promises.interrupt_timeout_125 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_108));
|
|
3649
|
+
}
|
|
3650
|
+
if(config.probe_one_126_active){
|
|
3651
|
+
promises.probe_one_125 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
3652
|
+
}
|
|
3653
|
+
if(config.probe_two_126_active){
|
|
3654
|
+
promises.probe_two_125 = node.config_gateway.config_set_probe_two_ct_126(mac, parseInt(config.probe_two_126));
|
|
3655
|
+
}
|
|
3656
|
+
if(config.threshold_probe_one_126_active){
|
|
3657
|
+
promises.threshold_probe_one_125 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
3658
|
+
}
|
|
3659
|
+
if(config.threshold_probe_two_126_active){
|
|
3660
|
+
promises.threshold_probe_two_125 = node.config_gateway.config_set_probe_two_current_threshold_126(mac, parseInt(config.threshold_probe_two_126));
|
|
3661
|
+
}
|
|
3662
|
+
break;
|
|
3663
|
+
case 126:
|
|
3664
|
+
if(config.clear_timers_123){
|
|
3665
|
+
promises.clear_timers_126 = node.config_gateway.config_set_clear_timers_108(mac, 7);
|
|
3666
|
+
}
|
|
3667
|
+
if(config.debounce_time_123_active){
|
|
3668
|
+
promises.debounce_time_126 = node.config_gateway.config_set_debounce_time_v10_108(mac, parseInt(config.debounce_time_123));
|
|
3669
|
+
}
|
|
3670
|
+
if(config.input_one_123_active){
|
|
3671
|
+
promises.input_one_126 = node.config_gateway.config_set_input_one_108(mac, parseInt(config.input_one_123));
|
|
3672
|
+
}
|
|
3673
|
+
if(config.input_two_123_active){
|
|
3674
|
+
promises.input_two_126 = node.config_gateway.config_set_input_two_108(mac, parseInt(config.input_two_123));
|
|
3675
|
+
}
|
|
3676
|
+
if(config.input_three_123_active){
|
|
3677
|
+
promises.input_three_126 = node.config_gateway.config_set_input_three_108(mac, parseInt(config.input_three_123));
|
|
3678
|
+
}
|
|
3679
|
+
if(config.counter_threshold_108_active){
|
|
3680
|
+
promises.counter_threshold_126 = node.config_gateway.config_set_counter_threshold_108(mac, parseInt(config.counter_threshold_108));
|
|
3681
|
+
}
|
|
3682
|
+
if(config.push_notification_123_active){
|
|
3683
|
+
promises.push_notification_126 = node.config_gateway.config_set_push_notification_108(mac, parseInt(config.push_notification_123));
|
|
3684
|
+
}
|
|
3685
|
+
if(config.reset_timeout_108_active){
|
|
3686
|
+
promises.reset_timeout_126 = node.config_gateway.config_set_reset_timeout_108(mac, parseInt(config.reset_timeout_108));
|
|
3687
|
+
}
|
|
3688
|
+
if(config.reset_mode_to_disabled_108_active){
|
|
3689
|
+
promises.reset_mode_126 = node.config_gateway.config_set_reset_mode_to_disabled_108(mac, parseInt(config.reset_mode_to_disabled_108));
|
|
3690
|
+
}
|
|
3691
|
+
if(config.rtc_108){
|
|
3692
|
+
promises.rtc_126 = node.config_gateway.config_set_rtc_108(mac);
|
|
3693
|
+
}
|
|
3694
|
+
if(config.transmission_interval_108_active){
|
|
3695
|
+
promises.transmission_interval_126 = node.config_gateway.config_set_transmission_interval_108(mac, parseInt(config.transmission_interval_108));
|
|
3696
|
+
}
|
|
3697
|
+
if(config.shift_one_108_active){
|
|
3698
|
+
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));
|
|
3699
|
+
}
|
|
3700
|
+
if(config.shift_two_108_active){
|
|
3701
|
+
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));
|
|
3702
|
+
}
|
|
3703
|
+
if(config.shift_three_108_active){
|
|
3704
|
+
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));
|
|
3705
|
+
}
|
|
3706
|
+
if(config.shift_four_108_active){
|
|
3707
|
+
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));
|
|
3708
|
+
}
|
|
3709
|
+
if(config.quality_of_service_108_active){
|
|
3710
|
+
promises.quality_of_service_126 = node.config_gateway.config_set_quality_of_service_108(mac, parseInt(config.quality_of_service_108));
|
|
3711
|
+
}
|
|
3712
|
+
if(config.interrupt_timeout_108_active){
|
|
3713
|
+
promises.interrupt_timeout_126 = node.config_gateway.config_set_interrupt_timeout_108(mac, parseInt(config.interrupt_timeout_108));
|
|
3714
|
+
}
|
|
3715
|
+
if(config.probe_one_126_active){
|
|
3716
|
+
promises.probe_one_126 = node.config_gateway.config_set_probe_one_ct_126(mac, parseInt(config.probe_one_126));
|
|
3717
|
+
}
|
|
3718
|
+
if(config.probe_two_126_active){
|
|
3719
|
+
promises.probe_two_126 = node.config_gateway.config_set_probe_two_ct_126(mac, parseInt(config.probe_two_126));
|
|
3720
|
+
}
|
|
3721
|
+
if(config.probe_three_126_active){
|
|
3722
|
+
promises.probe_three_126 = node.config_gateway.config_set_probe_three_ct_126(mac, parseInt(config.probe_three_126));
|
|
3723
|
+
}
|
|
3724
|
+
if(config.threshold_probe_one_126_active){
|
|
3725
|
+
promises.threshold_probe_one_126 = node.config_gateway.config_set_probe_one_current_threshold_126(mac, parseInt(config.threshold_probe_one_126));
|
|
3726
|
+
}
|
|
3727
|
+
if(config.threshold_probe_two_126_active){
|
|
3728
|
+
promises.threshold_probe_two_126 = node.config_gateway.config_set_probe_two_current_threshold_126(mac, parseInt(config.threshold_probe_two_126));
|
|
3729
|
+
}
|
|
3730
|
+
if(config.threshold_probe_three_126_active){
|
|
3731
|
+
promises.threshold_probe_three_126 = node.config_gateway.config_set_probe_three_current_threshold_126(mac, parseInt(config.threshold_probe_three_126));
|
|
3732
|
+
}
|
|
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;
|
|
3371
3745
|
case 180:
|
|
3372
3746
|
if(config.output_data_rate_101_active){
|
|
3373
3747
|
promises.output_data_rate_101 = node.config_gateway.config_set_output_data_rate_101(mac, parseInt(config.output_data_rate_101));
|
|
@@ -4033,8 +4407,6 @@ module.exports = function(RED) {
|
|
|
4033
4407
|
(function(name){
|
|
4034
4408
|
promises[name].then((f) => {
|
|
4035
4409
|
if(name != 'finish'){
|
|
4036
|
-
// console.log('IN PROMISE RESOLVE');
|
|
4037
|
-
// console.log(f);
|
|
4038
4410
|
// success[name] = true;
|
|
4039
4411
|
if(Object.hasOwn(f, 'result')){
|
|
4040
4412
|
switch(f.result){
|
|
@@ -4070,6 +4442,152 @@ module.exports = function(RED) {
|
|
|
4070
4442
|
});
|
|
4071
4443
|
}
|
|
4072
4444
|
node._sensor_config = _config;
|
|
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
|
+
}
|
|
4451
|
+
|
|
4452
|
+
this.pgm_on(sync_topic, (data) => {
|
|
4453
|
+
if(data.sensor_type == config.sensor_type){
|
|
4454
|
+
let message = {
|
|
4455
|
+
topic: 'sync',
|
|
4456
|
+
type: data.payload.type,
|
|
4457
|
+
...data,
|
|
4458
|
+
time: Date.now()
|
|
4459
|
+
};
|
|
4460
|
+
|
|
4461
|
+
// switch(data.type){
|
|
4462
|
+
// case 'sync_check_in':
|
|
4463
|
+
// break;
|
|
4464
|
+
// case 'sync_init':
|
|
4465
|
+
// break;
|
|
4466
|
+
// case 'sync_acknowledgment':
|
|
4467
|
+
// break;
|
|
4468
|
+
// case 'sync_acknowledgment_error':
|
|
4469
|
+
// break;
|
|
4470
|
+
// case 'sync_end':
|
|
4471
|
+
// break;
|
|
4472
|
+
// default:
|
|
4473
|
+
// console.log('Default in device node sync');
|
|
4474
|
+
// console.log(data.type);
|
|
4475
|
+
// }
|
|
4476
|
+
if(data.type == 'sync_check_in' || data.type == 'manual_sync_check_in'){
|
|
4477
|
+
if(config.auto_config && config.on_the_fly_enable || data.type == 'manual_sync_check_in' && config.auto_config){
|
|
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')){
|
|
4479
|
+
const html_map = this.config_gateway.get_intended_wireless_node_configs(data, config);
|
|
4480
|
+
|
|
4481
|
+
console.log(html_map);
|
|
4482
|
+
|
|
4483
|
+
let update_flag = false;
|
|
4484
|
+
for(let key in html_map){
|
|
4485
|
+
if(html_map[key].html_value != node.gateway_node.sensor_configs[data.payload.address].reported_configs[key]){
|
|
4486
|
+
// console.log('Comparing ' + html_map[key].html_value + ' to ' + node.gateway_node.sensor_configs[data.payload.address].reported_configs[key]);
|
|
4487
|
+
// console.log('Value is different, updating config for ' + key);
|
|
4488
|
+
update_flag = true;
|
|
4489
|
+
break;
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
if(update_flag){
|
|
4493
|
+
promises = {};
|
|
4494
|
+
setTimeout(() => {
|
|
4495
|
+
let msg = {
|
|
4496
|
+
values: {},
|
|
4497
|
+
pass: {},
|
|
4498
|
+
status: 'Configuring'
|
|
4499
|
+
};
|
|
4500
|
+
var tout = setTimeout(() => {
|
|
4501
|
+
console.log('Sync Request Timed Out');
|
|
4502
|
+
}, 20000);
|
|
4503
|
+
promises.send_sync_configs = this.config_gateway.send_sync_config_wireless_node(data, html_map, node.gateway_node.sensor_configs[data.payload.address]);
|
|
4504
|
+
|
|
4505
|
+
promises.finish = new Promise((fulfill, reject) => {
|
|
4506
|
+
node.config_gateway.queue.add(() => {
|
|
4507
|
+
return new Promise((f, r) => {
|
|
4508
|
+
clearTimeout(tout);
|
|
4509
|
+
node.status(modes.FLY);
|
|
4510
|
+
fulfill();
|
|
4511
|
+
f();
|
|
4512
|
+
});
|
|
4513
|
+
});
|
|
4514
|
+
});
|
|
4515
|
+
for(var i in promises){
|
|
4516
|
+
(function(name){
|
|
4517
|
+
promises[name].then((f) => {
|
|
4518
|
+
if(name != 'finish'){
|
|
4519
|
+
let fail_flag = false;
|
|
4520
|
+
for(const key in html_map){
|
|
4521
|
+
if(Object.hasOwn(f.payload.machine_values, key) && f.payload.machine_values[key] == html_map[key].html_value){
|
|
4522
|
+
msg.pass[key] = true;
|
|
4523
|
+
msg.values[key] = f.payload.human_readable[key];
|
|
4524
|
+
}else{
|
|
4525
|
+
msg.pass[key] = false;
|
|
4526
|
+
msg.values[key] = f.payload[key];
|
|
4527
|
+
fail_flag = true;
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
if(fail_flag){
|
|
4531
|
+
msg.status = 'Error';
|
|
4532
|
+
}else{
|
|
4533
|
+
msg.status = 'Success';
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
else{
|
|
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
|
+
});
|
|
4549
|
+
// top_fulfill(msg);
|
|
4550
|
+
}
|
|
4551
|
+
}).catch((err) => {
|
|
4552
|
+
msg[name] = err;
|
|
4553
|
+
});
|
|
4554
|
+
})(i);
|
|
4555
|
+
}
|
|
4556
|
+
});
|
|
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{
|
|
4571
|
+
// console.log('No Config Differences Detected, Skipping Sync Configs');
|
|
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
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
node.send(message);
|
|
4589
|
+
}
|
|
4590
|
+
});
|
|
4073
4591
|
if(config.addr){
|
|
4074
4592
|
config.addr = config.addr.toLowerCase();
|
|
4075
4593
|
|
|
@@ -4132,6 +4650,7 @@ module.exports = function(RED) {
|
|
|
4132
4650
|
});
|
|
4133
4651
|
}
|
|
4134
4652
|
});
|
|
4653
|
+
|
|
4135
4654
|
this.pgm_on('sensor_mode-'+config.addr, (sensor) => {
|
|
4136
4655
|
if(sensor.mode in modes){
|
|
4137
4656
|
node.status(modes[sensor.mode]);
|
|
@@ -4141,7 +4660,7 @@ module.exports = function(RED) {
|
|
|
4141
4660
|
}
|
|
4142
4661
|
if(config.auto_config && sensor.mode == "PGM"){
|
|
4143
4662
|
_config(sensor);
|
|
4144
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY"){
|
|
4663
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync')){
|
|
4145
4664
|
// _send_otn_request(sensor);
|
|
4146
4665
|
// Sensors having issues seeing OTN request sent too quickly
|
|
4147
4666
|
// Added timeout to fix issue
|
|
@@ -4155,11 +4674,11 @@ module.exports = function(RED) {
|
|
|
4155
4674
|
}else{
|
|
4156
4675
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4157
4676
|
}
|
|
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){
|
|
4677
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN" && !Object.hasOwn(sensor, 'sync')){
|
|
4678
|
+
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 103 || config.sensor_type == 202){
|
|
4160
4679
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4161
4680
|
this.gateway.fly_101_in_progress = true;
|
|
4162
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4681
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4163
4682
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4164
4683
|
var broadcast_tout = setTimeout(() => {
|
|
4165
4684
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4181,10 +4700,10 @@ module.exports = function(RED) {
|
|
|
4181
4700
|
}else{
|
|
4182
4701
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4183
4702
|
};
|
|
4184
|
-
} else if(config.sensor_type == 101 && sensor.mode == "FLY" || config.sensor_type == 102 && sensor.mode == "FLY" || config.sensor_type == 202 && sensor.mode == "FLY"){
|
|
4703
|
+
} 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
4704
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4186
4705
|
this.gateway.fly_101_in_progress = true;
|
|
4187
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4706
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4188
4707
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4189
4708
|
var broadcast_tout = setTimeout(() => {
|
|
4190
4709
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4257,7 +4776,7 @@ module.exports = function(RED) {
|
|
|
4257
4776
|
}
|
|
4258
4777
|
if(config.auto_config && sensor.mode == 'PGM'){
|
|
4259
4778
|
_config(sensor);
|
|
4260
|
-
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY"){
|
|
4779
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "FLY" && !Object.hasOwn(sensor, 'sync')){
|
|
4261
4780
|
// _send_otn_request(sensor);
|
|
4262
4781
|
// Sensors having issues seeing OTN request sent too quickly
|
|
4263
4782
|
// Added timeout to fix issue
|
|
@@ -4271,8 +4790,8 @@ module.exports = function(RED) {
|
|
|
4271
4790
|
}else{
|
|
4272
4791
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4273
4792
|
}
|
|
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){
|
|
4793
|
+
}else if(config.auto_config && config.on_the_fly_enable && sensor.mode == "OTN" && !Object.hasOwn(sensor, 'sync')){
|
|
4794
|
+
if(config.sensor_type == 101 || config.sensor_type == 102 || config.sensor_type == 103|| config.sensor_type == 202){
|
|
4276
4795
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4277
4796
|
this.gateway.fly_101_in_progress = true;
|
|
4278
4797
|
node.warn('Starting RTC Timer' + Date.now());
|
|
@@ -4299,10 +4818,10 @@ module.exports = function(RED) {
|
|
|
4299
4818
|
node.send({topic: 'warning', payload: {'warning': 'Wireless Device Node configurations overridden by API Configuration'}, addr: sensor.mac, time: Date.now()});
|
|
4300
4819
|
};
|
|
4301
4820
|
|
|
4302
|
-
}else if(sensor.mode == "FLY" && config.sensor_type == 101 || sensor.mode == "FLY" && config.sensor_type == 102 || sensor.mode == "FLY" && config.sensor_type == 202){
|
|
4821
|
+
}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
4822
|
if(this.gateway.hasOwnProperty('fly_101_in_progress') && this.gateway.fly_101_in_progress == false || !this.gateway.hasOwnProperty('fly_101_in_progress')){
|
|
4304
4823
|
this.gateway.fly_101_in_progress = true;
|
|
4305
|
-
node.warn('Starting RTC Timer' + Date.now());
|
|
4824
|
+
node.warn('Starting RTC Timer ' + Date.now());
|
|
4306
4825
|
node.warn('Sensor checked in for RTC: ' + sensor.mac + ' at ' + Date.now());
|
|
4307
4826
|
var broadcast_tout = setTimeout(() => {
|
|
4308
4827
|
node.warn('Sending RTC Broadcast ' + Date.now());
|
|
@@ -4513,15 +5032,17 @@ module.exports = function(RED) {
|
|
|
4513
5032
|
break;
|
|
4514
5033
|
case 'sensor_config_options':
|
|
4515
5034
|
msg.request = msg.payload;
|
|
4516
|
-
//
|
|
4517
|
-
|
|
4518
|
-
|
|
5035
|
+
// console.log(typeof msg.payload == 'object');
|
|
5036
|
+
// console.log(Object.hasOwn(msg.payload, 'sensor_type'));
|
|
5037
|
+
// console.log(Object.hasOwn(this.gateway.sensor_libs, msg.payload.sensor_type));
|
|
5038
|
+
if(typeof msg.payload == 'object' && Object.hasOwn(msg.payload, 'sensor_type') && Object.hasOwn(this.gateway.sensor_libs, msg.payload.sensor_type)){
|
|
5039
|
+
let options = this.get_config_options(msg.payload.sensor_type, msg.payload.firmware_version);
|
|
4519
5040
|
msg.payload = options;
|
|
4520
5041
|
msg.status = 200;
|
|
4521
5042
|
msg.time = Date.now();
|
|
4522
5043
|
send(msg);
|
|
4523
5044
|
}else{
|
|
4524
|
-
msg.payload = {error: 'get_config_options error:
|
|
5045
|
+
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
5046
|
msg.status = 500;
|
|
4526
5047
|
msg.time = Date.now();
|
|
4527
5048
|
send(msg);
|
|
@@ -4582,48 +5103,36 @@ module.exports = function(RED) {
|
|
|
4582
5103
|
return response;
|
|
4583
5104
|
};
|
|
4584
5105
|
|
|
4585
|
-
this.get_config_options = function(sensor_type){
|
|
4586
|
-
if(Object.hasOwn(
|
|
4587
|
-
const config_list =
|
|
5106
|
+
this.get_config_options = function(sensor_type, firmware_version = 1){
|
|
5107
|
+
if(Object.hasOwn(this.gateway.sensor_libs, sensor_type)){
|
|
5108
|
+
const config_list = this.gateway.sensor_libs[sensor_type].get_config_map(firmware_version);
|
|
4588
5109
|
let response = {};
|
|
4589
5110
|
for (const key in config_list){
|
|
4590
|
-
const info =
|
|
5111
|
+
const info = config_list[key];
|
|
4591
5112
|
// If sensors actually reports and supports the listed config
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
5113
|
+
// console.log(key);
|
|
5114
|
+
// console.log(info);
|
|
5115
|
+
if(Object.hasOwn(info, 'write_index') && !Object.hasOwn(info, 'read_only')){
|
|
5116
|
+
response[key] = {
|
|
5117
|
+
title: info.descriptions.title,
|
|
5118
|
+
default_value: info.default_value,
|
|
5119
|
+
};
|
|
5120
|
+
if(Object.hasOwn(info.descriptions, 'main_caption')){
|
|
5121
|
+
response[key].description = info.descriptions.main_caption;
|
|
5122
|
+
}
|
|
5123
|
+
if(Object.hasOwn(info.descriptions, 'sub_caption')){
|
|
5124
|
+
response[key].description = info.descriptions.main_caption;
|
|
5125
|
+
}
|
|
5126
|
+
if(Object.hasOwn(info, 'validator')){
|
|
5127
|
+
if(Object.hasOwn(info.validator, 'generated')){
|
|
5128
|
+
delete info.validator.generated;
|
|
5129
|
+
}
|
|
5130
|
+
response[key] = {...response[key], ...info.validator};
|
|
5131
|
+
}
|
|
5132
|
+
if(Object.hasOwn(info, 'options')){
|
|
5133
|
+
response[key].options = info.options;
|
|
4605
5134
|
}
|
|
4606
|
-
response[key] = {...response[key], ...info.validator};
|
|
4607
|
-
}
|
|
4608
|
-
if(Object.hasOwn(info, 'options')){
|
|
4609
|
-
response[key].options = info.options;
|
|
4610
5135
|
}
|
|
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
5136
|
}
|
|
4628
5137
|
return response;
|
|
4629
5138
|
}else{
|
|
@@ -4636,12 +5145,96 @@ module.exports = function(RED) {
|
|
|
4636
5145
|
var response = {};
|
|
4637
5146
|
let error_msg = {};
|
|
4638
5147
|
let warning_msg = {};
|
|
5148
|
+
|
|
4639
5149
|
if(desired_configs == null || typeof desired_configs == 'undefined'){
|
|
4640
5150
|
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
5151
|
}else if(!Array.isArray(desired_configs) || desired_configs.length == 0){
|
|
4642
5152
|
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
5153
|
}
|
|
5154
|
+
|
|
5155
|
+
const build_error = (sensor, key, detail) => {
|
|
5156
|
+
return {
|
|
5157
|
+
type: 'error',
|
|
5158
|
+
message: `${detail.text} for ${key} on sensor ${sensor.addr}.`,
|
|
5159
|
+
detail: {
|
|
5160
|
+
config_name: key,
|
|
5161
|
+
...detail // Merges everything: received, help, expected, etc.
|
|
5162
|
+
}
|
|
5163
|
+
};
|
|
5164
|
+
};
|
|
5165
|
+
|
|
5166
|
+
const build_warning = (sensor, key, detail) => {
|
|
5167
|
+
return {
|
|
5168
|
+
type: 'warning',
|
|
5169
|
+
message: `${detail.text} for ${key} on sensor ${sensor.addr}.`,
|
|
5170
|
+
detail: {
|
|
5171
|
+
config_name: key,
|
|
5172
|
+
...detail,
|
|
5173
|
+
help: detail.help || "This warning does not prevent the configuration from going through."
|
|
5174
|
+
}
|
|
5175
|
+
};
|
|
5176
|
+
};
|
|
5177
|
+
|
|
5178
|
+
const validation_methods = {
|
|
5179
|
+
// HEX: Strict, no colons allowed
|
|
5180
|
+
hex: (val, validator, configName, sensor) => {
|
|
5181
|
+
const strVal = String(val);
|
|
5182
|
+
if (!/^[0-9a-f]+$/i.test(strVal)) {
|
|
5183
|
+
return { error: this.build_error(sensor, configName, val, "Invalid hex string", "Hex string should only contain 0-9 and a-f.") };
|
|
5184
|
+
}
|
|
5185
|
+
if (validator.length && strVal.length !== validator.length) {
|
|
5186
|
+
return { error: this.build_error(sensor, configName, val, "Invalid length for hex string", `Expected ${validator.length}, got ${strVal.length}`) };
|
|
5187
|
+
}
|
|
5188
|
+
|
|
5189
|
+
const result = { value: strVal.toLowerCase() };
|
|
5190
|
+
if (!validator.length) {
|
|
5191
|
+
result.warning = this.build_warning(sensor, configName, "Missing length validator", "hexString");
|
|
5192
|
+
}
|
|
5193
|
+
return result;
|
|
5194
|
+
},
|
|
5195
|
+
|
|
5196
|
+
// MAC: Flexible, strips colons first
|
|
5197
|
+
mac: (val, validator, configName, sensor) => {
|
|
5198
|
+
const clean = String(val).replace(/:/g, '');
|
|
5199
|
+
if (!/^[0-9a-f]+$/i.test(clean)) {
|
|
5200
|
+
return { error: this.build_error(sensor, configName, val, "Invalid MAC format", "MAC string should only contain 0-9, a-f, and colons.") };
|
|
5201
|
+
}
|
|
5202
|
+
if (validator.length && clean.length !== validator.length) {
|
|
5203
|
+
return { error: this.build_error(sensor, configName, clean, "Invalid length for MAC", `Expected ${validator.length}, got ${clean.length}`) };
|
|
5204
|
+
}
|
|
5205
|
+
return { value: clean.toLowerCase() };
|
|
5206
|
+
},
|
|
5207
|
+
|
|
5208
|
+
// NUMBERS: uint8, uint16be, uint32be
|
|
5209
|
+
number: (val, validator, configName, sensor, options) => {
|
|
5210
|
+
const num = parseInt(val);
|
|
5211
|
+
if (isNaN(num)) {
|
|
5212
|
+
return { error: this.build_error(sensor, configName, val, "Integer value expected", "Ensure the value is a valid number.") };
|
|
5213
|
+
}
|
|
5214
|
+
|
|
5215
|
+
// Check Min/Max
|
|
5216
|
+
if (validator.min !== undefined && num < validator.min) {
|
|
5217
|
+
return { error: this.build_error(sensor, configName, num, "Value below minimum", `Min allowed: ${validator.min}`) };
|
|
5218
|
+
}
|
|
5219
|
+
if (validator.max !== undefined && num > validator.max) {
|
|
5220
|
+
return { error: this.build_error(sensor, configName, num, "Value above maximum", `Max allowed: ${validator.max}`) };
|
|
5221
|
+
}
|
|
5222
|
+
|
|
5223
|
+
// Check Options
|
|
5224
|
+
if (options && !Object.keys(options).includes(String(num))) {
|
|
5225
|
+
return { error: this.build_error(sensor, configName, num, "Invalid option", `Valid options: ${JSON.stringify(options)}`) };
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5228
|
+
const result = { value: num };
|
|
5229
|
+
if (validator.min === undefined || validator.max === undefined) {
|
|
5230
|
+
result.warning = this.build_warning(sensor, configName, "Missing min/max validator", "number");
|
|
5231
|
+
}
|
|
5232
|
+
return result;
|
|
5233
|
+
}
|
|
5234
|
+
};
|
|
5235
|
+
|
|
4644
5236
|
for (const sensor of desired_configs){
|
|
5237
|
+
|
|
4645
5238
|
// TODO validate sensor object
|
|
4646
5239
|
// must have sensor.addr, sensor.type, sensor.configs
|
|
4647
5240
|
// sensor.configs is an object with key value pairs of config name and desired value
|
|
@@ -4674,6 +5267,21 @@ module.exports = function(RED) {
|
|
|
4674
5267
|
// 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
5268
|
continue;
|
|
4676
5269
|
}
|
|
5270
|
+
if(!Object.hasOwn(node.gateway.sensor_libs, sensor.type)){
|
|
5271
|
+
error_msg.syntax_error ||= {};
|
|
5272
|
+
error_msg.syntax_error = {
|
|
5273
|
+
type: 'error',
|
|
5274
|
+
message: `Invalid sensor type ${sensor.type} for sensor ${sensor.addr}. See detail.valid_sensor in this message for a list of valid sensors.`,
|
|
5275
|
+
detail: {
|
|
5276
|
+
"text": "Invlalid sensor type",
|
|
5277
|
+
"received": sensor.type,
|
|
5278
|
+
"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}}]",
|
|
5279
|
+
"valid_sensors": Object.keys(node.gateway.sensor_libs)
|
|
5280
|
+
}
|
|
5281
|
+
};
|
|
5282
|
+
continue;
|
|
5283
|
+
}
|
|
5284
|
+
|
|
4677
5285
|
// Force lowercase for consistency
|
|
4678
5286
|
sensor.addr = sensor.addr.toLowerCase();
|
|
4679
5287
|
// force configs values lowercase for consistency
|
|
@@ -4698,31 +5306,20 @@ module.exports = function(RED) {
|
|
|
4698
5306
|
node._gateway_node.sensor_configs[sensor.addr].type = sensor.type;
|
|
4699
5307
|
_requires_file_update = true;
|
|
4700
5308
|
}
|
|
5309
|
+
|
|
5310
|
+
const config_map = node.gateway.sensor_libs[sensor.type].get_config_map();
|
|
5311
|
+
|
|
4701
5312
|
// Validate configs
|
|
4702
5313
|
for (const config_name in sensor.configs){
|
|
4703
5314
|
// 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':
|
|
5315
|
+
if(Object.hasOwn(config_map, config_name)){
|
|
5316
|
+
let map_key = config_map[config_name];
|
|
5317
|
+
if(Object.hasOwn(map_key, 'validator')){
|
|
5318
|
+
if(Object.hasOwn(map_key.validator, 'type')){
|
|
5319
|
+
|
|
5320
|
+
// TODO replace with validation_methods object approach for cleaner code
|
|
5321
|
+
switch(map_key.validator.type){
|
|
5322
|
+
case 'hex':
|
|
4726
5323
|
// Remove colons from string
|
|
4727
5324
|
sensor.configs[config_name] = sensor.configs[config_name].replace(/:/g, '');
|
|
4728
5325
|
|
|
@@ -4743,7 +5340,7 @@ module.exports = function(RED) {
|
|
|
4743
5340
|
continue;
|
|
4744
5341
|
}
|
|
4745
5342
|
// Invalid length error
|
|
4746
|
-
if(Object.hasOwn(
|
|
5343
|
+
if(Object.hasOwn(map_key.validator, 'length') && sensor.configs[config_name].length != map_key.validator.length){
|
|
4747
5344
|
error_msg[sensor.addr] ||= {};
|
|
4748
5345
|
error_msg[sensor.addr][config_name] = {
|
|
4749
5346
|
type: 'error',
|
|
@@ -4759,7 +5356,57 @@ module.exports = function(RED) {
|
|
|
4759
5356
|
continue;
|
|
4760
5357
|
}
|
|
4761
5358
|
// Warning for missing length validator
|
|
4762
|
-
if (!Object.hasOwn(
|
|
5359
|
+
if (!Object.hasOwn(map_key.validator, 'length')) {
|
|
5360
|
+
warning_msg[sensor.addr] ||= {};
|
|
5361
|
+
warning_msg[sensor.addr][config_name] = {
|
|
5362
|
+
type: 'warning',
|
|
5363
|
+
message: `No length validator defined for hex string ${config_name} for sensor ${sensor.addr}.`,
|
|
5364
|
+
detail: {
|
|
5365
|
+
"text": "Missing length validator",
|
|
5366
|
+
"type": "hexString",
|
|
5367
|
+
"help": "This warning does not prevent the configuration from going through."
|
|
5368
|
+
}
|
|
5369
|
+
};
|
|
5370
|
+
}
|
|
5371
|
+
break;
|
|
5372
|
+
case 'mac':
|
|
5373
|
+
// Remove colons from string
|
|
5374
|
+
sensor.configs[config_name] = sensor.configs[config_name].replace(/:/g, '');
|
|
5375
|
+
|
|
5376
|
+
// Invalid hex string error
|
|
5377
|
+
if (!/^[0-9a-f]+$/.test(sensor.configs[config_name])) {
|
|
5378
|
+
error_msg[sensor.addr] ||= {};
|
|
5379
|
+
error_msg[sensor.addr][config_name] = {
|
|
5380
|
+
type: 'error',
|
|
5381
|
+
message: `Invalid hex string for configuration ${config_name} for sensor ${sensor.addr}. Received value: ${sensor.configs[config_name]}`,
|
|
5382
|
+
detail: {
|
|
5383
|
+
"text": "Invalid hex string",
|
|
5384
|
+
"regex_validator": "/^[0-9a-f]+$/",
|
|
5385
|
+
"received": sensor.configs[config_name],
|
|
5386
|
+
"help": "Hex string should only contain characters 0-9 and a-f. Colons are removed during validation."
|
|
5387
|
+
}
|
|
5388
|
+
};
|
|
5389
|
+
delete sensor.configs[config_name];
|
|
5390
|
+
continue;
|
|
5391
|
+
}
|
|
5392
|
+
// Invalid length error
|
|
5393
|
+
if(Object.hasOwn(map_key.validator, 'length') && sensor.configs[config_name].length != map_key.validator.length){
|
|
5394
|
+
error_msg[sensor.addr] ||= {};
|
|
5395
|
+
error_msg[sensor.addr][config_name] = {
|
|
5396
|
+
type: 'error',
|
|
5397
|
+
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}`,
|
|
5398
|
+
detail: {
|
|
5399
|
+
"text": "Invalid length for hex string",
|
|
5400
|
+
"expected_length": node._gateway_node.configuration_map[map_key].validator.length,
|
|
5401
|
+
"received_length": sensor.configs[config_name].length,
|
|
5402
|
+
"help": "Add leading or trailing zeros to meet length requirement."
|
|
5403
|
+
}
|
|
5404
|
+
};
|
|
5405
|
+
delete sensor.configs[config_name];
|
|
5406
|
+
continue;
|
|
5407
|
+
}
|
|
5408
|
+
// Warning for missing length validator
|
|
5409
|
+
if (!Object.hasOwn(map_key.validator, 'length')) {
|
|
4763
5410
|
warning_msg[sensor.addr] ||= {};
|
|
4764
5411
|
warning_msg[sensor.addr][config_name] = {
|
|
4765
5412
|
type: 'warning',
|
|
@@ -4794,14 +5441,14 @@ module.exports = function(RED) {
|
|
|
4794
5441
|
continue;
|
|
4795
5442
|
}
|
|
4796
5443
|
// Value below minimum error
|
|
4797
|
-
if(Object.hasOwn(
|
|
5444
|
+
if(Object.hasOwn(map_key.validator, 'min') && sensor.configs[config_name] < map_key.validator.min){
|
|
4798
5445
|
error_msg[sensor.addr] ||= {};
|
|
4799
5446
|
error_msg[sensor.addr][config_name] = {
|
|
4800
5447
|
type: 'error',
|
|
4801
5448
|
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
5449
|
detail: {
|
|
4803
5450
|
"text": "Value below minimum",
|
|
4804
|
-
"min_allowed":
|
|
5451
|
+
"min_allowed": map_key.validator.min,
|
|
4805
5452
|
"received": sensor.configs[config_name],
|
|
4806
5453
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4807
5454
|
}
|
|
@@ -4811,14 +5458,14 @@ module.exports = function(RED) {
|
|
|
4811
5458
|
// 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
5459
|
}
|
|
4813
5460
|
// Value above maximum error
|
|
4814
|
-
if(Object.hasOwn(
|
|
5461
|
+
if(Object.hasOwn(map_key.validator, 'max') && sensor.configs[config_name] > map_key.validator.max){
|
|
4815
5462
|
error_msg[sensor.addr] ||= {};
|
|
4816
5463
|
error_msg[sensor.addr][config_name] = {
|
|
4817
5464
|
type: 'error',
|
|
4818
5465
|
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
5466
|
detail: {
|
|
4820
5467
|
"text": "Value above maximum",
|
|
4821
|
-
"max_allowed":
|
|
5468
|
+
"max_allowed": map_key.validator.max,
|
|
4822
5469
|
"received": sensor.configs[config_name],
|
|
4823
5470
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4824
5471
|
}
|
|
@@ -4828,7 +5475,7 @@ module.exports = function(RED) {
|
|
|
4828
5475
|
// 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
5476
|
}
|
|
4830
5477
|
// Warning for missing min/max validators
|
|
4831
|
-
if(!Object.hasOwn(
|
|
5478
|
+
if(!Object.hasOwn(map_key.validator, 'min') || !Object.hasOwn(map_key.validator, 'max')){
|
|
4832
5479
|
warning_msg[sensor.addr] ||= {};
|
|
4833
5480
|
warning_msg[sensor.addr][config_name] = {
|
|
4834
5481
|
type: 'warning',
|
|
@@ -4843,15 +5490,15 @@ module.exports = function(RED) {
|
|
|
4843
5490
|
}
|
|
4844
5491
|
// If options exist, value must be one of the options
|
|
4845
5492
|
// This is assuming that all configs with options are number types
|
|
4846
|
-
if(Object.hasOwn(
|
|
4847
|
-
if(!Object.keys(
|
|
5493
|
+
if(Object.hasOwn(map_key, 'options')){
|
|
5494
|
+
if(!Object.keys(map_key.options).includes(String(sensor.configs[config_name]))){
|
|
4848
5495
|
error_msg[sensor.addr] ||= {};
|
|
4849
5496
|
error_msg[sensor.addr][config_name] = {
|
|
4850
5497
|
type: 'error',
|
|
4851
5498
|
message: `Invalid option for configuration ${config_name} for sensor ${sensor.addr}. Received value: ${sensor.configs[config_name]}`,
|
|
4852
5499
|
detail: {
|
|
4853
5500
|
"text": "Invalid option",
|
|
4854
|
-
"valid_options":
|
|
5501
|
+
"valid_options": map_key.options,
|
|
4855
5502
|
"received": sensor.configs[config_name],
|
|
4856
5503
|
"help": `Inject this message into the configuration node to get valid configuration values: {topic: 'sensor_config_options', payload: ${sensor.type}}`
|
|
4857
5504
|
}
|
|
@@ -4933,29 +5580,78 @@ module.exports = function(RED) {
|
|
|
4933
5580
|
if(_requires_file_update){
|
|
4934
5581
|
node._gateway_node.store_sensor_configs(JSON.stringify(node._gateway_node.sensor_configs));
|
|
4935
5582
|
}
|
|
4936
|
-
console.log(Object.keys(warning_msg).length);
|
|
5583
|
+
// console.log(Object.keys(warning_msg).length);
|
|
4937
5584
|
if(Object.keys(warning_msg).length){
|
|
4938
5585
|
response.warnings = warning_msg;
|
|
4939
5586
|
}
|
|
4940
|
-
console.log(Object.keys(error_msg).length);
|
|
5587
|
+
// console.log(Object.keys(error_msg).length);
|
|
4941
5588
|
if(Object.keys(error_msg).length){
|
|
4942
5589
|
response.errors = error_msg;
|
|
4943
5590
|
}
|
|
4944
5591
|
return response;
|
|
4945
5592
|
};
|
|
4946
5593
|
|
|
4947
|
-
node.gateway.on('sensor_mode', (d) => {
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
5594
|
+
// node.gateway.on('sensor_mode', (d) => {
|
|
5595
|
+
// if(d.mode == 'FLY'){
|
|
5596
|
+
// if(Object.hasOwn(node._gateway_node.sensor_configs, d.mac) && Object.hasOwn(node._gateway_node.sensor_configs[d.mac], 'api_config_override')){
|
|
5597
|
+
// node.send({topic: 'sensor_report', payload: node._gateway_node.sensor_configs[d.mac], addr: d.mac, time: Date.now()});
|
|
5598
|
+
// }
|
|
5599
|
+
// }else if(d.mode == 'OTF'){
|
|
5600
|
+
// if(Object.hasOwn(node._gateway_node.sensor_configs, d.mac) && Object.hasOwn(node._gateway_node.sensor_configs[d.mac], 'api_config_override')){
|
|
5601
|
+
// node.send({topic: 'post_update_sensor_report', payload: node._gateway_node.sensor_configs[d.mac], addr: d.mac, time: Date.now()});
|
|
5602
|
+
// }
|
|
5603
|
+
// }
|
|
5604
|
+
// });
|
|
5605
|
+
|
|
5606
|
+
node.gateway.on('sync', (d) => {
|
|
5607
|
+
switch (d.payload.type){
|
|
5608
|
+
case 'sync_check_in':
|
|
5609
|
+
// node.set_status();
|
|
5610
|
+
node.send({
|
|
5611
|
+
'topic': 'sync',
|
|
5612
|
+
'type': d.payload.type,
|
|
5613
|
+
...d,
|
|
5614
|
+
'time': Date.now()
|
|
5615
|
+
});
|
|
5616
|
+
break;
|
|
5617
|
+
case 'sync_init':
|
|
5618
|
+
// node.set_status();
|
|
5619
|
+
node.send({
|
|
5620
|
+
'topic': 'sync',
|
|
5621
|
+
'type': d.payload.type,
|
|
5622
|
+
...d,
|
|
5623
|
+
'time': Date.now()
|
|
5624
|
+
});
|
|
5625
|
+
break;
|
|
5626
|
+
case 'sync_end':
|
|
5627
|
+
// node.set_status();
|
|
5628
|
+
node.send({
|
|
5629
|
+
'topic': 'sync',
|
|
5630
|
+
'type': d.payload.type,
|
|
5631
|
+
...d,
|
|
5632
|
+
'time': Date.now()
|
|
5633
|
+
});
|
|
5634
|
+
break;
|
|
5635
|
+
case 'manual_sync_check_in':
|
|
5636
|
+
// node.set_status();
|
|
5637
|
+
node.send({
|
|
5638
|
+
'topic': 'sync',
|
|
5639
|
+
'type': d.payload.type,
|
|
5640
|
+
...d,
|
|
5641
|
+
'time': Date.now()
|
|
5642
|
+
});
|
|
5643
|
+
break;
|
|
5644
|
+
case 'sync_acknowledgment':
|
|
5645
|
+
// node.set_status();
|
|
5646
|
+
node.send({
|
|
5647
|
+
'topic': 'sync',
|
|
5648
|
+
'type': d.payload.type,
|
|
5649
|
+
...d,
|
|
5650
|
+
'time': Date.now()
|
|
5651
|
+
});
|
|
5652
|
+
break;
|
|
4956
5653
|
}
|
|
4957
5654
|
});
|
|
4958
|
-
|
|
4959
5655
|
node._gateway_node.on('config_node_msg', (d) => {
|
|
4960
5656
|
node.send(d);
|
|
4961
5657
|
});
|
|
@@ -4967,13 +5663,14 @@ module.exports = function(RED) {
|
|
|
4967
5663
|
node._gateway_node.removeAllListeners('config_node_msg');
|
|
4968
5664
|
node._gateway_node.removeAllListeners('config_node_error');
|
|
4969
5665
|
node._gateway_node.removeAllListeners('sensor_mode');
|
|
5666
|
+
node._gateway_node.removeAllListeners('sync');
|
|
4970
5667
|
done();
|
|
4971
5668
|
});
|
|
4972
|
-
|
|
4973
5669
|
|
|
4974
5670
|
this.get_all_sensor_info = function(){
|
|
4975
5671
|
return node._gateway_node.sensor_configs;
|
|
4976
5672
|
};
|
|
5673
|
+
|
|
4977
5674
|
this.get_sensor_array_info = function(sensor_array){
|
|
4978
5675
|
let response = {
|
|
4979
5676
|
status: 0,
|