mqtt-devices-parser 1.0.9 → 1.0.10
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/package.json +1 -1
- package/src/db/data.js +221 -98
- package/src/db/project.js +48 -6
- package/src/device/device.js +56 -5
package/Changelog.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.10
|
|
4
|
+
src/db/data: handles json data
|
|
5
|
+
- Adds updateJson call
|
|
6
|
+
- Adds addJsonLog
|
|
7
|
+
src/db/project: deals with settings
|
|
8
|
+
src/device/device: fixes fota fw link, stores settings on project table (twin model)
|
|
9
|
+
|
|
3
10
|
## 1.0.9
|
|
4
11
|
- Adds method to delete logs older than 1 week
|
|
5
12
|
|
package/package.json
CHANGED
package/src/db/data.js
CHANGED
|
@@ -5,24 +5,24 @@ var self = module.exports = {
|
|
|
5
5
|
|
|
6
6
|
checkEntry : async (table,deviceId)=>{
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
return new Promise((resolve,reject) => {
|
|
9
|
+
|
|
10
|
+
let query = "SELECT * FROM ?? where device_id = ?";
|
|
11
|
+
let args = [table,deviceId];
|
|
12
|
+
query = mysql.format(query,args);
|
|
13
|
+
|
|
14
|
+
$.db.queryRow(query)
|
|
15
|
+
.then( rows => {
|
|
16
|
+
if(rows.length > 0)
|
|
17
|
+
return resolve(rows[0]);
|
|
18
|
+
else
|
|
19
|
+
return resolve(null);
|
|
20
|
+
})
|
|
21
|
+
.catch( err => {
|
|
22
|
+
console.log(err);
|
|
23
|
+
return resolve(null);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
26
|
},
|
|
27
27
|
|
|
28
28
|
update : async (table, deviceId, topic, payload)=>{
|
|
@@ -54,41 +54,41 @@ var self = module.exports = {
|
|
|
54
54
|
topic = topic.substring(index+1);
|
|
55
55
|
|
|
56
56
|
if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
57
|
+
// create JSON struct with the remaining topic
|
|
58
|
+
// table is the table
|
|
59
|
+
// key is the column
|
|
60
|
+
|
|
61
|
+
// build object with the remaining topic and respective data
|
|
62
|
+
if(typeof data === "object")
|
|
63
|
+
obj[key] = JSON.stringify(parser.pathIntoObject(topic,JSON.stringify(data)))
|
|
64
|
+
else
|
|
65
|
+
obj[key] = JSON.stringify(parser.pathIntoObject(topic,data));
|
|
66
|
+
|
|
67
|
+
let exists = await self.checkEntry(table,deviceId);
|
|
68
|
+
if(!exists){
|
|
69
|
+
obj['device_id'] = deviceId;
|
|
70
|
+
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
71
|
+
$.db.insert(table,obj)
|
|
72
|
+
.then((rows)=>{
|
|
73
|
+
return resolve(rows);
|
|
74
|
+
})
|
|
75
|
+
.catch((err)=>{
|
|
76
|
+
console.log(err);
|
|
77
|
+
return resolve();
|
|
78
|
+
})
|
|
79
|
+
}else{
|
|
80
|
+
let filter = {
|
|
81
|
+
device_id : deviceId
|
|
82
|
+
}
|
|
83
|
+
$.db.update(table,obj,filter)
|
|
84
|
+
.then((rows)=>{
|
|
85
|
+
return resolve(rows);
|
|
86
|
+
})
|
|
87
|
+
.catch((err)=>{
|
|
88
|
+
console.log(err);
|
|
89
|
+
return resolve();
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
92
|
|
|
93
93
|
}else return resolve();
|
|
94
94
|
}else{
|
|
@@ -115,7 +115,7 @@ var self = module.exports = {
|
|
|
115
115
|
})
|
|
116
116
|
}else{
|
|
117
117
|
let filter = {
|
|
118
|
-
|
|
118
|
+
device_id : deviceId
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
$.db.update(table,obj,filter)
|
|
@@ -132,67 +132,184 @@ var self = module.exports = {
|
|
|
132
132
|
})
|
|
133
133
|
},
|
|
134
134
|
|
|
135
|
+
updateJson : async (table, deviceId, payload)=>{
|
|
136
|
+
|
|
137
|
+
return new Promise( async (resolve, reject) => {
|
|
138
|
+
|
|
139
|
+
if (!payload || typeof payload !== 'object')
|
|
140
|
+
return resolve();
|
|
141
|
+
|
|
142
|
+
let obj = {
|
|
143
|
+
updatedAt: moment().utc().format('YYYY-MM-DD HH:mm:ss'),
|
|
144
|
+
device_id: deviceId,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Get columns info
|
|
148
|
+
const db_columns = $.models.get(table);
|
|
149
|
+
if (db_columns == null)
|
|
150
|
+
return resolve();
|
|
151
|
+
|
|
152
|
+
// Prepare data for insertion
|
|
153
|
+
for (let key in payload) {
|
|
154
|
+
if (db_columns.hasOwnProperty(key)) {
|
|
155
|
+
let value = payload[key];
|
|
156
|
+
|
|
157
|
+
// Convert object to JSON string if needed
|
|
158
|
+
if (typeof value === 'object') {
|
|
159
|
+
value = JSON.stringify(value);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
obj[key] = value;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let exists = await self.checkEntry(table,deviceId);
|
|
167
|
+
if(!exists){
|
|
168
|
+
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
169
|
+
$.db.insert(table,obj)
|
|
170
|
+
.then((rows)=>{
|
|
171
|
+
return resolve(rows);
|
|
172
|
+
})
|
|
173
|
+
.catch((err)=>{
|
|
174
|
+
console.log(err);
|
|
175
|
+
return resolve();
|
|
176
|
+
})
|
|
177
|
+
}else{
|
|
178
|
+
let filter = {
|
|
179
|
+
device_id : deviceId
|
|
180
|
+
}
|
|
181
|
+
$.db.update(table,obj,filter)
|
|
182
|
+
.then((rows)=>{
|
|
183
|
+
return resolve(rows);
|
|
184
|
+
})
|
|
185
|
+
.catch((err)=>{
|
|
186
|
+
console.log(err);
|
|
187
|
+
return resolve();
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return resolve();
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
|
|
135
195
|
addLog : async (table, deviceId, topic, payload)=>{
|
|
136
196
|
|
|
137
197
|
return new Promise((resolve,reject) => {
|
|
138
198
|
|
|
139
199
|
if(!payload) return resolve();
|
|
140
200
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
201
|
+
let data = null;
|
|
202
|
+
// check if data is in JSON format
|
|
203
|
+
try{
|
|
204
|
+
data = JSON.parse(payload);
|
|
205
|
+
}catch(e){
|
|
206
|
+
data = payload;
|
|
207
|
+
}
|
|
148
208
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
209
|
+
let obj = {
|
|
210
|
+
updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
|
|
211
|
+
}
|
|
152
212
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
213
|
+
let db_columns = $.models.get(table);
|
|
214
|
+
if(db_columns == null)
|
|
215
|
+
return resolve();
|
|
156
216
|
|
|
157
|
-
|
|
217
|
+
let index = topic.indexOf("/");
|
|
158
218
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
219
|
+
if(index > -1){ // check if topic has subtopics
|
|
220
|
+
let key = topic.substring(0,index);
|
|
221
|
+
topic = topic.substring(index+1);
|
|
162
222
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
223
|
+
if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
|
|
224
|
+
// create JSON struct with the remaining topic
|
|
225
|
+
// key is the column
|
|
166
226
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
227
|
+
// build object with the remaining topic and respective data
|
|
228
|
+
if(typeof data === "object")
|
|
229
|
+
obj[key] = JSON.stringify(parser.pathIntoObject(topic,JSON.stringify(data)))
|
|
230
|
+
else
|
|
231
|
+
obj[key] = JSON.stringify(parser.pathIntoObject(topic,data));
|
|
232
|
+
|
|
233
|
+
obj['device_id'] = deviceId;
|
|
234
|
+
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
235
|
+
$.db.insert(table,obj)
|
|
236
|
+
.then((rows)=>{
|
|
237
|
+
return resolve(rows);
|
|
238
|
+
})
|
|
239
|
+
.catch((err)=>{
|
|
240
|
+
console.log(err);
|
|
241
|
+
return resolve();
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
}else
|
|
245
|
+
return resolve();
|
|
246
|
+
}else{
|
|
172
247
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
248
|
+
let key = topic;
|
|
249
|
+
if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
|
|
250
|
+
// build object with respective data
|
|
251
|
+
if(typeof data === "object")
|
|
252
|
+
obj[key] = JSON.stringify(data);
|
|
253
|
+
else
|
|
254
|
+
obj[key] = data;
|
|
176
255
|
|
|
256
|
+
obj['device_id'] = deviceId;
|
|
257
|
+
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
258
|
+
$.db.insert(table,obj)
|
|
259
|
+
.then((rows)=>{
|
|
260
|
+
return resolve(rows);
|
|
261
|
+
})
|
|
262
|
+
.catch((err)=>{
|
|
263
|
+
console.log(err);
|
|
264
|
+
return resolve();
|
|
265
|
+
})
|
|
266
|
+
}else
|
|
267
|
+
return resolve();
|
|
177
268
|
}
|
|
178
|
-
}else{
|
|
179
269
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
// build object with respective data
|
|
183
|
-
if(typeof data === "object")
|
|
184
|
-
obj[key] = JSON.stringify(data);
|
|
185
|
-
else
|
|
186
|
-
obj[key] = data;
|
|
270
|
+
});
|
|
271
|
+
},
|
|
187
272
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
273
|
+
addJsonLog: async (table, deviceId, dataObject) => {
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
if (!dataObject || typeof dataObject !== 'object')
|
|
276
|
+
return resolve();
|
|
277
|
+
|
|
278
|
+
let obj = {
|
|
279
|
+
updatedAt: moment().utc().format('YYYY-MM-DD HH:mm:ss'),
|
|
280
|
+
device_id: deviceId,
|
|
281
|
+
createdAt: moment().utc().format('YYYY-MM-DD HH:mm:ss')
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
// Get columns info
|
|
285
|
+
const db_columns = $.models.get(table);
|
|
286
|
+
if (db_columns == null)
|
|
287
|
+
return resolve();
|
|
288
|
+
|
|
289
|
+
// Prepare data for insertion
|
|
290
|
+
for (let key in dataObject) {
|
|
291
|
+
if (db_columns.hasOwnProperty(key)) {
|
|
292
|
+
let value = dataObject[key];
|
|
293
|
+
|
|
294
|
+
// Convert object to JSON string if needed
|
|
295
|
+
if (typeof value === 'object') {
|
|
296
|
+
value = JSON.stringify(value);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
obj[key] = value;
|
|
300
|
+
}
|
|
191
301
|
}
|
|
192
|
-
}
|
|
193
302
|
|
|
194
|
-
|
|
195
|
-
|
|
303
|
+
//console.log("updateJSONlog")
|
|
304
|
+
$.db.insert(table, obj)
|
|
305
|
+
.then((rows)=>{
|
|
306
|
+
return resolve(rows);
|
|
307
|
+
})
|
|
308
|
+
.catch((err)=>{
|
|
309
|
+
console.log(err);
|
|
310
|
+
return resolve();
|
|
311
|
+
})
|
|
312
|
+
});
|
|
196
313
|
},
|
|
197
314
|
|
|
198
315
|
deleteLogs : async (table, deviceId, topic, payload)=>{
|
|
@@ -223,7 +340,13 @@ var self = module.exports = {
|
|
|
223
340
|
obj['device_id'] = deviceId;
|
|
224
341
|
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
225
342
|
$.db.insert(table,obj)
|
|
226
|
-
|
|
343
|
+
.then((rows)=>{
|
|
344
|
+
return resolve(rows);
|
|
345
|
+
})
|
|
346
|
+
.catch((err)=>{
|
|
347
|
+
console.log(err);
|
|
348
|
+
return resolve();
|
|
349
|
+
})
|
|
227
350
|
}
|
|
228
351
|
}else{
|
|
229
352
|
|
|
@@ -237,7 +360,7 @@ var self = module.exports = {
|
|
|
237
360
|
|
|
238
361
|
obj['device_id'] = deviceId;
|
|
239
362
|
obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
|
|
240
|
-
$.db.insert(table,obj)
|
|
363
|
+
$.db.insert(table,obj)
|
|
241
364
|
}
|
|
242
365
|
}
|
|
243
366
|
|
package/src/db/project.js
CHANGED
|
@@ -20,8 +20,7 @@ var self = module.exports = {
|
|
|
20
20
|
return resolve(null);
|
|
21
21
|
})
|
|
22
22
|
.catch( err => {
|
|
23
|
-
|
|
24
|
-
return resolve(null);
|
|
23
|
+
return reject(err);
|
|
25
24
|
});
|
|
26
25
|
});
|
|
27
26
|
},
|
|
@@ -42,8 +41,7 @@ var self = module.exports = {
|
|
|
42
41
|
return resolve(null);
|
|
43
42
|
})
|
|
44
43
|
.catch( err => {
|
|
45
|
-
|
|
46
|
-
return resolve(null);
|
|
44
|
+
return reject(err);
|
|
47
45
|
});
|
|
48
46
|
});
|
|
49
47
|
},
|
|
@@ -61,8 +59,7 @@ var self = module.exports = {
|
|
|
61
59
|
return resolve(rows);
|
|
62
60
|
})
|
|
63
61
|
.catch( err => {
|
|
64
|
-
|
|
65
|
-
return resolve(null);
|
|
62
|
+
return reject(null);
|
|
66
63
|
});
|
|
67
64
|
});
|
|
68
65
|
},
|
|
@@ -88,4 +85,49 @@ var self = module.exports = {
|
|
|
88
85
|
});
|
|
89
86
|
},
|
|
90
87
|
|
|
88
|
+
getSettings : async(project,deviceId)=>{
|
|
89
|
+
|
|
90
|
+
return new Promise((resolve,reject) => {
|
|
91
|
+
|
|
92
|
+
let query = "SELECT settings FROM ?? where device_id = ?";
|
|
93
|
+
let table = [project, deviceId];
|
|
94
|
+
query = mysql.format(query,table);
|
|
95
|
+
|
|
96
|
+
$.db.queryRow(query)
|
|
97
|
+
.then( rows => {
|
|
98
|
+
if(rows?.length > 0)
|
|
99
|
+
return resolve(rows[0].settings);
|
|
100
|
+
else
|
|
101
|
+
return resolve(null);
|
|
102
|
+
})
|
|
103
|
+
.catch( err => {
|
|
104
|
+
return reject(err);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
updateSettings : async(project, settings, deviceId)=>{
|
|
110
|
+
|
|
111
|
+
return new Promise((resolve,reject) => {
|
|
112
|
+
let obj = {
|
|
113
|
+
settings : settings,
|
|
114
|
+
updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let filter = {
|
|
118
|
+
device_id : deviceId
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
resolve(null)
|
|
122
|
+
|
|
123
|
+
$.db.update(project,obj,filter)
|
|
124
|
+
.then (rows => {
|
|
125
|
+
return resolve(rows[0]);
|
|
126
|
+
})
|
|
127
|
+
.catch(error => {
|
|
128
|
+
return reject(error);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
});
|
|
132
|
+
},
|
|
91
133
|
}
|
package/src/device/device.js
CHANGED
|
@@ -130,15 +130,17 @@ var self = module.exports = {
|
|
|
130
130
|
return;
|
|
131
131
|
|
|
132
132
|
let mqtt_prefix = `${project_name}/${uid}`;
|
|
133
|
-
let link = `${$.config.web.protocol}${$.config.web.domain}${$.config.web.fw_path}${new_firmware.filename}/download?token=${new_firmware.token}`;
|
|
134
133
|
|
|
135
|
-
if(
|
|
136
|
-
console.log(
|
|
134
|
+
if(new_app != null && semver.lt(app_version, new_app.app_version)) {
|
|
135
|
+
console.log(new_app)
|
|
136
|
+
console.log(`updating firmware of ${uid} to minor version ${new_app.app_version}`);
|
|
137
|
+
let link = `${$.config.web.protocol}${$.config.web.domain}${$.config.web.fw_path}${new_app.filename}/download?token=${new_app.token}`;
|
|
137
138
|
client.publish(mqtt_prefix+"/fw/fota/update/set",`{"url":"${link}"}`,{qos:2,retain:false});
|
|
138
139
|
await $.db_data.update(project_name,device.id,"fota_tries",++fota_tries);
|
|
139
140
|
}else{
|
|
140
|
-
if(
|
|
141
|
-
console.log(`updating firmware of ${uid} to ${
|
|
141
|
+
if(new_firmware != null && semver.lt(fw_version, new_firmware.fw_version)) {
|
|
142
|
+
console.log(`updating firmware of ${uid} to major version ${new_firmware.fw_version}`);
|
|
143
|
+
let link = `${$.config.web.protocol}${$.config.web.domain}${$.config.web.fw_path}${new_firmware.filename}/download?token=${new_firmware.token}`;
|
|
142
144
|
client.publish(mqtt_prefix+"/fw/fota/update/set",`{"url":"${link}"}`,{qos:2,retain:false});
|
|
143
145
|
await $.db_data.update(project_name,device.id,"fota_tries",++fota_tries);
|
|
144
146
|
}
|
|
@@ -153,6 +155,55 @@ var self = module.exports = {
|
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
157
|
|
|
158
|
+
// store remote device settings on project table - twin model
|
|
159
|
+
if(topic.endsWith("/set") && payload != "" ){
|
|
160
|
+
|
|
161
|
+
let route = topic.split("/");
|
|
162
|
+
|
|
163
|
+
if(route == null){
|
|
164
|
+
console.log("topic invalid:",topic);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// get settings
|
|
168
|
+
let settings = await $.db_project.getSettings(project_name,device.id);
|
|
169
|
+
let obj = settings;
|
|
170
|
+
|
|
171
|
+
if(obj == null){
|
|
172
|
+
console.log("no settings available for deviceId:",device.id)
|
|
173
|
+
obj = {};
|
|
174
|
+
}
|
|
175
|
+
// Traverse through all route parts except the last one
|
|
176
|
+
route.slice(0, -1).forEach(property => {
|
|
177
|
+
if (!obj.hasOwnProperty(property) ||
|
|
178
|
+
( obj.hasOwnProperty(property) && typeof obj[property] !== 'object'))
|
|
179
|
+
{
|
|
180
|
+
obj[property] = {}; // create nested object if missing or not an object
|
|
181
|
+
}
|
|
182
|
+
obj = obj[property]; // go deeper
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
let data = {};
|
|
186
|
+
try{
|
|
187
|
+
data = JSON.parse(payload)
|
|
188
|
+
}catch(error){}
|
|
189
|
+
|
|
190
|
+
if (true || (data && typeof payload === 'object' && !Array.isArray(payload) ) ) {
|
|
191
|
+
// Assuming payload is an object with properties to process
|
|
192
|
+
for (const [key, value] of Object.entries(data)) {
|
|
193
|
+
obj[key] = value; // go deeper
|
|
194
|
+
};
|
|
195
|
+
}else{
|
|
196
|
+
obj = payload
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// update on device fw settings
|
|
200
|
+
try{
|
|
201
|
+
await $.db_project.updateSettings(project_name,JSON.stringify(settings),device.id);
|
|
202
|
+
}catch(error){
|
|
203
|
+
console.log(error);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
156
207
|
if(project[project_name]){
|
|
157
208
|
project[project_name].module.parseMessage(client,project_name,device,topic,payload,retain,()=>{});
|
|
158
209
|
}
|