mqtt-devices-parser 1.0.24 → 1.0.25

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,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.25
4
+
5
+ Sensors template (#9)
6
+
7
+ * new table sensorsTemplate
8
+
9
+ * store topics which match a sensor
10
+ for each mqtt msg received, check if there is a sensor associated to that topic.
11
+ If there is, update current value and insert new log
12
+
13
+ * db: models/sensors
14
+ changes localUnixTs field to remoteUnixTs
15
+ adds value, error
16
+ changes property: allow null
17
+ adds foreign keys to model_id and device_id
18
+
19
+ * handle change db column localUnixTs to remoteUnixTs
20
+
21
+ * fix getSensorsByRef
22
+ ref is not unique so it can have more than 1 row
23
+
24
+ * src/db/data: Implements missing function pathIntoObject
25
+
26
+ * src/aux/parser: adds functions to handle mqtt topics parsing
27
+ index: uses global $.parser as a pointer to class src/aux/parser
28
+ src/device/device: fixes null iterations, sets updateSensor and handleMqttTopic as public functions. Removes local mqtt parser functions. Adapts calls to those functions
29
+
30
+ mqtt: always check if topic is registered
31
+ store values in db
32
+
3
33
  ## 1.0.24
4
34
  src/device/device: fix log
5
35
  src/kafka/consumer: increase initialRetryTime from 100 to 300ms
package/index.js CHANGED
@@ -17,6 +17,7 @@ $.db_firmware = require('./src/db/firmware');
17
17
  $.db_sensor = require('./src/db/sensor');
18
18
  $.db_fota = require('./src/db/fota');
19
19
  $.mqtt_client = null;
20
+ $.parser = require('./src/aux/parser')
20
21
 
21
22
  const packageJson = require(__dirname+'/package.json');
22
23
  const packageVersion = packageJson.version;
@@ -30,7 +30,7 @@ module.exports = (sequelize,DataTypes)=>{
30
30
  type: DataTypes.STRING,
31
31
  allowNull: true,
32
32
  },
33
- localUnixTs: {
33
+ remoteUnixTs: {
34
34
  type: DataTypes.BIGINT,
35
35
  allowNull: true,
36
36
  }
@@ -3,11 +3,19 @@ module.exports = (sequelize,DataTypes)=>{
3
3
  return sequelize.define("sensors", {
4
4
  model_id: { // reference a model
5
5
  type: DataTypes.INTEGER,
6
- allowNull: true,
6
+ allowNull: false,
7
+ references: {
8
+ model: 'models',
9
+ key: 'id'
10
+ }
7
11
  },
8
12
  device_id: { // reference a device id
9
13
  type: DataTypes.INTEGER,
10
- allowNull: true,
14
+ allowNull: false,
15
+ references: {
16
+ model: 'devices',
17
+ key: 'id'
18
+ }
11
19
  },
12
20
  active: {
13
21
  type: DataTypes.BOOLEAN,
@@ -28,7 +36,19 @@ module.exports = (sequelize,DataTypes)=>{
28
36
  },
29
37
  property: {
30
38
  type: DataTypes.STRING,
31
- allowNull: false,
39
+ allowNull: true
40
+ },
41
+ value: {
42
+ type: DataTypes.STRING,
43
+ allowNull: true
44
+ },
45
+ error: {
46
+ type: DataTypes.STRING,
47
+ allowNull: true,
48
+ },
49
+ remoteUnixTs: {
50
+ type: DataTypes.BIGINT,
51
+ allowNull: true,
32
52
  },
33
53
  graph: {
34
54
  type: DataTypes.JSON,
@@ -0,0 +1,43 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("sensorsTemplate", {
4
+ model_id: { // reference a model
5
+ type: DataTypes.INTEGER,
6
+ allowNull: false,
7
+ references: {
8
+ model: 'models',
9
+ key: 'id'
10
+ }
11
+ },
12
+ active: {
13
+ type: DataTypes.BOOLEAN,
14
+ allowNull: false,
15
+ defaultValue: true
16
+ },
17
+ ref: {
18
+ type: DataTypes.STRING,
19
+ allowNull: false,
20
+ },
21
+ name: {
22
+ type: DataTypes.STRING,
23
+ allowNull: false,
24
+ },
25
+ type: {
26
+ type: DataTypes.STRING,
27
+ allowNull: false,
28
+ },
29
+ property: {
30
+ type: DataTypes.STRING,
31
+ allowNull: true
32
+ },
33
+ graph: {
34
+ type: DataTypes.JSON,
35
+ allowNull: true,
36
+ }
37
+ },
38
+ {
39
+ tableName: 'sensorsTemplate',
40
+ freezeTableName: true
41
+ })
42
+ }
43
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mqtt-devices-parser",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/aux/parser.js CHANGED
@@ -16,5 +16,41 @@ module.exports = {
16
16
  }
17
17
  });
18
18
  return obj;
19
+ },
20
+
21
+ getFirstWord : (str)=>{
22
+ const slashIndex = str.indexOf('/');
23
+ if (slashIndex === -1) {
24
+ // No slash found, return the original string
25
+ return str;
26
+ }
27
+ return str.substring(0,slashIndex);
28
+ },
29
+
30
+ getTopicAfterSlash : (str)=>{
31
+ const slashIndex = str.indexOf('/');
32
+ if (slashIndex === -1) {
33
+ // No slash found, return empty string
34
+ return "";
35
+ }
36
+ return str.substring(slashIndex + 1);
37
+ },
38
+
39
+ getWordAfterLastSlash : (str)=>{
40
+ const lastSlashIndex = str.lastIndexOf('/');
41
+ if (lastSlashIndex === -1) {
42
+ // No slash found, return the original string
43
+ return str;
44
+ }
45
+ return str.substring(lastSlashIndex + 1);
46
+ },
47
+
48
+ getWordBeforeLastSlash : (str)=>{
49
+ const lastSlashIndex = str.lastIndexOf('/');
50
+ if (lastSlashIndex === -1) {
51
+ // No slash found, return the original string
52
+ return str;
53
+ }
54
+ return str.substring(0,lastSlashIndex);
19
55
  }
20
56
  }
package/src/db/data.js CHANGED
@@ -372,3 +372,59 @@ var self = module.exports = {
372
372
  });
373
373
  }
374
374
  };
375
+
376
+ /**
377
+ * Build a nested object from a path string and a leaf value.
378
+ *
379
+ * Example:
380
+ * pathIntoObject('foo/bar/baz', 123) -> { foo: { bar: { baz: 123 } } }
381
+ *
382
+ * Notes:
383
+ * - By default, splits on '/'.
384
+ * - Leading/trailing/duplicate delimiters are ignored (e.g., '/a//b/' -> ['a','b']).
385
+ * - Value is used as-is. If you pass JSON.stringify(data), the leaf will be that string.
386
+ *
387
+ * @param {string} path - The path to turn into nested object keys (e.g., 'a/b/c').
388
+ * @param {*} value - The value to place at the final key.
389
+ * @param {Object} [options]
390
+ * @param {string} [options.delimiter='/'] - Path delimiter.
391
+ * @returns {*}
392
+ */
393
+ const parser = {
394
+ pathIntoObject(path, value, options = {}) {
395
+ const delimiter = options.delimiter || '/';
396
+
397
+ if (typeof path !== 'string') {
398
+ throw new TypeError('path must be a string');
399
+ }
400
+
401
+ // Normalize path: remove empty segments caused by leading/trailing or duplicate delimiters
402
+ const segments = path
403
+ .split(delimiter)
404
+ .map(s => s.trim())
405
+ .filter(Boolean);
406
+
407
+ // If no segments, just return the value directly
408
+ if (segments.length === 0) return value;
409
+
410
+ // Build nested object
411
+ let root = {};
412
+ let cursor = root;
413
+
414
+ for (let i = 0; i < segments.length; i++) {
415
+ const key = segments[i];
416
+ const isLast = i === segments.length - 1;
417
+
418
+ if (isLast) {
419
+ cursor[key] = value;
420
+ } else {
421
+ // Create the next level if not present
422
+ cursor[key] = {};
423
+ cursor = cursor[key];
424
+ }
425
+ }
426
+
427
+ return root;
428
+ },
429
+ };
430
+
package/src/db/device.js CHANGED
@@ -388,7 +388,7 @@ var self = module.exports = {
388
388
  });
389
389
  },
390
390
 
391
- getSensorByRef : async(deviceId, ref)=>{
391
+ getSensorsByRef : async(deviceId, ref)=>{
392
392
  return new Promise((resolve,reject) => {
393
393
 
394
394
  let query = "SELECT * FROM ?? where device_id = ? and ref = ?";
@@ -398,7 +398,7 @@ var self = module.exports = {
398
398
  $.db.queryRow(query)
399
399
  .then( rows => {
400
400
  if(rows.length > 0)
401
- return resolve(rows[0]);
401
+ return resolve(rows);
402
402
  else
403
403
  return resolve(null);
404
404
  })
package/src/db/model.js CHANGED
@@ -112,7 +112,7 @@ var self = module.exports = {
112
112
  });
113
113
  },
114
114
 
115
- getSensorByRef : async(modelId, ref)=>{
115
+ getSensorsByRef : async(modelId, ref)=>{
116
116
  return new Promise((resolve,reject) => {
117
117
 
118
118
  let query = "SELECT * FROM ?? where model_id = ? and ref = ?";
@@ -122,7 +122,7 @@ var self = module.exports = {
122
122
  $.db.queryRow(query)
123
123
  .then( rows => {
124
124
  if(rows.length > 0)
125
- return resolve(rows[0]);
125
+ return resolve(rows);
126
126
  else
127
127
  return resolve(null);
128
128
  })
package/src/db/sensor.js CHANGED
@@ -26,6 +26,7 @@ var self = module.exports = {
26
26
  });
27
27
  },
28
28
 
29
+ // not used !!
29
30
  getByRef : async (ref)=>{
30
31
 
31
32
  return new Promise((resolve,reject) => {
@@ -98,7 +99,7 @@ var self = module.exports = {
98
99
  value : payload?.value,
99
100
  error : payload?.error,
100
101
  obj : payload?.object,
101
- localUnixTs : payload?.timestamp, // local timestamp
102
+ remoteUnixTs : payload?.timestamp, // local timestamp
102
103
  createdAt : moment().utc().format('YYYY-MM-DD HH:mm:ss'),
103
104
  updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
104
105
  }
@@ -113,4 +114,16 @@ var self = module.exports = {
113
114
  });
114
115
  },
115
116
 
117
+ update : async(table,obj,filter)=>{
118
+ return new Promise((resolve,reject) => {
119
+
120
+ $.db.update(table,obj,filter)
121
+ .then (rows => {
122
+ return resolve(rows);
123
+ })
124
+ .catch(error => {
125
+ return reject(error);
126
+ });
127
+ });
128
+ },
116
129
  }
@@ -2,6 +2,7 @@ const moment = require('moment');
2
2
  const { isDeepStrictEqual } = require('node:util');
3
3
 
4
4
  var _project = [];
5
+ const table = "sensors"
5
6
  const logs_table = "logs_sensor";
6
7
  const semver = require('semver');
7
8
 
@@ -30,8 +31,6 @@ var self = module.exports = {
30
31
  })
31
32
  })
32
33
  });
33
-
34
-
35
34
  },
36
35
 
37
36
  parseMessage : async (client,topic,payload,retain)=>{
@@ -49,22 +48,22 @@ var self = module.exports = {
49
48
  }catch(err){};
50
49
 
51
50
  // --- project ---
52
- project_name = getFirstWord(topic);
51
+ project_name = $.parser.getFirstWord(topic);
53
52
  project = await $.db_project.getByName(project_name);
54
53
  if(project == null)
55
54
  return;
56
55
 
57
56
  project_id = project?.id;
58
- topic = getWordAfterSlash(topic)
57
+ topic = $.parser.getTopicAfterSlash(topic)
59
58
 
60
59
  // check if is from lwm2m gw
61
60
  if(topic.startsWith("responses") || topic.startsWith("requests")){
62
- action = getFirstWord(topic);
63
- topic = getWordAfterSlash(topic);
61
+ action = $.parser.getFirstWord(topic);
62
+ topic = $.parser.getTopicAfterSlash(topic);
64
63
  }
65
64
 
66
65
  // --- uid ---
67
- uid = getFirstWord(topic);
66
+ uid = $.parser.getFirstWord(topic);
68
67
  // check if topic corresponds to a device
69
68
  if(!uid.startsWith(project.uidPrefix) || uid.length > project?.uidLength)
70
69
  return;
@@ -73,14 +72,13 @@ var self = module.exports = {
73
72
  if(!device)
74
73
  return;
75
74
 
76
- topic = getWordAfterSlash(topic);
75
+ topic = $.parser.getTopicAfterSlash(topic);
77
76
 
78
77
  if(device.protocol.toLowerCase() === "lwm2m"){
79
78
  parseLwm2mMessage(client, project_name, device, topic, payload, action);
80
79
  }else if(device.protocol.toLowerCase() === "mqtt"){
81
80
  parseMqttMessage(client, project_name, device, topic, payload, retain);
82
81
  }
83
-
84
82
  },
85
83
 
86
84
  deleteLogs : async()=>{
@@ -105,6 +103,9 @@ var self = module.exports = {
105
103
 
106
104
  const models = await $.db_model.getAll();
107
105
 
106
+ if(!models || !models?.length)
107
+ return;
108
+
108
109
  for (const model of models) {
109
110
 
110
111
  //console.log("model:",model?.name);
@@ -181,6 +182,9 @@ var self = module.exports = {
181
182
 
182
183
  const devices = await $.db_fota.getUpdatable(release);
183
184
 
185
+ if(!devices || !!devices?.length)
186
+ return;
187
+
184
188
  const batchSize = 10;
185
189
  for (let i = 0; i < devices.length; i += batchSize) {
186
190
  const batch = devices.slice(i, i + batchSize);
@@ -247,6 +251,91 @@ var self = module.exports = {
247
251
  }
248
252
  },
249
253
 
254
+
255
+ updateSensor : async (device,ref,payload)=>{
256
+
257
+ let sensors = await $.db_device.getSensorsByRef(device.id,ref)
258
+
259
+ if(!sensors?.length)
260
+ return;
261
+
262
+ object = payload;
263
+ value = null;
264
+ error = null;
265
+ timestamp = null;
266
+
267
+ sensors.map( (sensor,index) =>{
268
+ let value = null;
269
+ let error = null;
270
+ let remoteUnixTs = null;
271
+ if(sensor?.type === "json" && typeof object === 'object'){
272
+ if(object.hasOwnProperty(sensor?.property)){
273
+ value = object[sensor.property];
274
+ }
275
+ }else{
276
+ if (typeof object === 'object') {
277
+ value = object?.value || object?.v;
278
+ error = object?.error || object?.e;
279
+ remoteUnixTs = object?.timestamp || objects?.ts;
280
+ }else{
281
+ value = payload;
282
+ }
283
+ }
284
+ if(value || error){
285
+
286
+ if(!remoteUnixTs)
287
+ remoteUnixTs = moment().unix()
288
+
289
+ const data = {
290
+ value,
291
+ error,
292
+ remoteUnixTs
293
+ }
294
+
295
+ let filter = {
296
+ id : sensor.id
297
+ }
298
+
299
+ $.db_sensor.update(table,data,filter);
300
+ $.db_sensor.insert(logs_table,device.id,sensor.id,data);
301
+ }
302
+ })
303
+ },
304
+
305
+ handleMqttTopic : async(device, dbTopic, payload, set)=>{
306
+ if(set){
307
+ // update local topic
308
+ $.db_device.updateLocalTopic(dbTopic.id,payload)
309
+ .then(()=>{
310
+ // set as not synched
311
+ $.db_device.setSynchedTopic(dbTopic.id,false);
312
+ })
313
+ .catch((error)=>{
314
+ console.error(error);
315
+ })
316
+ }else{
317
+ // update remote topic
318
+ $.db_device.updateRemoteTopic(dbTopic.id,payload)
319
+ .then(async (res)=>{
320
+ // check if topics mismatch
321
+ if(isDeepStrictEqual(dbTopic?.localData, dbTopic?.remoteData)){
322
+ $.db_device.setSynchedTopic(dbTopic.id,true);
323
+ }else{
324
+ // set as not synched
325
+ await $.db_device.setSynchedTopic(dbTopic.id,false);
326
+ if(dbTopic?.synch){ // check if sync is enabled
327
+ // synch topic
328
+ synchMqttTopic(device,dbTopic);
329
+ }
330
+ }
331
+ })
332
+ .catch((error)=>{
333
+ console.error(error);
334
+ })
335
+
336
+ }
337
+ },
338
+
250
339
  }
251
340
 
252
341
  async function parseLwm2mMessage(client, project_name, device, topic, payload, action){
@@ -257,8 +346,8 @@ async function parseLwm2mMessage(client, project_name, device, topic, payload, a
257
346
  payload = JSON.parse(payload);
258
347
  }catch(error){}
259
348
 
260
- let word = getFirstWord(topic);
261
- topic = getWordAfterSlash(topic);
349
+ let word = $.parser.getFirstWord(topic);
350
+ topic = $.parser.getTopicAfterSlash(topic);
262
351
 
263
352
  switch (word) {
264
353
  case "status":
@@ -269,7 +358,7 @@ async function parseLwm2mMessage(client, project_name, device, topic, payload, a
269
358
  return;
270
359
  break;
271
360
  case "sensor":
272
- updateSensor(device,topic,payload)
361
+ self.updateSensor(device,topic,payload)
273
362
  }
274
363
 
275
364
  if(_project[project_name]){
@@ -289,8 +378,8 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
289
378
  payload = JSON.parse(payload);
290
379
  }catch(error){}
291
380
 
292
- let word = getFirstWord(topic);
293
- topic = getWordAfterSlash(topic);
381
+ let word = $.parser.getFirstWord(topic);
382
+ topic = $.parser.getTopicAfterSlash(topic);
294
383
 
295
384
  switch (word) {
296
385
  case "status":
@@ -299,6 +388,7 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
299
388
  $.db_device.addLog(device.id,"status",payload);
300
389
  }
301
390
 
391
+ // list mqtt topics and do calls to readable topics
302
392
  if (payload === "online"){
303
393
  let mqtt_prefix = `${project_name}/${device.uid}`;
304
394
  // check if remote settings are known, if not require it
@@ -323,7 +413,6 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
323
413
  $.mqtt_client.publish(topic,"",{qos:1,retain:false});
324
414
  }
325
415
  }
326
- return;
327
416
  break;
328
417
  case "model":
329
418
  let res = await $.db_model.getByName(payload);
@@ -332,14 +421,12 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
332
421
  $.db_device.update(device.id, "model_id", model_id);
333
422
  $.db_device.addLog(device.id,"model_id",model_id);
334
423
  }
335
- return;
336
424
  break;
337
425
  case "tech":
338
426
  if (payload != null && payload != device?.tech) {
339
427
  $.db_device.update(device.id, "tech", payload);
340
428
  $.db_device.addLog(device.id,"tech",payload);
341
429
  }
342
- return;
343
430
  break;
344
431
  case "version":
345
432
  if (payload != null && payload != device?.version) {
@@ -347,7 +434,6 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
347
434
  $.db_device.update(device.id, "version", payload);
348
435
  handleFotaSuccess(device.id);
349
436
  }
350
- return;
351
437
  break;
352
438
  case "app_version":
353
439
  if (payload != null && payload != device?.app_version) {
@@ -355,7 +441,6 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
355
441
  $.db_device.update(device.id, "app_version", payload);
356
442
  handleFotaSuccess(device.id);
357
443
  }
358
- return;
359
444
  break;
360
445
  case "fw":
361
446
  if(topic === "fota/update/status"){
@@ -371,7 +456,7 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
371
456
  }else if(typeof payload !== 'object' && payload !== null){
372
457
  // change it to topic.startsWith("fw")
373
458
  try{
374
- const column = getWordAfterLastSlash(topic);
459
+ const column = $.parser.getWordAfterLastSlash(topic);
375
460
  let rows = await $.db_data.update("fw",device.id,column,payload);
376
461
  rows = await $.db_data.addLog("logs_fw",device.id,column,payload);
377
462
  }catch(error){
@@ -379,7 +464,6 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
379
464
  }
380
465
  }
381
466
  }
382
- return;
383
467
  break;
384
468
  case "settings":
385
469
  if(topic.endsWith("/set")){
@@ -387,68 +471,39 @@ async function parseMqttMessage(client, project_name, device, topic, payload, re
387
471
  }else{
388
472
  updateRemoteSettings(device,topic,payload);
389
473
  }
390
- return;
391
- break;
392
- case "sensor":
393
- let ref = getFirstWord(topic)
394
- updateSensor(device,ref,payload)
395
- return;
396
474
  break;
397
475
  // Optional: default case if needed
398
476
  default:
399
- // handle other topics or do nothing
400
- // check if topic is associated with device
401
- let findTopic = topicBck;
402
- if(topicBck.endsWith("/set")) // remove set if exists on topic
403
- findTopic = getWordBeforeLastSlash(topicBck);
404
-
405
- const dbTopic = await $.db_device.getMqttTopic(device.id,findTopic)
406
- if(dbTopic != null){
407
- if(topicBck.endsWith("/set")){
408
- // update local topic
409
- $.db_device.updateLocalTopic(dbTopic.id,payload)
410
- .then(()=>{
411
- // set as not synched
412
- $.db_device.setSynchedTopic(dbTopic.id,false);
413
- })
414
- .catch((error)=>{
415
- console.error(error);
416
- })
417
- }else{
418
- // update remote topic
419
- $.db_device.updateRemoteTopic(dbTopic.id,payload)
420
- .then(async (res)=>{
421
- // check if topics mismatch
422
- if(isDeepStrictEqual(dbTopic?.localData, dbTopic?.remoteData)){
423
- $.db_device.setSynchedTopic(dbTopic.id,true);
424
- }else{
425
- // set as not synched
426
- await $.db_device.setSynchedTopic(dbTopic.id,false);
427
- if(dbTopic?.synch){ // check if sync is enabled
428
- // synch topic
429
- synchMqttTopic(device,dbTopic,findTopic);
430
- }
431
- }
432
- })
433
- .catch((error)=>{
434
- console.error(error);
435
- })
436
-
437
- }
438
- }
439
477
  break;
440
478
  }
441
479
 
480
+ // check if topic is associated with device
481
+ let findTopic = topicBck;
482
+ let set = false;
483
+ if(topicBck.endsWith("/set")){ // remove set if exists on topic
484
+ set = true;
485
+ findTopic = $.parser.getWordBeforeLastSlash(topicBck);
486
+ }
487
+
488
+ const dbTopic = await $.db_device.getMqttTopic(device.id,findTopic)
489
+ if(dbTopic != null){
490
+ self.handleMqttTopic(device,dbTopic,payload,set);
491
+ }
492
+
493
+ // check if topic is a sensor
494
+ if(!set)
495
+ self.updateSensor(device,topicBck,payload);
496
+
442
497
  if(_project[project_name]){
443
498
  _project[project_name]?.module?.parseMessage(client,project_name,device,`${word}/${topic}`,payload,retain,()=>{});
444
499
  }
445
500
  }
446
501
 
447
- async function synchMqttTopic(device,dbTopic,topicBck){
502
+ async function synchMqttTopic(device,dbTopic){
448
503
 
449
504
  const project = await $.db_project.getById(device.project_id);
450
505
  let mqtt_prefix = `${project.name}/${device.uid}`;
451
- let topic = `${mqtt_prefix}/${topicBck}/set`
506
+ let topic = `${mqtt_prefix}/${dbTopic.topic}/set`
452
507
  let payload = "";
453
508
  if(dbTopic?.remoteData && typeof dbTopic?.remoteData === 'object'){
454
509
  try{
@@ -589,47 +644,6 @@ async function synchSettings(device,key){
589
644
  }
590
645
  }
591
646
 
592
- async function updateSensor(device,ref,payload){
593
- let res = await $.db_device.getSensorByRef(device.id,ref)
594
- if(res == null)
595
- res = await $.db_model.getSensorByRef(device.model_id,ref)
596
- if(res == null)
597
- return;
598
-
599
- object = payload;
600
- value = null;
601
- error = null;
602
- timestamp = null;
603
-
604
- if(res?.type.toLowerCase() === "json"){
605
- if(res?.property && payload.hasOwnProperty(res?.property)){
606
- object = payload[res.property];
607
- }else{
608
- return;
609
- }
610
- }
611
-
612
- if (typeof object === 'object' && object !== null) {
613
- value = object?.value || object?.v;
614
- error = object?.error || object?.e;
615
- timestamp = object?.timestamp || objects?.ts;
616
- }else{
617
- value = payload;
618
- }
619
-
620
- if(value || error)
621
- object = null;
622
-
623
- const data = {
624
- object,
625
- value,
626
- error,
627
- timestamp
628
- }
629
-
630
- $.db_sensor.insert(logs_table,device.id,res.id,data);
631
- return;
632
- }
633
647
 
634
648
  function handleFotaSuccess (deviceId){
635
649
  let object = {
@@ -650,38 +664,4 @@ function handleFotaError (deviceId, error){
650
664
  $.db_fota.updateLog(deviceId,object);
651
665
  }
652
666
 
653
- function getFirstWord(str){
654
- const slashIndex = str.indexOf('/');
655
- if (slashIndex === -1) {
656
- // No slash found, return the original string
657
- return str;
658
- }
659
- return str.substring(0,slashIndex);
660
- }
661
-
662
- function getWordAfterSlash(str){
663
- const slashIndex = str.indexOf('/');
664
- if (slashIndex === -1) {
665
- // No slash found, return empty string
666
- return "";
667
- }
668
- return str.substring(slashIndex + 1);
669
- }
670
667
 
671
- function getWordAfterLastSlash(str){
672
- const lastSlashIndex = str.lastIndexOf('/');
673
- if (lastSlashIndex === -1) {
674
- // No slash found, return the original string
675
- return str;
676
- }
677
- return str.substring(lastSlashIndex + 1);
678
- }
679
-
680
- function getWordBeforeLastSlash(str){
681
- const lastSlashIndex = str.lastIndexOf('/');
682
- if (lastSlashIndex === -1) {
683
- // No slash found, return the original string
684
- return str;
685
- }
686
- return str.substring(0,lastSlashIndex);
687
- }