mqtt-devices-parser 1.0.28 → 1.0.29
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 +5 -0
- package/models/logs_mqtt.models.js +29 -0
- package/models/logs_mqtt_msgs.models.js +29 -0
- package/models/sensors.models.js +1 -1
- package/package.json +1 -1
- package/src/db/device.js +50 -0
- package/src/device/device.js +52 -10
- package/src/kafka/consumer.js +1 -0
package/Changelog.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.29
|
|
4
|
+
fix(models/sensors): allow null model_id
|
|
5
|
+
fix: synching mqtt topics
|
|
6
|
+
feat: stores mqtt messages
|
|
7
|
+
|
|
3
8
|
## 1.0.28
|
|
4
9
|
test: Add comprehensive Jest test suite for device.js module (#2)
|
|
5
10
|
feat: scope FOTA checks to device variant_id (#11)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = (sequelize,DataTypes)=>{
|
|
3
|
+
return sequelize.define("logs_mqtt", {
|
|
4
|
+
mqtt_id: {
|
|
5
|
+
type: DataTypes.INTEGER,
|
|
6
|
+
allowNull: false,
|
|
7
|
+
},
|
|
8
|
+
device_id: {
|
|
9
|
+
type: DataTypes.INTEGER,
|
|
10
|
+
allowNull: false,
|
|
11
|
+
},
|
|
12
|
+
source: {
|
|
13
|
+
type: DataTypes.STRING,
|
|
14
|
+
allowNull: false
|
|
15
|
+
},
|
|
16
|
+
action: {
|
|
17
|
+
type: DataTypes.STRING,
|
|
18
|
+
allowNull: false
|
|
19
|
+
},
|
|
20
|
+
payload: {
|
|
21
|
+
type: DataTypes.STRING,
|
|
22
|
+
allowNull: true
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tableName: 'logs_mqtt',
|
|
27
|
+
freezeTableName: true
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = (sequelize,DataTypes)=>{
|
|
3
|
+
return sequelize.define("logs_mqtt_msgs", {
|
|
4
|
+
device_id: {
|
|
5
|
+
type: DataTypes.INTEGER,
|
|
6
|
+
allowNull: false,
|
|
7
|
+
},
|
|
8
|
+
topic: {
|
|
9
|
+
type: DataTypes.STRING,
|
|
10
|
+
allowNull: false
|
|
11
|
+
},
|
|
12
|
+
payload: {
|
|
13
|
+
type: DataTypes.STRING,
|
|
14
|
+
allowNull: true
|
|
15
|
+
},
|
|
16
|
+
qos: {
|
|
17
|
+
type: DataTypes.INTEGER,
|
|
18
|
+
allowNull: false
|
|
19
|
+
},
|
|
20
|
+
retain: {
|
|
21
|
+
type: DataTypes.INTEGER,
|
|
22
|
+
allowNull: false
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tableName: 'logs_mqtt_msgs',
|
|
27
|
+
freezeTableName: true
|
|
28
|
+
})
|
|
29
|
+
}
|
package/models/sensors.models.js
CHANGED
package/package.json
CHANGED
package/src/db/device.js
CHANGED
|
@@ -216,6 +216,56 @@ var self = module.exports = {
|
|
|
216
216
|
});
|
|
217
217
|
},
|
|
218
218
|
|
|
219
|
+
addMqttLog : async(deviceId,dbTopicId,from,action,payload)=>{
|
|
220
|
+
return new Promise((resolve,reject) => {
|
|
221
|
+
|
|
222
|
+
const timestamp = moment().utc().format('YYYY-MM-DD HH:mm:ss')
|
|
223
|
+
let obj = {
|
|
224
|
+
createdAt : timestamp,
|
|
225
|
+
updatedAt : timestamp
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
obj['device_id'] = deviceId;
|
|
229
|
+
obj['mqtt_id'] = dbTopicId;
|
|
230
|
+
obj['source'] = from;
|
|
231
|
+
obj['action'] = action;
|
|
232
|
+
obj['payload'] = payload;
|
|
233
|
+
|
|
234
|
+
$.db.insert("logs_mqtt",obj)
|
|
235
|
+
.then (rows => {
|
|
236
|
+
return resolve(rows);
|
|
237
|
+
})
|
|
238
|
+
.catch(error => {
|
|
239
|
+
return reject(error);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
addMqttMsgLog : async(deviceId,topic,payload,retain,qos)=>{
|
|
245
|
+
return new Promise((resolve,reject) => {
|
|
246
|
+
|
|
247
|
+
const timestamp = moment().utc().format('YYYY-MM-DD HH:mm:ss')
|
|
248
|
+
let obj = {
|
|
249
|
+
createdAt : timestamp,
|
|
250
|
+
updatedAt : timestamp
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
obj['device_id'] = deviceId;
|
|
254
|
+
obj['topic'] = topic;
|
|
255
|
+
obj['payload'] = payload;
|
|
256
|
+
obj['retain'] = retain;
|
|
257
|
+
obj['qos'] = qos;
|
|
258
|
+
|
|
259
|
+
$.db.insert("logs_mqtt_msgs",obj)
|
|
260
|
+
.then (rows => {
|
|
261
|
+
return resolve(rows);
|
|
262
|
+
})
|
|
263
|
+
.catch(error => {
|
|
264
|
+
return reject(error);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
|
|
219
269
|
addLogIfChanged : async(id,column,value)=>{
|
|
220
270
|
return new Promise(async (resolve,reject) => {
|
|
221
271
|
|
package/src/device/device.js
CHANGED
|
@@ -33,7 +33,7 @@ var self = module.exports = {
|
|
|
33
33
|
});
|
|
34
34
|
},
|
|
35
35
|
|
|
36
|
-
parseMessage : async (client,topic,payload,retain)=>{
|
|
36
|
+
parseMessage : async (client,topic,payload,retain,qos=0)=>{
|
|
37
37
|
|
|
38
38
|
let topic_bck = topic;
|
|
39
39
|
let project_name = null;
|
|
@@ -77,6 +77,7 @@ var self = module.exports = {
|
|
|
77
77
|
if(device.protocol.toLowerCase() === "lwm2m"){
|
|
78
78
|
parseLwm2mMessage(client, project_name, device, topic, payload, action);
|
|
79
79
|
}else if(device.protocol.toLowerCase() === "mqtt"){
|
|
80
|
+
$.db_device.addMqttMsgLog(device.id,topic,payload,retain,qos);
|
|
80
81
|
parseMqttMessage(client, project_name, device, topic, payload, retain);
|
|
81
82
|
}
|
|
82
83
|
},
|
|
@@ -266,7 +267,6 @@ var self = module.exports = {
|
|
|
266
267
|
}
|
|
267
268
|
},
|
|
268
269
|
|
|
269
|
-
|
|
270
270
|
updateSensor : async (device,ref,payload)=>{
|
|
271
271
|
|
|
272
272
|
let sensors = await $.db_device.getSensorsByRef(device.id,ref)
|
|
@@ -319,17 +319,37 @@ var self = module.exports = {
|
|
|
319
319
|
|
|
320
320
|
handleMqttTopic : async(device, dbTopic, payload, set)=>{
|
|
321
321
|
if(set){
|
|
322
|
+
if(payload === "" || payload == null){
|
|
323
|
+
// acknowledgment
|
|
324
|
+
$.db_device.setSynchedTopic(dbTopic.id,true);
|
|
325
|
+
$.db_device.updateRemoteTopic(dbTopic.id,dbTopic?.localData?.value ? dbTopic.localData.value : dbTopic?.localData);
|
|
326
|
+
let from = "device";
|
|
327
|
+
let action = "ack"
|
|
328
|
+
$.db_device.addMqttLog(device.id,dbTopic.id,from,action,null);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
322
331
|
// update local topic
|
|
332
|
+
let from = "server";
|
|
333
|
+
let action = "write";
|
|
334
|
+
$.db_device.addMqttLog(device.id,dbTopic.id,from,action,JSON.stringify(payload));
|
|
335
|
+
|
|
323
336
|
$.db_device.updateLocalTopic(dbTopic.id,payload)
|
|
324
337
|
.then(()=>{
|
|
325
338
|
// set as not synched
|
|
326
|
-
|
|
339
|
+
if(isDeepStrictEqual(payload, dbTopic?.remoteData))
|
|
340
|
+
$.db_device.setSynchedTopic(dbTopic.id,true);
|
|
341
|
+
else
|
|
342
|
+
$.db_device.setSynchedTopic(dbTopic.id,false);
|
|
327
343
|
})
|
|
328
344
|
.catch((error)=>{
|
|
329
345
|
console.error(error);
|
|
330
346
|
})
|
|
331
347
|
}else{
|
|
332
348
|
// update remote topic
|
|
349
|
+
let from = "device";
|
|
350
|
+
let action = "update";
|
|
351
|
+
$.db_device.addMqttLog(device.id,dbTopic.id,from,action,JSON.stringify(payload));
|
|
352
|
+
|
|
333
353
|
$.db_device.updateRemoteTopic(dbTopic.id,payload)
|
|
334
354
|
.then(async (res)=>{
|
|
335
355
|
// check if topics mismatch
|
|
@@ -383,8 +403,17 @@ async function parseLwm2mMessage(client, project_name, device, topic, payload, a
|
|
|
383
403
|
|
|
384
404
|
async function parseMqttMessage(client, project_name, device, topic, payload, retain){
|
|
385
405
|
|
|
386
|
-
if(topic.endsWith("/get"))
|
|
406
|
+
if(topic.endsWith("/get")){
|
|
407
|
+
let findTopic = $.parser.getWordBeforeLastSlash(topic);
|
|
408
|
+
const dbTopic = await $.db_device.getMqttTopic(device.id,findTopic)
|
|
409
|
+
if(dbTopic != null){
|
|
410
|
+
let from = "server";
|
|
411
|
+
let action = "request";
|
|
412
|
+
let data = null;
|
|
413
|
+
$.db_device.addMqttLog(device.id,dbTopic.id,from,action,data);
|
|
414
|
+
}
|
|
387
415
|
return;
|
|
416
|
+
}
|
|
388
417
|
|
|
389
418
|
const topicBck = topic;
|
|
390
419
|
//console.log("[MQTT] parse topic: ",topic);
|
|
@@ -485,7 +514,8 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
|
|
|
485
514
|
}
|
|
486
515
|
}
|
|
487
516
|
break;
|
|
488
|
-
case "settings":
|
|
517
|
+
case "settings": // deprecated
|
|
518
|
+
break;
|
|
489
519
|
if(topic.endsWith("/set")){
|
|
490
520
|
updateLocalSettings(device,topic,payload);
|
|
491
521
|
}else{
|
|
@@ -525,19 +555,25 @@ async function synchMqttTopic(device,dbTopic){
|
|
|
525
555
|
let mqtt_prefix = `${project.name}/${device.uid}`;
|
|
526
556
|
let topic = `${mqtt_prefix}/${dbTopic.topic}/set`
|
|
527
557
|
let payload = "";
|
|
528
|
-
if(dbTopic?.
|
|
558
|
+
if(dbTopic?.localData && typeof dbTopic?.localData === 'object'){
|
|
529
559
|
try{
|
|
530
|
-
|
|
560
|
+
if(dbTopic?.localData?.value)
|
|
561
|
+
payload = JSON.stringify(dbTopic?.localData?.value);
|
|
562
|
+
else
|
|
563
|
+
payload = JSON.stringify(dbTopic?.localData);
|
|
531
564
|
}catch(err){
|
|
532
565
|
console.error(err);
|
|
533
566
|
return;
|
|
534
567
|
}
|
|
535
568
|
}else{
|
|
536
|
-
payload = dbTopic?.
|
|
569
|
+
payload = dbTopic?.localData;
|
|
537
570
|
}
|
|
538
571
|
$.mqtt_client.publish(topic,payload,{qos:1,retain:false});
|
|
539
572
|
}
|
|
540
573
|
|
|
574
|
+
// keep a struct with all settings configured on the device
|
|
575
|
+
// only topics <project>/<uid>/settings are stored on this struct
|
|
576
|
+
// easier way to return all settings at once
|
|
541
577
|
async function updateLocalSettings(device,topic,payload){
|
|
542
578
|
|
|
543
579
|
$.db_device.addLog(device.id,"local_settings",JSON.stringify(payload));
|
|
@@ -586,6 +622,9 @@ async function updateLocalSettings(device,topic,payload){
|
|
|
586
622
|
}
|
|
587
623
|
}
|
|
588
624
|
|
|
625
|
+
// keep a struct with all settings configured on the device
|
|
626
|
+
// only topics <project>/<uid>/settings are stored on this struct
|
|
627
|
+
// easier way to return all settings at once
|
|
589
628
|
async function updateRemoteSettings(device,topic,payload){
|
|
590
629
|
|
|
591
630
|
$.db_device.addLog(device.id,"remote_settings",JSON.stringify(payload));
|
|
@@ -629,13 +668,15 @@ async function updateRemoteSettings(device,topic,payload){
|
|
|
629
668
|
|
|
630
669
|
try {
|
|
631
670
|
await $.db_device.updateRemoteSettings(JSON.stringify(settings), device.id);
|
|
632
|
-
|
|
671
|
+
// deprecated, only defined topics with synch enabled can be synched
|
|
672
|
+
if(device?.synch && false)
|
|
633
673
|
synchSettings(device,route[0]);
|
|
634
674
|
} catch (err) {
|
|
635
675
|
console.error("Failed to update local settings:", err);
|
|
636
676
|
}
|
|
637
677
|
}
|
|
638
678
|
|
|
679
|
+
// deprecated - only defined mqtt topics can be synched
|
|
639
680
|
async function synchSettings(device,key){
|
|
640
681
|
|
|
641
682
|
console.log(`check topic ${key} from ${device.uid}`);
|
|
@@ -646,6 +687,7 @@ async function synchSettings(device,key){
|
|
|
646
687
|
console.log(remoteSettings)
|
|
647
688
|
|
|
648
689
|
//let keys = await checkSettings(localSettings,remoteSettings);
|
|
690
|
+
/*
|
|
649
691
|
if(localSettings?.hasOwnProperty(key) && remoteSettings?.hasOwnProperty(key)){
|
|
650
692
|
if(!isDeepStrictEqual(localSettings?.[key], remoteSettings?.[key])){
|
|
651
693
|
const project = await $.db_project.getById(device.project_id);
|
|
@@ -662,9 +704,9 @@ async function synchSettings(device,key){
|
|
|
662
704
|
}
|
|
663
705
|
}
|
|
664
706
|
}
|
|
707
|
+
*/
|
|
665
708
|
}
|
|
666
709
|
|
|
667
|
-
|
|
668
710
|
function handleFotaSuccess (deviceId){
|
|
669
711
|
let object = {
|
|
670
712
|
"nAttempts" : 0,
|
package/src/kafka/consumer.js
CHANGED