mqtt-devices-parser 1.0.12 → 1.0.14

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 CHANGED
@@ -1,7 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.14
4
+ Fixes check FOTA mechanism and response
5
+
6
+ ## 1.0.13
7
+ adds 2 new tables to db:
8
+ Adds 5 new columns to devices
9
+ Registers device logs, records device settings..
10
+ fixes: ws affected by a DoS when handling a request with many HTTP headers !breaking change
11
+ Updates npm
12
+
3
13
  ## 1.0.12
4
- Adds periodically call to check and update devices
14
+ Adds module fota
5
15
 
6
16
  ## 1.0.11
7
17
  index: MQTT
package/Release.md CHANGED
@@ -8,4 +8,7 @@
8
8
 
9
9
  ## Releasing
10
10
 
11
+ launch release on git:
12
+ >> gh release create ${tag}
13
+
11
14
  npm publish
@@ -43,6 +43,27 @@ module.exports = (sequelize,DataTypes)=>{
43
43
  type: DataTypes.STRING,
44
44
  allowNull: true
45
45
  },
46
+ remote_settings: { // device settings
47
+ type: DataTypes.JSON,
48
+ allowNull: true
49
+ },
50
+ local_settings: { // server settings
51
+ type: DataTypes.JSON,
52
+ allowNull: true
53
+ },
54
+ settings_ref: { // settings to be used, can be a uid, deviceId, default..
55
+ type: DataTypes.STRING,
56
+ allowNull: true
57
+ },
58
+ associatedDevice: {
59
+ type: DataTypes.INTEGER,
60
+ allowNull: true
61
+ },
62
+ endpoint: { // info about protocol communication
63
+ type: DataTypes.JSON,
64
+ allowNull: true
65
+ },
66
+
46
67
  },
47
68
  {
48
69
  tableName: 'devices',
@@ -4,6 +4,9 @@ module.exports = (sequelize,DataTypes)=>{
4
4
  type: DataTypes.INTEGER,
5
5
  unique: true,
6
6
  },
7
+ model_id: {
8
+ type: DataTypes.INTEGER,
9
+ },
7
10
  target_version: {
8
11
  type: DataTypes.STRING,
9
12
  },
@@ -0,0 +1,17 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("logs_actions", {
4
+ client_id: {
5
+ type: DataTypes.INTEGER,
6
+ allowNull: false
7
+ },
8
+ action: {
9
+ type: DataTypes.STRING,
10
+ allowNull: true
11
+ },
12
+ },
13
+ {
14
+ tableName: 'logs_actions',
15
+ freezeTableName: true
16
+ })
17
+ }
@@ -0,0 +1,62 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("logs_devices", {
4
+ device_id: {
5
+ type: DataTypes.INTEGER,
6
+ },
7
+ status: {
8
+ type: DataTypes.STRING,
9
+ allowNull: true
10
+ },
11
+ project_id: {
12
+ type: DataTypes.INTEGER,
13
+ references: {
14
+ model: 'projects',
15
+ key: 'id'
16
+ }
17
+ },
18
+ model_id: {
19
+ type: DataTypes.INTEGER,
20
+ references: {
21
+ model: 'models',
22
+ key: 'id'
23
+ }
24
+ },
25
+ version: {
26
+ type: DataTypes.STRING,
27
+ allowNull: true
28
+ },
29
+ app_version: {
30
+ type: DataTypes.STRING,
31
+ allowNull: true
32
+ },
33
+ tech: {
34
+ type: DataTypes.STRING,
35
+ allowNull: true
36
+ },
37
+ associatedDevice: {
38
+ type: DataTypes.INTEGER,
39
+ allowNull: true
40
+ },
41
+ local_settings: { // server settings
42
+ type: DataTypes.JSON,
43
+ allowNull: true
44
+ },
45
+ remote_settings: { // server settings
46
+ type: DataTypes.JSON,
47
+ allowNull: true
48
+ },
49
+ settings_ref: { // settings to be used, can be a uid, deviceId, default..
50
+ type: DataTypes.STRING,
51
+ allowNull: true
52
+ },
53
+ endpoint: { // info about protocol communication
54
+ type: DataTypes.JSON,
55
+ allowNull: true
56
+ },
57
+ },
58
+ {
59
+ tableName: 'logs_devices',
60
+ freezeTableName: true
61
+ })
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mqtt-devices-parser",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/db/data.js CHANGED
@@ -278,7 +278,7 @@ var self = module.exports = {
278
278
  addJsonLog: async (table, deviceId, dataObject) => {
279
279
  return new Promise((resolve, reject) => {
280
280
  if (!dataObject || typeof dataObject !== 'object')
281
- return resolve();
281
+ return reject("Not an object");
282
282
 
283
283
  let obj = {
284
284
  updatedAt: moment().utc().format('YYYY-MM-DD HH:mm:ss'),
@@ -289,7 +289,7 @@ var self = module.exports = {
289
289
  // Get columns info
290
290
  const db_columns = $.models.get(table);
291
291
  if (db_columns == null)
292
- return resolve();
292
+ return reject(`No columns for table: ${table}`);
293
293
 
294
294
  // Prepare data for insertion
295
295
  for (let key in dataObject) {
package/src/db/device.js CHANGED
@@ -194,4 +194,199 @@ var self = module.exports = {
194
194
  });
195
195
  },
196
196
 
197
+
198
+ addLog : async(id,column,value)=>{
199
+ return new Promise((resolve,reject) => {
200
+
201
+ const timestamp = moment().utc().format('YYYY-MM-DD HH:mm:ss')
202
+ let obj = {
203
+ createdAt : timestamp,
204
+ updatedAt : timestamp
205
+ };
206
+
207
+ obj['device_id'] = id;
208
+ obj[column] = value;
209
+
210
+ $.db.insert("logs_devices",obj)
211
+ .then (rows => {
212
+ return resolve(rows);
213
+ })
214
+ .catch(error => {
215
+ return reject(error);
216
+ });
217
+ });
218
+ },
219
+
220
+ addLogIfChanged : async(id,column,value)=>{
221
+ return new Promise(async (resolve,reject) => {
222
+
223
+ let query = "SELECT ?? FROM ?? where id = ? and ?? is NOT NULL ORDER BY updatedAt DESC LIMIT 1";
224
+ let table = [column,"logs_devices",id,column];
225
+ query = mysql.format(query,table);
226
+
227
+ try{
228
+ let rows = await $.db.queryRow(query)
229
+
230
+ if(rows.length > 0){
231
+ let lastValue = rows[0]?.column
232
+ if(lastValue == value)
233
+ resolve();
234
+ }
235
+
236
+ const timestamp = moment().utc().format('YYYY-MM-DD HH:mm:ss')
237
+ let obj = {
238
+ createdAt : timestamp,
239
+ updatedAt : timestamp
240
+ };
241
+
242
+ obj['device_id'] = id;
243
+ obj[column] = value;
244
+
245
+ await $.db.insert("logs_devices",obj)
246
+
247
+ resolve();
248
+
249
+ }catch (err) {
250
+ return reject(err);
251
+ };
252
+
253
+ });
254
+ },
255
+
256
+ getLocalSettings : async(deviceId)=>{
257
+
258
+ return new Promise((resolve,reject) => {
259
+
260
+ let query = "SELECT local_settings FROM ?? where id = ?";
261
+ let table = ["devices", deviceId];
262
+ query = mysql.format(query,table);
263
+
264
+ $.db.queryRow(query)
265
+ .then( rows => {
266
+ if(rows?.length > 0)
267
+ return resolve(rows[0]?.local_settings);
268
+ else
269
+ return resolve(null);
270
+ })
271
+ .catch( err => {
272
+ return reject(err);
273
+ });
274
+ });
275
+ },
276
+
277
+ updateLocalSettings : async(settings, deviceId)=>{
278
+
279
+ return new Promise((resolve,reject) => {
280
+ let obj = {
281
+ local_settings : settings,
282
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
283
+ }
284
+
285
+ let filter = {
286
+ id : deviceId
287
+ };
288
+
289
+ resolve(null)
290
+
291
+ $.db.update("devices",obj,filter)
292
+ .then (rows => {
293
+ return resolve(rows[0]);
294
+ })
295
+ .catch(error => {
296
+ return reject(error);
297
+ });
298
+
299
+ });
300
+ },
301
+
302
+ getRemoteSettings : async(deviceId)=>{
303
+
304
+ return new Promise((resolve,reject) => {
305
+
306
+ let query = "SELECT remote_settings FROM ?? where id = ?";
307
+ let table = ["devices", deviceId];
308
+ query = mysql.format(query,table);
309
+
310
+ $.db.queryRow(query)
311
+ .then( rows => {
312
+ if(rows?.length > 0)
313
+ return resolve(rows[0]?.remote_settings);
314
+ else
315
+ return resolve(null);
316
+ })
317
+ .catch( err => {
318
+ return reject(err);
319
+ });
320
+ });
321
+ },
322
+
323
+ updateRemoteSettings : async(settings, deviceId)=>{
324
+
325
+ return new Promise((resolve,reject) => {
326
+ let obj = {
327
+ remote_settings : settings,
328
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
329
+ }
330
+
331
+ let filter = {
332
+ id : deviceId
333
+ };
334
+
335
+ resolve(null)
336
+
337
+ $.db.update("devices",obj,filter)
338
+ .then (rows => {
339
+ return resolve(rows[0]);
340
+ })
341
+ .catch(error => {
342
+ return reject(error);
343
+ });
344
+
345
+ });
346
+ },
347
+
348
+ getAssociatedDevice : async (deviceId)=>{
349
+
350
+ return new Promise((resolve,reject) => {
351
+
352
+ let query = "SELECT associatedDevice FROM ?? where id = ?";
353
+ let args = ["devices",deviceId];
354
+ query = mysql.format(query,args);
355
+
356
+ $.db.queryRow(query)
357
+ .then( rows => {
358
+ if(rows.length > 0)
359
+ return resolve(rows[0]?.associatedDevice);
360
+ else
361
+ return resolve(null);
362
+ })
363
+ .catch( err => {
364
+ return reject(err);
365
+ });
366
+
367
+ });
368
+ },
369
+
370
+ updateAssociatedDevice : async(deviceId,associatedDeviceId)=>{
371
+ return new Promise((resolve,reject) => {
372
+ let obj = {
373
+ associatedDevice : associatedDeviceId,
374
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
375
+ }
376
+
377
+ let filter = {
378
+ id : deviceId
379
+ };
380
+
381
+ $.db.update("devices",obj,filter)
382
+ .then (rows => {
383
+ return resolve(rows[0]);
384
+ })
385
+ .catch(error => {
386
+ return reject(error);
387
+ });
388
+
389
+ });
390
+ }
391
+
197
392
  }
package/src/db/fota.js CHANGED
@@ -7,7 +7,7 @@ var self = module.exports = {
7
7
 
8
8
  return new Promise((resolve,reject) => {
9
9
 
10
- let query = `SELECT COUNT(*) FROM ?? where
10
+ let query = `SELECT * FROM ?? where
11
11
  device_id = ? and
12
12
  target_version = ? and
13
13
  target_app_version = ? and
@@ -91,13 +91,13 @@ var self = module.exports = {
91
91
  obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
92
92
  obj['device_id'] = deviceId;
93
93
 
94
- $.db.insert("fota",obj)
95
- .then (rows => {
96
- return resolve(rows[0]);
97
- })
98
- .catch(error => {
99
- return reject(error);
100
- });
94
+ $.db.insert("fota",obj)
95
+ .then (rows => {
96
+ return resolve(rows[0]);
97
+ })
98
+ .catch(error => {
99
+ return reject(error);
100
+ });
101
101
 
102
102
  }else{
103
103
 
@@ -106,18 +106,18 @@ var self = module.exports = {
106
106
  };
107
107
 
108
108
  $.db.update("fota",obj,filter)
109
- .then (rows => {
110
- return resolve(rows[0]);
111
- })
112
- .catch(error => {
113
- return reject(error);
114
- });
109
+ .then (rows => {
110
+ return resolve(rows[0]);
111
+ })
112
+ .catch(error => {
113
+ return reject(error);
114
+ });
115
115
  }
116
116
 
117
117
  });
118
118
  },
119
119
 
120
- getDeviceLastLog : async(deviceId)=>{
120
+ getFotaLastLog : async(deviceId)=>{
121
121
 
122
122
  return new Promise((resolve,reject) => {
123
123
 
@@ -127,7 +127,7 @@ var self = module.exports = {
127
127
  LIMIT 1`;
128
128
 
129
129
  let table = [
130
- "fota",
130
+ "logs_fota",
131
131
  deviceId,
132
132
  ];
133
133
  query = mysql.format(query,table);
@@ -195,7 +195,7 @@ var self = module.exports = {
195
195
 
196
196
  return new Promise(async (resolve,reject) => {
197
197
 
198
- const log = await getDeviceLastLog(deviceId);
198
+ const log = await self.getFotaLastLog(deviceId);
199
199
 
200
200
  if(log?.createdAt != log?.updatedAt)
201
201
 
@@ -1,6 +1,6 @@
1
1
  const moment = require('moment');
2
2
 
3
- var project = [];
3
+ var _project = [];
4
4
  const logs_table = "sensor_logs";
5
5
  const semver = require('semver');
6
6
 
@@ -14,11 +14,11 @@ var self = module.exports = {
14
14
 
15
15
  projects.map( async (name,counter)=>{
16
16
  console.log("project:",name)
17
- project[name] = {
17
+ _project[name] = {
18
18
  module : null
19
19
  };
20
- project[name].module = require(`${BASE_DIR}/projects/${name}/${name}.js`)
21
- project[name].module?.init();
20
+ _project[name].module = require(`${BASE_DIR}/projects/${name}/${name}.js`)
21
+ _project[name].module?.init();
22
22
  let row = await $.db_project.getByName(name);
23
23
  if(row == null)
24
24
  $.db_project.insert(name,name,"logs_"+name);
@@ -78,33 +78,42 @@ var self = module.exports = {
78
78
  }
79
79
 
80
80
  // update project id if needed
81
- if(project_id != null && project_id != device?.project_id)
81
+ if(project_id != null && project_id != device?.project_id){
82
82
  $.db_device.update(device.id,"project_id",project_id);
83
+ $.db_device.addLog(device.id,"project_id",project_id);
84
+ }
83
85
 
84
86
  switch (topic) {
85
87
  case "status":
86
88
  if (payload === "online" || payload === "offline") {
87
89
  await $.db_device.update(device.id, "status", payload);
90
+ $.db_device.addLog(device.id,"status",payload);
88
91
  }
89
92
  break;
90
93
  case "model":
91
94
  let res = await $.db_model.getByName(payload);
92
95
  let model_id = res?.id;
93
- if (model_id != null) {
96
+ if (model_id != null && device?.tech != payload) {
94
97
  await $.db_device.update(device.id, "model_id", model_id);
98
+ $.db_device.addLog(device.id,"model_id",model_id);
95
99
  }
96
100
  break;
97
101
  case "tech":
98
- await $.db_device.update(device.id, "tech", payload);
102
+ if (device?.tech && payload != device.tech) {
103
+ await $.db_device.update(device.id, "tech", payload);
104
+ $.db_device.addLog(device.id,"tech",payload);
105
+ }
99
106
  break;
100
107
  case "version":
101
108
  if (device?.version && payload != device.version) {
109
+ $.db_device.addLog(device.id,"version",payload);
102
110
  await $.db_device.update(device.id, "version", payload);
103
111
  await self.handleFotaSuccess(device.id);
104
112
  }
105
113
  break;
106
114
  case "app_version":
107
115
  if (device?.app_version && payload != device.app_version) {
116
+ $.db_device.addLog(device.id,"app_version",payload);
108
117
  await $.db_device.update(device.id, "app_version", payload);
109
118
  await self.handleFotaSuccess(device.id);
110
119
  }
@@ -118,8 +127,38 @@ var self = module.exports = {
118
127
  break;
119
128
  }
120
129
 
121
- if(topic.startsWith("sensor/")){
122
-
130
+ if(topic.startsWith("settings/") && topic.endsWith("/set") && payload != "" ){
131
+ // update local settings
132
+ let index = topic.indexOf("settings/");
133
+ topic = topic.substring(index+9);
134
+ self.updateLocalSettings(device,topic,payload);
135
+ }else if(topic.startsWith("settings/") && !topic.endsWith("/set") && payload != "" ){
136
+ // store remote device settings
137
+ let index = topic.indexOf("settings/");
138
+ topic = topic.substring(index+9);
139
+ self.updateRemoteSettings(device,topic,payload);
140
+ }else if(topic == "fw"){
141
+ try{
142
+ payload = JSON.parse(payload);
143
+ }catch(error){}
144
+ if(typeof payload === 'object' && payload !== null){
145
+ try{
146
+ $.db_data.updateJson("fw",device.id,payload);
147
+ $.db_data.addJsonLog("logs_fw",device.id,payload);
148
+ }catch(error){
149
+ console.error(error)
150
+ }
151
+ }else if(typeof payload !== 'object' && payload !== null){
152
+ // change it to topic.startsWith("fw")
153
+ try{
154
+ const column = getWordAfterLastSlash(topic);
155
+ $.db_data.update("fw",device.id,column,payload);
156
+ $.db_data.addLog("logs_fw",device.id,column,payload);
157
+ }catch(error){
158
+ console.error(error)
159
+ }
160
+ }
161
+ }else if(topic.startsWith("sensor/")){
123
162
  updateSensor(device,topic,paylaod)
124
163
  index = topic.indexOf("/");
125
164
  if(index == -1)
@@ -132,13 +171,8 @@ var self = module.exports = {
132
171
  }
133
172
  }
134
173
 
135
- // store remote device settings on project table - twin model
136
- if(topic.endsWith("/set") && payload != "" ){
137
- self.updateSettings(project_name,device,topic,payload);
138
- }
139
-
140
- if(project[project_name]){
141
- project[project_name].module.parseMessage(client,project_name,device,topic,payload,retain,()=>{});
174
+ if(_project[project_name]){
175
+ _project[project_name]?.module?.parseMessage(client,project_name,device,topic,payload,retain,()=>{});
142
176
  }
143
177
  }
144
178
 
@@ -162,49 +196,115 @@ var self = module.exports = {
162
196
  }
163
197
  },
164
198
 
165
- updateSettings : async (project_name,device,topic,payload)=>{
199
+ updateLocalSettings: async (device, topic, payload) => {
200
+
201
+ $.db_device.addLog(device.id,"local_settings",JSON.stringify(payload));
202
+
166
203
  let route = topic.split("/");
167
204
 
168
- if(route == null){
169
- console.log("topic invalid:",topic);
205
+ if (route == null || route.length == 0) {
206
+ console.warn("updateLocalSettings: topic invalid:", topic);
170
207
  return;
171
208
  }
172
- // get settings
173
- let settings = await $.db_project.getSettings(project_name,device.id);
174
- let obj = settings;
175
209
 
176
- if(obj == null){
177
- obj = {};
210
+ // Retrieve existing settings
211
+ let settings = await $.db_device.getLocalSettings(device.id);
212
+
213
+ if (!settings || typeof settings !== 'object') {
214
+ settings = {};
178
215
  }
179
- // Traverse through all route parts except the last one
216
+
217
+ let obj = settings;
218
+
219
+ // Traverse route parts to reach the target object
180
220
  route.slice(0, -1).forEach(property => {
181
- if (!obj.hasOwnProperty(property) ||
182
- ( obj.hasOwnProperty(property) && typeof obj[property] !== 'object'))
183
- {
221
+ if (
222
+ !Object.prototype.hasOwnProperty.call(obj, property) ||
223
+ (obj.hasOwnProperty(property) && typeof obj[property] !== 'object') ||
224
+ obj[property] === null
225
+ ) {
226
+ obj[property] = {}; // Create nested object if missing or not an object
227
+ }
228
+ obj = obj[property];
229
+ });
230
+
231
+ // Parse the payload JSON
232
+ let data = {};
233
+ try {
234
+ data = JSON.parse(payload);
235
+ } catch (error) {
236
+ console.error("Failed to parse payload JSON:", error);
237
+ return;
238
+ }
239
+
240
+ // Check if the data is a plain object, then merge
241
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
242
+ Object.assign(obj, data);
243
+ } else {
244
+ console.warn("Payload is not a valid object:", payload);
245
+ return;
246
+ }
247
+
248
+ try {
249
+ // Update the settings in the database
250
+ await $.db_device.updateLocalSettings(JSON.stringify(settings), device.id);
251
+ } catch (err) {
252
+ console.error("Failed to update local settings:", err);
253
+ }
254
+ },
255
+
256
+ updateRemoteSettings : async (device,topic,payload)=>{
257
+
258
+ $.db_device.addLog(device.id,"remote_settings",JSON.stringify(payload));
259
+
260
+ let route = topic.split("/");
261
+
262
+ if(route == null){
263
+ console.warn("updateRemoteSettings: topic invalid:",topic);
264
+ return;
265
+ }
266
+ // Parse existing settings
267
+ let settings = await $.db_device.getRemoteSettings(device.id);
268
+
269
+ if (!settings || typeof settings !== 'object') {
270
+ settings = {};
271
+ }
272
+
273
+ let obj = settings;
274
+
275
+ // Traverse route parts
276
+ route.slice(0, route.length).forEach(property => {
277
+ if (
278
+ !Object.prototype.hasOwnProperty.call(obj, property) ||
279
+ (obj.hasOwnProperty(property) && typeof obj[property] !== 'object') ||
280
+ obj[property] === null
281
+ ) {
184
282
  obj[property] = {}; // create nested object if missing or not an object
185
283
  }
186
- obj = obj[property]; // go deeper
187
- })
188
-
284
+ obj = obj[property];
285
+ });
286
+
287
+ // Merge payload into nested object
189
288
  let data = {};
190
- try{
191
- data = JSON.parse(payload)
192
- }catch(error){}
193
-
194
- if ((data && typeof payload === 'object' && !Array.isArray(payload) ) ) {
195
- // Assuming payload is an object with properties to process
289
+ try {
290
+ data = JSON.parse(payload);
291
+ } catch(error) {
292
+ }
293
+
294
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
295
+ // Merge data properties
196
296
  for (const [key, value] of Object.entries(data)) {
197
- obj[key] = value; // go deeper
198
- };
199
- }else{
200
- obj = payload
297
+ obj[key] = value;
298
+ }
299
+ } else {
300
+ // payload isn't an object, replace the nested object
301
+ obj = payload;
201
302
  }
202
303
 
203
- // update on device fw settings
204
- try{
205
- await $.db_project.updateSettings(project_name,JSON.stringify(settings),device.id);
206
- }catch(error){
207
- console.log(error);
304
+ try {
305
+ await $.db_device.updateRemoteSettings(JSON.stringify(settings), device.id);
306
+ } catch (err) {
307
+ console.error("Failed to update local settings:", err);
208
308
  }
209
309
  },
210
310
 
@@ -214,12 +314,15 @@ var self = module.exports = {
214
314
 
215
315
  for (const model of models) {
216
316
 
317
+ console.log("model:",model?.name);
217
318
  if(!model?.id)
218
319
  continue;
219
320
 
220
321
  try{
221
322
  const latestVersion = await $.db_firmware.getLatestVersion(model.id,release);
222
323
  const latestAppVersion = await $.db_firmware.getLatestAppVersion(model.id,release);
324
+ console.log("latestVersion:",latestVersion?.version);
325
+ console.log("latestAppVersion:",latestAppVersion?.app_version);
223
326
 
224
327
  const devices = await $.db_device.listByModel(model.id);
225
328
 
@@ -256,23 +359,31 @@ var self = module.exports = {
256
359
  };
257
360
  }
258
361
  if(obj != null){
259
- try{
260
- let res = await $.db_fota.getEntry(device.id,obj);
261
- if(res == null)
262
- $.db_fota.update(device.id,obj);
263
- }catch(error){
264
- console.log(error)
362
+ try {
363
+
364
+ let res = await $.db_fota.getEntry(device.id, obj);
365
+
366
+ if (res == null) {
367
+ try {
368
+ console.log("add fota entry for device:", device.uid);
369
+ await $.db_fota.update(device.id, obj);
370
+ } catch (err) {
371
+ console.error("Error updating FOTA entry:", err);
372
+ }
373
+ }
374
+
375
+ } catch (error) {
376
+ console.error("Error getting or processing FOTA entry:", error);
265
377
  }
266
378
  }
267
379
  }
268
380
  }catch(error){
269
- console.log(error);
381
+ console.error(error);
270
382
  continue;
271
383
  }
272
384
  }
273
385
  },
274
386
 
275
-
276
387
  triggerFota : async (release = "dev")=>{
277
388
 
278
389
  const devices = await $.db_fota.getUpdatable(release);
@@ -290,21 +401,27 @@ var self = module.exports = {
290
401
  const model_name = model?.name;
291
402
  let topic = "";
292
403
  if(model_name == "sniffer"){
404
+ resolve();
405
+ // !! This cannot be handled on this way
406
+
293
407
  // get sniffer info associated to device
294
- const sniffer = await $.db_data.getGwAssociatedToDevice("sniffer",device.uid);
408
+ const sniffer = await $.db_data.getAssociatedToDevice("sniffer",device.id);
295
409
  if(sniffer == null) return;
296
410
  // get device_uid from devices table
297
411
  const gw = await $.db_device.getById(sniffer?.id)
298
412
  if(gw == null) return;
299
413
  let mqtt_prefix = `${project_name}/${gw.uid}`;
300
- topic = mqtt_prefix+"/app/sniffer/fota/update/set";
414
+ if (semver.gt(sniffer.version, "2.0.1"))
415
+ topic = mqtt_prefix+`/app/sniffer/${sniffer.uid}/fota/update/set`;
416
+ else
417
+ topic = mqtt_prefix+`/app/sniffer/fota/update/set`;
301
418
  }
302
419
  else{
303
420
  let mqtt_prefix = `${project_name}/${device.uid}`;
304
421
  topic = mqtt_prefix+"/fw/fota/update/set";
305
422
  }
306
423
  let link = `${$.config.web.protocol}${$.config.web.domain}${$.config.web.fw_path}${firmware?.filename}/download?token=${firmware?.token}`;
307
- console.log(`Requesting firmware update of ${device.uid} to ${firmware?.filename}`);
424
+ console.log(`Requesting firmware update for ${device.uid} to ${firmware?.filename}`);
308
425
  $.mqtt_client.publish(topic,`{"url":"${link}"}`,{qos:1,retain:false});
309
426
 
310
427
  let obj = {
@@ -343,14 +460,14 @@ var self = module.exports = {
343
460
  object = {
344
461
  success : 1,
345
462
  }
346
- await $.db_fota.updateLog(deviceId,obj);
463
+ await $.db_fota.updateLog(deviceId,object);
347
464
  },
348
465
 
349
466
  handleFotaError : async (deviceId, error) => {
350
467
  let object = {
351
468
  error : error,
352
469
  }
353
- await $.db_fota.updateLog(deviceId,obj);
470
+ await $.db_fota.updateLog(deviceId,object);
354
471
  }
355
472
  }
356
473