mqtt-devices-parser 1.0.32 → 1.0.33
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/Changelog.md +7 -0
- package/config/index.js +3 -0
- package/index.js +16 -14
- package/models/actuators.models.js +61 -0
- package/models/actuatorsTemplate.models.js +47 -0
- package/models/logs_actuators.models.js +42 -0
- package/models/models.js +24 -23
- package/models/sensors.models.js +5 -0
- package/models/sensorsTemplate.models.js +5 -0
- package/package.json +2 -1
- package/src/db/actuator.js +172 -0
- package/src/db/db.js +4 -3
- package/src/db/device.js +29 -7
- package/src/db/firmware.js +4 -3
- package/src/db/fota.js +2 -1
- package/src/db/model.js +5 -4
- package/src/db/sensor.js +5 -4
- package/src/device/device.js +95 -37
- package/src/device/device.test.js +55 -5
- package/src/kafka/consumer.js +21 -20
- package/src/logger.js +20 -0
- package/src/logger.test.js +12 -0
package/src/db/device.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'Device database' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
var mysql = require('mysql2')
|
|
3
4
|
|
|
@@ -18,7 +19,7 @@ var self = module.exports = {
|
|
|
18
19
|
return resolve(null);
|
|
19
20
|
})
|
|
20
21
|
.catch( err => {
|
|
21
|
-
|
|
22
|
+
logger.info(err);
|
|
22
23
|
return resolve(null);
|
|
23
24
|
});
|
|
24
25
|
});
|
|
@@ -39,7 +40,7 @@ var self = module.exports = {
|
|
|
39
40
|
return resolve(null);
|
|
40
41
|
})
|
|
41
42
|
.catch( err => {
|
|
42
|
-
|
|
43
|
+
logger.info(err);
|
|
43
44
|
return resolve(null);
|
|
44
45
|
});
|
|
45
46
|
});
|
|
@@ -60,7 +61,7 @@ var self = module.exports = {
|
|
|
60
61
|
return resolve(null);
|
|
61
62
|
})
|
|
62
63
|
.catch( err => {
|
|
63
|
-
|
|
64
|
+
logger.info(err);
|
|
64
65
|
return resolve(null);
|
|
65
66
|
});
|
|
66
67
|
});
|
|
@@ -81,7 +82,7 @@ var self = module.exports = {
|
|
|
81
82
|
return resolve(null);
|
|
82
83
|
})
|
|
83
84
|
.catch( err => {
|
|
84
|
-
|
|
85
|
+
logger.info(err);
|
|
85
86
|
return resolve(null);
|
|
86
87
|
});
|
|
87
88
|
});
|
|
@@ -102,7 +103,7 @@ var self = module.exports = {
|
|
|
102
103
|
return resolve(null);
|
|
103
104
|
})
|
|
104
105
|
.catch( err => {
|
|
105
|
-
|
|
106
|
+
logger.info(err);
|
|
106
107
|
return resolve(null);
|
|
107
108
|
});
|
|
108
109
|
});
|
|
@@ -123,7 +124,7 @@ var self = module.exports = {
|
|
|
123
124
|
return resolve(null);
|
|
124
125
|
})
|
|
125
126
|
.catch( err => {
|
|
126
|
-
|
|
127
|
+
logger.info(err);
|
|
127
128
|
return resolve(null);
|
|
128
129
|
});
|
|
129
130
|
});
|
|
@@ -445,6 +446,27 @@ var self = module.exports = {
|
|
|
445
446
|
let args = ["sensors",deviceId,ref];
|
|
446
447
|
query = mysql.format(query,args);
|
|
447
448
|
|
|
449
|
+
$.db.queryRow(query)
|
|
450
|
+
.then( rows => {
|
|
451
|
+
if(rows.length > 0)
|
|
452
|
+
return resolve(rows);
|
|
453
|
+
else
|
|
454
|
+
return resolve(null);
|
|
455
|
+
})
|
|
456
|
+
.catch( err => {
|
|
457
|
+
logger.info(err);
|
|
458
|
+
return resolve(null);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
getActuatorsByRef : async(deviceId, ref)=>{
|
|
464
|
+
return new Promise((resolve,reject) => {
|
|
465
|
+
|
|
466
|
+
let query = "SELECT * FROM ?? where device_id = ? and ref = ?";
|
|
467
|
+
let args = ["actuators",deviceId,ref];
|
|
468
|
+
query = mysql.format(query,args);
|
|
469
|
+
|
|
448
470
|
$.db.queryRow(query)
|
|
449
471
|
.then( rows => {
|
|
450
472
|
if(rows.length > 0)
|
|
@@ -474,7 +496,7 @@ var self = module.exports = {
|
|
|
474
496
|
return resolve(null);
|
|
475
497
|
})
|
|
476
498
|
.catch( err => {
|
|
477
|
-
|
|
499
|
+
logger.info(err);
|
|
478
500
|
return resolve(null);
|
|
479
501
|
});
|
|
480
502
|
});
|
package/src/db/firmware.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'Firmware database' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
var mysql = require('mysql2')
|
|
3
4
|
|
|
@@ -22,7 +23,7 @@ var self = module.exports = {
|
|
|
22
23
|
return resolve(null);
|
|
23
24
|
})
|
|
24
25
|
.catch( err => {
|
|
25
|
-
|
|
26
|
+
logger.info(err);
|
|
26
27
|
return resolve(null);
|
|
27
28
|
});
|
|
28
29
|
});
|
|
@@ -51,7 +52,7 @@ var self = module.exports = {
|
|
|
51
52
|
return resolve(null);
|
|
52
53
|
})
|
|
53
54
|
.catch( err => {
|
|
54
|
-
|
|
55
|
+
logger.info(err);
|
|
55
56
|
return resolve(null);
|
|
56
57
|
});
|
|
57
58
|
});
|
|
@@ -80,7 +81,7 @@ var self = module.exports = {
|
|
|
80
81
|
return resolve(null);
|
|
81
82
|
})
|
|
82
83
|
.catch( err => {
|
|
83
|
-
|
|
84
|
+
logger.info(err);
|
|
84
85
|
return resolve(null);
|
|
85
86
|
});
|
|
86
87
|
});
|
package/src/db/fota.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'FOTA database' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
var mysql = require('mysql2')
|
|
3
4
|
|
|
@@ -74,7 +75,7 @@ var self = module.exports = {
|
|
|
74
75
|
return resolve(rows);
|
|
75
76
|
})
|
|
76
77
|
.catch( err => {
|
|
77
|
-
|
|
78
|
+
logger.info(err);
|
|
78
79
|
return resolve(null);
|
|
79
80
|
});
|
|
80
81
|
});
|
package/src/db/model.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'Model database' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
var mysql = require('mysql2')
|
|
3
4
|
|
|
@@ -19,7 +20,7 @@ var self = module.exports = {
|
|
|
19
20
|
return resolve(null);
|
|
20
21
|
})
|
|
21
22
|
.catch( err => {
|
|
22
|
-
|
|
23
|
+
logger.info(err);
|
|
23
24
|
return resolve(null);
|
|
24
25
|
});
|
|
25
26
|
});
|
|
@@ -41,7 +42,7 @@ var self = module.exports = {
|
|
|
41
42
|
return resolve(null);
|
|
42
43
|
})
|
|
43
44
|
.catch( err => {
|
|
44
|
-
|
|
45
|
+
logger.info(err);
|
|
45
46
|
return resolve(null);
|
|
46
47
|
});
|
|
47
48
|
});
|
|
@@ -60,7 +61,7 @@ var self = module.exports = {
|
|
|
60
61
|
return resolve(rows);
|
|
61
62
|
})
|
|
62
63
|
.catch( err => {
|
|
63
|
-
|
|
64
|
+
logger.info(err);
|
|
64
65
|
return resolve(null);
|
|
65
66
|
});
|
|
66
67
|
});
|
|
@@ -127,7 +128,7 @@ var self = module.exports = {
|
|
|
127
128
|
return resolve(null);
|
|
128
129
|
})
|
|
129
130
|
.catch( err => {
|
|
130
|
-
|
|
131
|
+
logger.info(err);
|
|
131
132
|
return resolve(null);
|
|
132
133
|
});
|
|
133
134
|
});
|
package/src/db/sensor.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'Sensor database' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
var mysql = require('mysql2')
|
|
3
4
|
const table = "sensors"
|
|
@@ -20,7 +21,7 @@ var self = module.exports = {
|
|
|
20
21
|
return resolve(null);
|
|
21
22
|
})
|
|
22
23
|
.catch( err => {
|
|
23
|
-
|
|
24
|
+
logger.info(err);
|
|
24
25
|
return resolve(null);
|
|
25
26
|
});
|
|
26
27
|
});
|
|
@@ -43,7 +44,7 @@ var self = module.exports = {
|
|
|
43
44
|
return resolve(null);
|
|
44
45
|
})
|
|
45
46
|
.catch( err => {
|
|
46
|
-
|
|
47
|
+
logger.info(err);
|
|
47
48
|
return resolve(null);
|
|
48
49
|
});
|
|
49
50
|
});
|
|
@@ -65,7 +66,7 @@ var self = module.exports = {
|
|
|
65
66
|
return resolve(null);
|
|
66
67
|
})
|
|
67
68
|
.catch( err => {
|
|
68
|
-
|
|
69
|
+
logger.info(err);
|
|
69
70
|
return resolve(null);
|
|
70
71
|
});
|
|
71
72
|
});
|
|
@@ -84,7 +85,7 @@ var self = module.exports = {
|
|
|
84
85
|
return resolve(rows);
|
|
85
86
|
})
|
|
86
87
|
.catch( err => {
|
|
87
|
-
|
|
88
|
+
logger.info(err);
|
|
88
89
|
return resolve(null);
|
|
89
90
|
});
|
|
90
91
|
});
|
package/src/device/device.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
const logger = require('../logger').child({ label: 'Device' });
|
|
1
2
|
const moment = require('moment');
|
|
2
3
|
const { isDeepStrictEqual } = require('node:util');
|
|
3
4
|
|
|
4
5
|
var _project = [];
|
|
5
|
-
const table = "sensors"
|
|
6
|
-
const logs_table = "logs_sensor";
|
|
7
6
|
const semver = require('semver');
|
|
8
7
|
|
|
8
|
+
const deviceLogger = (device) => logger.child({ deviceId: device?.uid || device?.id });
|
|
9
|
+
|
|
9
10
|
var self = module.exports = {
|
|
10
11
|
|
|
11
12
|
init : async (config,projects)=>{
|
|
12
13
|
return new Promise(async (resolve,reject) => {
|
|
13
14
|
$.db.connect(config,()=>{
|
|
14
|
-
|
|
15
|
+
logger.info("MYSQL is connected");
|
|
15
16
|
|
|
16
17
|
projects.map( async (name,counter)=>{
|
|
17
|
-
|
|
18
|
+
logger.info("project:",name)
|
|
18
19
|
_project[name] = {
|
|
19
20
|
module : null
|
|
20
21
|
};
|
|
@@ -92,10 +93,10 @@ var self = module.exports = {
|
|
|
92
93
|
const oneWeekAgo = moment().utc().subtract(7, 'days').format('YYYY-MM-DD HH:mm:ss');
|
|
93
94
|
if(tableName.startsWith("logs_")){
|
|
94
95
|
const uptimeSeconds = Math.floor(process.uptime());
|
|
95
|
-
|
|
96
|
+
logger.info(`deleting logs of table ${tableName} older than ${oneWeekAgo}"`);
|
|
96
97
|
await $.db.deleteOldEntries(tableName, { createdAt: oneWeekAgo });
|
|
97
98
|
time = Math.floor(process.uptime()) - uptimeSeconds;
|
|
98
|
-
|
|
99
|
+
logger.info(`Logs of table ${tableName} deleted in ${time}s`);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
},
|
|
@@ -109,7 +110,7 @@ var self = module.exports = {
|
|
|
109
110
|
|
|
110
111
|
for (const model of models) {
|
|
111
112
|
|
|
112
|
-
//
|
|
113
|
+
//logger.info("model:",model?.name);
|
|
113
114
|
if(!model?.id)
|
|
114
115
|
continue;
|
|
115
116
|
|
|
@@ -139,8 +140,8 @@ var self = module.exports = {
|
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
const { latestVersion, latestAppVersion } = firmwareCache.get(cacheKey);
|
|
142
|
-
//
|
|
143
|
-
//
|
|
143
|
+
//logger.info("latestVersion:",latestVersion?.version);
|
|
144
|
+
//logger.info("latestAppVersion:",latestAppVersion?.app_version);
|
|
144
145
|
|
|
145
146
|
if(!latestVersion && !latestAppVersion)
|
|
146
147
|
continue;
|
|
@@ -175,20 +176,20 @@ var self = module.exports = {
|
|
|
175
176
|
|
|
176
177
|
if (res == null) {
|
|
177
178
|
try {
|
|
178
|
-
|
|
179
|
+
deviceLogger(device).info("add fota entry");
|
|
179
180
|
await $.db_fota.update(device.id, obj);
|
|
180
181
|
} catch (err) {
|
|
181
|
-
|
|
182
|
+
deviceLogger(device).error({ err }, "Error updating FOTA entry");
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
} catch (error) {
|
|
186
|
-
|
|
187
|
+
deviceLogger(device).error({ err: error }, "Error getting or processing FOTA entry");
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
}catch(error){
|
|
191
|
-
|
|
192
|
+
logger.error(error);
|
|
192
193
|
continue;
|
|
193
194
|
}
|
|
194
195
|
}
|
|
@@ -237,7 +238,7 @@ var self = module.exports = {
|
|
|
237
238
|
topic = mqtt_prefix+"/fw/fota/update/set";
|
|
238
239
|
}
|
|
239
240
|
let link = `${$.config.web.protocol}${$.config.web.domain}${$.config.web.fw_path}${firmware?.filename}/download?token=${firmware?.token}`;
|
|
240
|
-
|
|
241
|
+
deviceLogger(device).info(`Requesting firmware update to ${firmware?.filename}`);
|
|
241
242
|
$.mqtt_client.publish(topic,`{"url":"${link}"}`,{qos:1,retain:false});
|
|
242
243
|
|
|
243
244
|
let obj = {
|
|
@@ -269,6 +270,9 @@ var self = module.exports = {
|
|
|
269
270
|
|
|
270
271
|
updateSensor : async (device,ref,payload)=>{
|
|
271
272
|
|
|
273
|
+
const table = "sensors"
|
|
274
|
+
const logs_table = "logs_sensor";
|
|
275
|
+
|
|
272
276
|
let sensors = await $.db_device.getSensorsByRef(device.id,ref)
|
|
273
277
|
|
|
274
278
|
if(!sensors?.length)
|
|
@@ -317,6 +321,55 @@ var self = module.exports = {
|
|
|
317
321
|
})
|
|
318
322
|
},
|
|
319
323
|
|
|
324
|
+
updateActuator : async (device,ref,payload)=>{
|
|
325
|
+
|
|
326
|
+
const table = "actuators"
|
|
327
|
+
const logs_table = "logs_actuators";
|
|
328
|
+
|
|
329
|
+
let actuators = await $.db_device.getActuatorsByRef(device.id,ref)
|
|
330
|
+
|
|
331
|
+
if(!actuators?.length)
|
|
332
|
+
return;
|
|
333
|
+
|
|
334
|
+
const object = payload;
|
|
335
|
+
|
|
336
|
+
for (const actuator of actuators) {
|
|
337
|
+
let value = null;
|
|
338
|
+
let error = null;
|
|
339
|
+
if(actuator?.type === "json" && object !== null && typeof object === 'object'){
|
|
340
|
+
if(Object.hasOwnProperty.call(object,actuator?.property)){
|
|
341
|
+
value = object[actuator.property];
|
|
342
|
+
}
|
|
343
|
+
}else{
|
|
344
|
+
if (typeof object === 'object') {
|
|
345
|
+
value = object?.value ?? object?.v;
|
|
346
|
+
error = object?.error ?? object?.e;
|
|
347
|
+
}else{
|
|
348
|
+
value = payload;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if(payload == null || value || error){
|
|
352
|
+
|
|
353
|
+
const data = {
|
|
354
|
+
value,
|
|
355
|
+
error,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
let filter = {
|
|
359
|
+
id : actuator.id
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
await $.db_actuator.update(table,data,filter);
|
|
363
|
+
if(payload == null){
|
|
364
|
+
const lastLogId = await $.db_actuator.getLastLogId(logs_table,actuator.id);
|
|
365
|
+
if(lastLogId != null)
|
|
366
|
+
await $.db_actuator.confirmMessage(logs_table,lastLogId);
|
|
367
|
+
}else
|
|
368
|
+
await $.db_actuator.insert(logs_table,device.id,actuator.id,data);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
|
|
320
373
|
handleMqttTopic : async(device, dbTopic, payload, set)=>{
|
|
321
374
|
if(set){
|
|
322
375
|
if(payload === "" || payload == null){
|
|
@@ -341,7 +394,7 @@ var self = module.exports = {
|
|
|
341
394
|
$.db_device.setSynchedTopic(dbTopic.id,false);
|
|
342
395
|
})
|
|
343
396
|
.catch((error)=>{
|
|
344
|
-
|
|
397
|
+
logger.error(error);
|
|
345
398
|
})
|
|
346
399
|
}else{
|
|
347
400
|
// update remote topic
|
|
@@ -364,7 +417,7 @@ var self = module.exports = {
|
|
|
364
417
|
}
|
|
365
418
|
})
|
|
366
419
|
.catch((error)=>{
|
|
367
|
-
|
|
420
|
+
logger.error(error);
|
|
368
421
|
})
|
|
369
422
|
|
|
370
423
|
}
|
|
@@ -392,7 +445,7 @@ var self = module.exports = {
|
|
|
392
445
|
|
|
393
446
|
async function parseLwm2mMessage(client, project_name, device, topic, payload, action){
|
|
394
447
|
|
|
395
|
-
|
|
448
|
+
deviceLogger(device).info({ topic }, "parse lwm2m message");
|
|
396
449
|
|
|
397
450
|
try{
|
|
398
451
|
payload = JSON.parse(payload);
|
|
@@ -420,6 +473,8 @@ async function parseLwm2mMessage(client, project_name, device, topic, payload, a
|
|
|
420
473
|
|
|
421
474
|
async function parseMqttMessage(client, project_name, device, topic, payload, retain){
|
|
422
475
|
|
|
476
|
+
const log = deviceLogger(device);
|
|
477
|
+
|
|
423
478
|
if(topic.endsWith("/get")){
|
|
424
479
|
let findTopic = $.parser.getWordBeforeLastSlash(topic);
|
|
425
480
|
const dbTopic = await $.db_device.getMqttTopic(device.id,findTopic)
|
|
@@ -433,7 +488,7 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
|
|
|
433
488
|
}
|
|
434
489
|
|
|
435
490
|
const topicBck = topic;
|
|
436
|
-
//
|
|
491
|
+
//logger.info("[MQTT] parse topic: ",topic);
|
|
437
492
|
|
|
438
493
|
try{
|
|
439
494
|
payload = JSON.parse(payload);
|
|
@@ -518,7 +573,7 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
|
|
|
518
573
|
let rows = await $.db_data.updateJson("fw",device.id,payload);
|
|
519
574
|
rows = await $.db_data.addJsonLog("logs_fw",device.id,payload,word);
|
|
520
575
|
}catch(error){
|
|
521
|
-
|
|
576
|
+
log.error(error)
|
|
522
577
|
}
|
|
523
578
|
}else if(typeof payload !== 'object' && payload !== null){
|
|
524
579
|
// change it to topic.startsWith("fw")
|
|
@@ -527,7 +582,7 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
|
|
|
527
582
|
let rows = await $.db_data.update("fw",device.id,column,payload);
|
|
528
583
|
rows = await $.db_data.addLog("logs_fw",device.id,column,payload);
|
|
529
584
|
}catch(error){
|
|
530
|
-
|
|
585
|
+
log.error(error)
|
|
531
586
|
}
|
|
532
587
|
}
|
|
533
588
|
}
|
|
@@ -553,14 +608,17 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
|
|
|
553
608
|
}
|
|
554
609
|
|
|
555
610
|
const dbTopic = await $.db_device.getMqttTopic(device.id,findTopic)
|
|
556
|
-
if(dbTopic != null){
|
|
611
|
+
if(dbTopic != null){ // mqtt topic is known and it's a setting
|
|
557
612
|
self.handleMqttTopic(device,dbTopic,payload,set);
|
|
558
613
|
}
|
|
559
614
|
|
|
560
|
-
// check if topic is a sensor
|
|
561
|
-
if(!set)
|
|
562
|
-
self.updateSensor(device,topicBck,payload);
|
|
563
615
|
|
|
616
|
+
if(!set) // check if topic is a sensor
|
|
617
|
+
self.updateSensor(device,topicBck,payload);
|
|
618
|
+
else{ // check if topic is an actuator
|
|
619
|
+
self.updateActuator(device,findTopic,payload);
|
|
620
|
+
}
|
|
621
|
+
|
|
564
622
|
if(_project[project_name]){
|
|
565
623
|
_project[project_name]?.module?.parseMessage(client,project_name,device,`${word}/${topic}`,payload,retain,()=>{});
|
|
566
624
|
}
|
|
@@ -579,7 +637,7 @@ async function synchMqttTopic(device,dbTopic){
|
|
|
579
637
|
else
|
|
580
638
|
payload = JSON.stringify(dbTopic?.localData);
|
|
581
639
|
}catch(err){
|
|
582
|
-
|
|
640
|
+
logger.error(err);
|
|
583
641
|
return;
|
|
584
642
|
}
|
|
585
643
|
}else{
|
|
@@ -598,7 +656,7 @@ async function updateLocalSettings(device,topic,payload){
|
|
|
598
656
|
let route = topic.split("/");
|
|
599
657
|
|
|
600
658
|
if (route == null || route.length == 0) {
|
|
601
|
-
|
|
659
|
+
deviceLogger(device).warn({ topic }, "updateLocalSettings: topic invalid");
|
|
602
660
|
return;
|
|
603
661
|
}
|
|
604
662
|
|
|
@@ -627,7 +685,7 @@ async function updateLocalSettings(device,topic,payload){
|
|
|
627
685
|
if (typeof payload === 'object' && !Array.isArray(payload)) {
|
|
628
686
|
Object.assign(obj, payload);
|
|
629
687
|
} else {
|
|
630
|
-
|
|
688
|
+
deviceLogger(device).warn({ payload }, "Payload is not a valid object");
|
|
631
689
|
return;
|
|
632
690
|
}
|
|
633
691
|
|
|
@@ -635,7 +693,7 @@ async function updateLocalSettings(device,topic,payload){
|
|
|
635
693
|
// Update the settings in the database
|
|
636
694
|
await $.db_device.updateLocalSettings(JSON.stringify(settings), device.id);
|
|
637
695
|
} catch (err) {
|
|
638
|
-
|
|
696
|
+
deviceLogger(device).error({ err }, "Failed to update local settings");
|
|
639
697
|
}
|
|
640
698
|
}
|
|
641
699
|
|
|
@@ -649,7 +707,7 @@ async function updateRemoteSettings(device,topic,payload){
|
|
|
649
707
|
let route = topic.split("/");
|
|
650
708
|
|
|
651
709
|
if(route == null){
|
|
652
|
-
|
|
710
|
+
deviceLogger(device).warn({ topic }, "updateRemoteSettings: topic invalid");
|
|
653
711
|
return;
|
|
654
712
|
}
|
|
655
713
|
// Parse existing settings
|
|
@@ -689,19 +747,19 @@ async function updateRemoteSettings(device,topic,payload){
|
|
|
689
747
|
if(device?.synch && false)
|
|
690
748
|
synchSettings(device,route[0]);
|
|
691
749
|
} catch (err) {
|
|
692
|
-
|
|
750
|
+
deviceLogger(device).error({ err }, "Failed to update remote settings");
|
|
693
751
|
}
|
|
694
752
|
}
|
|
695
753
|
|
|
696
754
|
// deprecated - only defined mqtt topics can be synched
|
|
697
755
|
async function synchSettings(device,key){
|
|
698
756
|
|
|
699
|
-
|
|
757
|
+
logger.info(`check topic ${key} from ${device.uid}`);
|
|
700
758
|
// Retrieve existing settings
|
|
701
759
|
let localSettings = await $.db_device.getLocalSettings(device.id);
|
|
702
|
-
|
|
760
|
+
logger.info(localSettings)
|
|
703
761
|
let remoteSettings = await $.db_device.getRemoteSettings(device.id);
|
|
704
|
-
|
|
762
|
+
logger.info(remoteSettings)
|
|
705
763
|
|
|
706
764
|
//let keys = await checkSettings(localSettings,remoteSettings);
|
|
707
765
|
/*
|
|
@@ -712,12 +770,12 @@ async function synchSettings(device,key){
|
|
|
712
770
|
let topic = `${mqtt_prefix}/settings/${key}/set`
|
|
713
771
|
try{
|
|
714
772
|
const payload = JSON.stringify(localSettings[key]);
|
|
715
|
-
|
|
716
|
-
|
|
773
|
+
logger.info(`updating key: ${key} with data:`);
|
|
774
|
+
logger.info(payload);
|
|
717
775
|
$.mqtt_client.publish(topic,payload,{qos:1,retain:false});
|
|
718
776
|
}catch(err){
|
|
719
|
-
|
|
720
|
-
|
|
777
|
+
logger.error(localSettings[key])
|
|
778
|
+
logger.error(err);
|
|
721
779
|
}
|
|
722
780
|
}
|
|
723
781
|
}
|
|
@@ -26,6 +26,7 @@ global.$ = {
|
|
|
26
26
|
getById: jest.fn(),
|
|
27
27
|
getMqttTopic: jest.fn(),
|
|
28
28
|
getSensorsByRef: jest.fn(),
|
|
29
|
+
getActuatorsByRef: jest.fn(),
|
|
29
30
|
updateLocalTopic: jest.fn(),
|
|
30
31
|
setSynchedTopic: jest.fn(),
|
|
31
32
|
updateRemoteTopic: jest.fn(),
|
|
@@ -41,6 +42,12 @@ global.$ = {
|
|
|
41
42
|
getByRef: jest.fn(),
|
|
42
43
|
insert: jest.fn()
|
|
43
44
|
},
|
|
45
|
+
db_actuator: {
|
|
46
|
+
update: jest.fn(),
|
|
47
|
+
insert: jest.fn(),
|
|
48
|
+
getLastLogId: jest.fn(),
|
|
49
|
+
confirmMessage: jest.fn()
|
|
50
|
+
},
|
|
44
51
|
db_data: {
|
|
45
52
|
updateJson: jest.fn(),
|
|
46
53
|
addJsonLog: jest.fn(),
|
|
@@ -76,19 +83,31 @@ global.BASE_DIR = '/mock/base/dir';
|
|
|
76
83
|
|
|
77
84
|
// Mock require for project modules
|
|
78
85
|
jest.mock('fs');
|
|
86
|
+
jest.mock('../logger', () => {
|
|
87
|
+
const logger = {
|
|
88
|
+
child: jest.fn(() => logger),
|
|
89
|
+
info: jest.fn(),
|
|
90
|
+
warn: jest.fn(),
|
|
91
|
+
error: jest.fn()
|
|
92
|
+
};
|
|
93
|
+
return logger;
|
|
94
|
+
});
|
|
79
95
|
|
|
80
96
|
const device = require('./device');
|
|
97
|
+
const logger = require('../logger');
|
|
81
98
|
|
|
82
99
|
describe('Device Module', () => {
|
|
83
100
|
beforeEach(() => {
|
|
84
101
|
// Clear all mocks before each test
|
|
85
102
|
jest.clearAllMocks();
|
|
103
|
+
logger.child.mockImplementation(() => logger);
|
|
86
104
|
|
|
87
105
|
// Setup default mock implementations
|
|
88
106
|
$.db.connect.mockImplementation((config, callback) => callback());
|
|
89
107
|
$.db_project.getByName.mockResolvedValue(null);
|
|
90
108
|
$.db_device.getMqttTopic.mockResolvedValue(null);
|
|
91
109
|
$.db_device.getSensorsByRef.mockResolvedValue([]);
|
|
110
|
+
$.db_device.getActuatorsByRef.mockResolvedValue([]);
|
|
92
111
|
});
|
|
93
112
|
|
|
94
113
|
describe('init', () => {
|
|
@@ -308,6 +327,41 @@ describe('Device Module', () => {
|
|
|
308
327
|
});
|
|
309
328
|
});
|
|
310
329
|
|
|
330
|
+
describe('updateActuator', () => {
|
|
331
|
+
it('should update a matched actuator and insert a log for a non-null payload', async () => {
|
|
332
|
+
const mockDevice = { id: 42 };
|
|
333
|
+
const actuator = {
|
|
334
|
+
id: 7,
|
|
335
|
+
ref: 'mode',
|
|
336
|
+
type: 'number'
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
$.db_device.getActuatorsByRef.mockResolvedValue([actuator]);
|
|
340
|
+
|
|
341
|
+
await device.updateActuator(mockDevice, 'mode', { value: 1 });
|
|
342
|
+
|
|
343
|
+
expect($.db_actuator.update).toHaveBeenCalledWith('actuators', { value: 1, error: undefined }, { id: 7 });
|
|
344
|
+
expect($.db_actuator.insert).toHaveBeenCalledWith('logs_actuators', 42, 7, { value: 1, error: undefined });
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should confirm the last actuator log when payload is null', async () => {
|
|
348
|
+
const mockDevice = { id: 42 };
|
|
349
|
+
const actuator = {
|
|
350
|
+
id: 9,
|
|
351
|
+
ref: 'fan',
|
|
352
|
+
type: 'number'
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
$.db_device.getActuatorsByRef.mockResolvedValue([actuator]);
|
|
356
|
+
$.db_actuator.getLastLogId.mockResolvedValue(15);
|
|
357
|
+
|
|
358
|
+
await device.updateActuator(mockDevice, 'fan', null);
|
|
359
|
+
|
|
360
|
+
expect($.db_actuator.getLastLogId).toHaveBeenCalledWith('logs_actuators', 9);
|
|
361
|
+
expect($.db_actuator.confirmMessage).toHaveBeenCalledWith('logs_actuators', 15);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
311
365
|
describe('deleteLogs', () => {
|
|
312
366
|
it('should delete old logs from all log tables', async () => {
|
|
313
367
|
const mockTables = [
|
|
@@ -319,15 +373,11 @@ describe('Device Module', () => {
|
|
|
319
373
|
$.db.getTables.mockResolvedValue(mockTables);
|
|
320
374
|
$.db.deleteOldEntries.mockResolvedValue();
|
|
321
375
|
|
|
322
|
-
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
323
|
-
|
|
324
376
|
await device.deleteLogs();
|
|
325
377
|
|
|
326
378
|
expect($.db.getTables).toHaveBeenCalled();
|
|
327
379
|
expect($.db.deleteOldEntries).toHaveBeenCalledTimes(2); // Only log tables
|
|
328
|
-
expect(
|
|
329
|
-
|
|
330
|
-
consoleSpy.mockRestore();
|
|
380
|
+
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('deleting logs of table'));
|
|
331
381
|
});
|
|
332
382
|
});
|
|
333
383
|
|