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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.33
4
+ feat(db): sensors supports readable option
5
+ feat(db): supports actuators, template actuators and logs actuators
6
+ feat: support actuators (actions,template and logs) (#18)
7
+ perf: Adopt labeled Pino logging (#17)
8
+ feat: add log.level parameter to config
9
+
3
10
  ## 1.0.32
4
11
  fix: handleFotaError call
5
12
 
package/config/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  module.exports = {
2
2
  version : "0.0.0",
3
3
  dev : process.env.dev || "true",
4
+ log : {
5
+ level : process.env.LOG_LEVEL || "trace"
6
+ },
4
7
  web:{
5
8
  protocol : process.env.HTTP_PROTOCOL || "http://",
6
9
  domain: process.env.DOMAIN || '10.168.1.162',
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ const logger = require('./src/logger').child({ label: 'MQTT' });
1
2
  const mqtt = require("mqtt");
2
3
  const fs = require('fs').promises;
3
4
 
@@ -15,6 +16,7 @@ $.db_device = require('./src/db/device');
15
16
  $.db_model = require('./src/db/model');
16
17
  $.db_firmware = require('./src/db/firmware');
17
18
  $.db_sensor = require('./src/db/sensor');
19
+ $.db_actuator = require('./src/db/actuator');
18
20
  $.db_fota = require('./src/db/fota');
19
21
  $.mqtt_client = null;
20
22
  $.parser = require('./src/aux/parser')
@@ -133,7 +135,7 @@ var self = module.exports = {
133
135
 
134
136
  function mqtt_connect(){
135
137
 
136
- console.log(`[MQTT] connecting to ${$.config.mqtt.host}:${$.config.mqtt.port}..`)
138
+ logger.info(`[MQTT] connecting to ${$.config.mqtt.host}:${$.config.mqtt.port}..`)
137
139
 
138
140
  const mqtt_prefix = $.config.mqtt.logs_path+"/"+$.config.mqtt.client;
139
141
  let checkFota = null;
@@ -167,18 +169,18 @@ function mqtt_connect(){
167
169
  $.mqtt_client.publish(mqtt_prefix+"/"+project,"deactive",{qos:2,retain:true});
168
170
  };
169
171
  })
170
- console.log(`[MQTT] connected`);
172
+ logger.info(`[MQTT] connected`);
171
173
 
172
174
  if (!$.config.kafka.enabled) {
173
175
  projects.map( project=>{
174
- console.log("[MQTT] subscribing project:",project);
176
+ logger.info("[MQTT] subscribing project:",project);
175
177
  $.mqtt_client.subscribe(project+"/#", (err) => {
176
178
  if(err){
177
- console.log("[MQTT] error");
178
- console.error(err);
179
+ logger.info("[MQTT] error");
180
+ logger.error(err);
179
181
  }
180
182
  else
181
- console.log("[MQTT] subscribed to project:",project);
183
+ logger.info("[MQTT] subscribed to project:",project);
182
184
  })
183
185
  })
184
186
  }
@@ -203,34 +205,34 @@ function mqtt_connect(){
203
205
  // Only parse MQTT messages if enabled in configuration
204
206
  if (!$.config.kafka.enabled) {
205
207
 
206
- console.log(`[MQTT] rx: ${topic.toString()}`);
208
+ logger.info(`[MQTT] rx: ${topic.toString()}`);
207
209
  // payload is Buffer
208
210
  $.device.parseMessage($.mqtt_client,topic.toString(),payload.toString(),packet.retain);
209
211
  }
210
212
  });
211
213
 
212
214
  $.mqtt_client.on("reconnect",()=>{
213
- console.log("[MQTT] reconnected")
215
+ logger.info("[MQTT] reconnected")
214
216
  });
215
217
 
216
218
  $.mqtt_client.on("close",()=>{
217
- console.log("[MQTT] closed")
219
+ logger.info("[MQTT] closed")
218
220
  checkFota = null;
219
221
  });
220
222
 
221
223
  $.mqtt_client.on("offline",()=>{
222
- console.log("[MQTT] offline")
224
+ logger.info("[MQTT] offline")
223
225
  checkFota = null;
224
226
  });
225
227
 
226
228
  $.mqtt_client.on("disconnect",(packet)=>{
227
- console.log(`[MQTT] disconnected`);
228
- console.log(packet);
229
+ logger.info(`[MQTT] disconnected`);
230
+ logger.info(packet);
229
231
  checkFota = null;
230
232
  })
231
233
 
232
234
  $.mqtt_client.on("error",(error)=>{
233
- console.log("[MQTT] error");
234
- console.error(error)
235
+ logger.info("[MQTT] error");
236
+ logger.error(error)
235
237
  })
236
238
  }
@@ -0,0 +1,61 @@
1
+ module.exports = (sequelize,DataTypes)=>{
2
+ return sequelize.define("actuators", {
3
+ model_id: {
4
+ type: DataTypes.INTEGER,
5
+ allowNull: true,
6
+ references: {
7
+ model: 'models',
8
+ key: 'id'
9
+ },
10
+ onDelete: 'CASCADE',
11
+ onUpdate: 'CASCADE'
12
+ },
13
+ device_id: {
14
+ type: DataTypes.INTEGER,
15
+ allowNull: true,
16
+ references: {
17
+ model: 'devices',
18
+ key: 'id'
19
+ },
20
+ onDelete: 'CASCADE',
21
+ onUpdate: 'CASCADE'
22
+ },
23
+ ref: {
24
+ type: DataTypes.STRING,
25
+ allowNull: false
26
+ },
27
+ name: {
28
+ type: DataTypes.STRING,
29
+ allowNull: false
30
+ },
31
+ type: {
32
+ type: DataTypes.ENUM('set', 'switch', 'number', 'text', 'json'),
33
+ allowNull: false
34
+ },
35
+ property: {
36
+ type: DataTypes.STRING,
37
+ allowNull: true,
38
+ defaultValue: ''
39
+ },
40
+ value: {
41
+ type: DataTypes.STRING,
42
+ allowNull: true
43
+ },
44
+ error: {
45
+ type: DataTypes.TEXT,
46
+ allowNull: true
47
+ },
48
+ active: {
49
+ type: DataTypes.BOOLEAN,
50
+ allowNull: true
51
+ },
52
+ graph: {
53
+ type: DataTypes.JSON,
54
+ allowNull: true
55
+ },
56
+ },
57
+ {
58
+ tableName: 'actuators',
59
+ freezeTableName: true
60
+ })
61
+ }
@@ -0,0 +1,47 @@
1
+ module.exports = (sequelize,DataTypes)=>{
2
+ return sequelize.define("actuatorsTemplate", {
3
+ model_id: {
4
+ type: DataTypes.INTEGER,
5
+ allowNull: false,
6
+ references: {
7
+ model: 'models',
8
+ key: 'id'
9
+ },
10
+ onDelete: 'CASCADE',
11
+ onUpdate: 'CASCADE'
12
+ },
13
+ ref: {
14
+ type: DataTypes.STRING,
15
+ allowNull: false
16
+ },
17
+ name: {
18
+ type: DataTypes.STRING,
19
+ allowNull: false
20
+ },
21
+ type: {
22
+ type: DataTypes.ENUM('set', 'switch', 'number', 'text', 'json'),
23
+ allowNull: false
24
+ },
25
+ property: {
26
+ type: DataTypes.STRING,
27
+ allowNull: true,
28
+ defaultValue: ''
29
+ },
30
+ value: {
31
+ type: DataTypes.STRING,
32
+ allowNull: true
33
+ },
34
+ active: {
35
+ type: DataTypes.BOOLEAN,
36
+ allowNull: true
37
+ },
38
+ graph: {
39
+ type: DataTypes.JSON,
40
+ allowNull: true
41
+ },
42
+ },
43
+ {
44
+ tableName: 'actuatorsTemplate',
45
+ freezeTableName: true
46
+ })
47
+ }
@@ -0,0 +1,42 @@
1
+ module.exports = (sequelize,DataTypes)=>{
2
+ return sequelize.define("logs_actuators", {
3
+ device_id: {
4
+ type: DataTypes.INTEGER,
5
+ allowNull: false,
6
+ references: {
7
+ model: 'devices',
8
+ key: 'id'
9
+ },
10
+ onDelete: 'CASCADE',
11
+ onUpdate: 'CASCADE'
12
+ },
13
+ actuator_id: {
14
+ type: DataTypes.INTEGER,
15
+ allowNull: false,
16
+ references: {
17
+ model: 'actuators',
18
+ key: 'id'
19
+ },
20
+ onDelete: 'CASCADE',
21
+ onUpdate: 'CASCADE'
22
+ },
23
+ value: {
24
+ type: DataTypes.STRING,
25
+ allowNull: true
26
+ },
27
+ error: {
28
+ type: DataTypes.STRING,
29
+ allowNull: true
30
+ },
31
+ confirmed: {
32
+ type: DataTypes.BOOLEAN,
33
+ default: false,
34
+ allowNull: false
35
+ }
36
+ },
37
+ {
38
+ tableName: 'logs_actuators',
39
+ freezeTableName: true
40
+ })
41
+ }
42
+
package/models/models.js CHANGED
@@ -1,3 +1,4 @@
1
+ const logger = require('../src/logger').child({ label: 'Models' });
1
2
  const fs = require('fs').promises;
2
3
  const path = require('path');
3
4
  const { Sequelize, DataTypes } = require("sequelize");
@@ -27,11 +28,11 @@ var self = module.exports = {
27
28
  sequelize
28
29
  .authenticate()
29
30
  .then(() => {
30
- console.log('Connection has been established successfully.');
31
+ logger.info('Connection has been established successfully.');
31
32
  return resolve();
32
33
  })
33
34
  .catch((error) => {
34
- console.error('Unable to connect to the database: ', error);
35
+ logger.error('Unable to connect to the database: ', error);
35
36
  return reject();
36
37
  });
37
38
  });
@@ -52,7 +53,7 @@ var self = module.exports = {
52
53
 
53
54
  // Use a for...of loop to load models sequentially
54
55
  for (const file of files) {
55
- console.log(`Sync file ${file}`);
56
+ logger.info(`Sync file ${file}`);
56
57
  const model = require(path.join(modelsPath, file));
57
58
  await model(sequelize, DataTypes); // Ensure each model is loaded before moving to the next
58
59
  }
@@ -70,11 +71,11 @@ var self = module.exports = {
70
71
  sequelize
71
72
  .sync({ alter: true })
72
73
  .then(async () => {
73
- console.log('All tables were synced!');
74
+ logger.info('All tables were synced!');
74
75
  return resolve();
75
76
  })
76
77
  .catch((error) => {
77
- console.error('Unable to create table : ', error);
78
+ logger.error('Unable to create table : ', error);
78
79
  return reject();
79
80
  });
80
81
  });
@@ -84,7 +85,7 @@ var self = module.exports = {
84
85
  return new Promise((resolve, reject) => {
85
86
  let tables = Object.keys(sequelize.models);
86
87
 
87
- console.log(tables);
88
+ logger.info(tables);
88
89
  if (!tables?.length) return resolve();
89
90
 
90
91
  tables.forEach(async (tableName, counter) => {
@@ -126,7 +127,7 @@ var self = module.exports = {
126
127
  sequelize
127
128
  .query(query)
128
129
  .then((res) => {
129
- console.log(`Dropped index ${index.Key_name}`);
130
+ logger.info(`Dropped index ${index.Key_name}`);
130
131
  if (counter === filteredIndexes.length - 1) return resolve();
131
132
  })
132
133
  .catch((error) => {
@@ -187,14 +188,14 @@ var self = module.exports = {
187
188
  })
188
189
  .then(([user, created]) => {
189
190
  if (created) {
190
- console.log('New user created:', type);
191
+ logger.info('New user created:', type);
191
192
  } else {
192
- console.log('User already exists:', type);
193
+ logger.info('User already exists:', type);
193
194
  }
194
195
  return resolve(user);
195
196
  })
196
197
  .catch((error) => {
197
- console.error('Error:', error);
198
+ logger.error('Error:', error);
198
199
  return reject(error);
199
200
  });
200
201
  });
@@ -212,14 +213,14 @@ var self = module.exports = {
212
213
  })
213
214
  .then(([client, created]) => {
214
215
  if (created) {
215
- console.log('New client created:', nick);
216
+ logger.info('New client created:', nick);
216
217
  } else {
217
- console.log('Client already exists:', nick);
218
+ logger.info('Client already exists:', nick);
218
219
  }
219
220
  return resolve(client);
220
221
  })
221
222
  .catch((error) => {
222
- console.error('Error:', error);
223
+ logger.error('Error:', error);
223
224
  return reject(error);
224
225
  });
225
226
  });
@@ -240,14 +241,14 @@ var self = module.exports = {
240
241
  })
241
242
  .then(([client, created]) => {
242
243
  if (created) {
243
- console.log('New project created:', project?.name);
244
+ logger.info('New project created:', project?.name);
244
245
  } else {
245
- console.log('Project already exists:', project?.name);
246
+ logger.info('Project already exists:', project?.name);
246
247
  }
247
248
  return resolve(client);
248
249
  })
249
250
  .catch((error) => {
250
- console.error('Error:', error);
251
+ logger.error('Error:', error);
251
252
  return reject(error);
252
253
  });
253
254
  });
@@ -270,10 +271,10 @@ var self = module.exports = {
270
271
  return { record, created };
271
272
  })
272
273
  );
273
- console.log("Insert/Update completed for LwM2M Objects.");
274
+ logger.info("Insert/Update completed for LwM2M Objects.");
274
275
  return results;
275
276
  } catch (error) {
276
- console.error("Error inserting/updating LwM2M Objects:", error.message);
277
+ logger.error("Error inserting/updating LwM2M Objects:", error.message);
277
278
  throw error;
278
279
  }
279
280
  },
@@ -296,10 +297,10 @@ var self = module.exports = {
296
297
  return { record, created };
297
298
  })
298
299
  );
299
- console.log("Insert/Update completed for LwM2M Resources.");
300
+ logger.info("Insert/Update completed for LwM2M Resources.");
300
301
  return results;
301
302
  } catch (error) {
302
- console.error("Error inserting/updating LwM2M Resources:", error.message);
303
+ logger.error("Error inserting/updating LwM2M Resources:", error.message);
303
304
  throw error;
304
305
  }
305
306
  },
@@ -353,7 +354,7 @@ var self = module.exports = {
353
354
  } else {
354
355
  // Skip invalid entries but warn
355
356
  // eslint-disable-next-line no-console
356
- console.warn('Skipping invalid resource entry:', entry);
357
+ logger.warn('Skipping invalid resource entry:', entry);
357
358
  }
358
359
  }
359
360
 
@@ -393,11 +394,11 @@ var self = module.exports = {
393
394
  });
394
395
 
395
396
  // eslint-disable-next-line no-console
396
- console.log('Insert/Update completed for LwM2M Resources.');
397
+ logger.info('Insert/Update completed for LwM2M Resources.');
397
398
  return results;
398
399
  } catch (error) {
399
400
  // eslint-disable-next-line no-console
400
- console.error('Error inserting/updating LwM2M Resources:', error.message);
401
+ logger.error('Error inserting/updating LwM2M Resources:', error.message);
401
402
  throw error;
402
403
  }
403
404
  }
@@ -22,6 +22,11 @@ module.exports = (sequelize,DataTypes)=>{
22
22
  allowNull: false,
23
23
  defaultValue: true
24
24
  },
25
+ readable: {
26
+ type: DataTypes.BOOLEAN,
27
+ allowNull: true,
28
+ default: true
29
+ },
25
30
  ref: {
26
31
  type: DataTypes.STRING,
27
32
  allowNull: false,
@@ -14,6 +14,11 @@ module.exports = (sequelize,DataTypes)=>{
14
14
  allowNull: false,
15
15
  defaultValue: true
16
16
  },
17
+ readable: {
18
+ type: DataTypes.BOOLEAN,
19
+ allowNull: true,
20
+ default: true
21
+ },
17
22
  ref: {
18
23
  type: DataTypes.STRING,
19
24
  allowNull: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mqtt-devices-parser",
3
- "version": "1.0.32",
3
+ "version": "1.0.33",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -20,6 +20,7 @@
20
20
  "mysql2": "^3.2.0",
21
21
  "net": "^1.0.2",
22
22
  "path": "^0.12.7",
23
+ "pino": "^9.14.0",
23
24
  "semver": "^7.3.8",
24
25
  "sequelize": "^6.32.1",
25
26
  "websocket-stream": "^5.4.0"
@@ -0,0 +1,172 @@
1
+ const moment = require('moment');
2
+ var mysql = require('mysql2')
3
+ const table = "actuators"
4
+
5
+ var self = module.exports = {
6
+
7
+ getById : async (id)=>{
8
+
9
+ return new Promise((resolve,reject) => {
10
+
11
+ let query = "SELECT * FROM ?? where id = ?";
12
+ let args = [table,id];
13
+ query = mysql.format(query,args);
14
+
15
+ $.db.queryRow(query)
16
+ .then( rows => {
17
+ if(rows.length > 0)
18
+ return resolve(rows[0]);
19
+ else
20
+ return resolve(null);
21
+ })
22
+ .catch( err => {
23
+ console.log(err);
24
+ return resolve(null);
25
+ });
26
+ });
27
+ },
28
+
29
+ // not used !!
30
+ getByRef : async (ref)=>{
31
+
32
+ return new Promise((resolve,reject) => {
33
+
34
+ let query = "SELECT * FROM ?? where ref = ?";
35
+ let args = [table,ref];
36
+ query = mysql.format(query,args);
37
+
38
+ $.db.queryRow(query)
39
+ .then( rows => {
40
+ if(rows.length > 0)
41
+ return resolve(rows[0]);
42
+ else
43
+ return resolve(null);
44
+ })
45
+ .catch( err => {
46
+ console.log(err);
47
+ return resolve(null);
48
+ });
49
+ });
50
+ },
51
+
52
+ getByName : async (name)=>{
53
+
54
+ return new Promise((resolve,reject) => {
55
+
56
+ let query = "SELECT * FROM ?? where name = ?";
57
+ let args = [table,name];
58
+ query = mysql.format(query,args);
59
+
60
+ $.db.queryRow(query)
61
+ .then( rows => {
62
+ if(rows.length > 0)
63
+ return resolve(rows[0]);
64
+ else
65
+ return resolve(null);
66
+ })
67
+ .catch( err => {
68
+ console.log(err);
69
+ return resolve(null);
70
+ });
71
+ });
72
+ },
73
+
74
+ getAll : async ()=>{
75
+
76
+ return new Promise((resolve,reject) => {
77
+
78
+ let query = "SELECT id,name FROM ??";
79
+ let args = [table];
80
+ query = mysql.format(query,args);
81
+
82
+ $.db.queryRow(query)
83
+ .then( rows => {
84
+ return resolve(rows);
85
+ })
86
+ .catch( err => {
87
+ console.log(err);
88
+ return resolve(null);
89
+ });
90
+ });
91
+ },
92
+
93
+ insert : async(table,deviceId,actuatorId,payload)=>{
94
+
95
+ return new Promise((resolve,reject) => {
96
+ let obj = {
97
+ device_id : deviceId,
98
+ actuator_id : actuatorId,
99
+ value : payload?.value,
100
+ error : payload?.error,
101
+ remoteUnixTs : payload?.timestamp, // local timestamp
102
+ createdAt : moment().utc().format('YYYY-MM-DD HH:mm:ss'),
103
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
104
+ }
105
+
106
+ $.db.insert(table,obj)
107
+ .then (rows => {
108
+ return resolve(rows[0]);
109
+ })
110
+ .catch(error => {
111
+ return reject(error);
112
+ });
113
+ });
114
+ },
115
+
116
+ update : async(table,obj,filter)=>{
117
+
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
+ },
129
+
130
+ getLastLogId : async(table,actuatorId)=>{
131
+
132
+ return new Promise((resolve,reject) => {
133
+
134
+ let query = "SELECT id FROM ?? WHERE actuator_id = ? AND confirmed = 0 ORDER BY id DESC LIMIT 1";
135
+ let args = [table,actuatorId];
136
+ query = mysql.format(query,args);
137
+
138
+ $.db.queryRow(query)
139
+ .then( rows => {
140
+ if(rows?.length > 0)
141
+ return resolve(rows[0].id);
142
+ else
143
+ return resolve(null);
144
+ })
145
+ .catch( err => {
146
+ console.log(err);
147
+ return resolve(null);
148
+ });
149
+ });
150
+ },
151
+
152
+ confirmMessage: async(table,lastLogId)=>{
153
+
154
+ let obj = {
155
+ confirmed : true
156
+ }
157
+ let filter = {
158
+ id : lastLogId
159
+ }
160
+
161
+ return new Promise((resolve,reject) => {
162
+
163
+ $.db.update(table,obj,filter)
164
+ .then (rows => {
165
+ return resolve(rows);
166
+ })
167
+ .catch(error => {
168
+ return reject(error);
169
+ });
170
+ });
171
+ },
172
+ }
package/src/db/db.js CHANGED
@@ -1,3 +1,4 @@
1
+ const logger = require('../logger').child({ label: 'Database' });
1
2
  var mysql = require('mysql2');
2
3
 
3
4
  var pool;
@@ -15,12 +16,12 @@ var self = module.exports = {
15
16
  });
16
17
  pool.getConnection(function(err,connection){
17
18
  if(err) {
18
- console.log("ISSUE WITH MYSQL \n" + err);
19
+ logger.info("ISSUE WITH MYSQL \n" + err);
19
20
  process.exit(1);
20
21
  } else {
21
22
  setInterval(function(){self.pingMySQL(connection);}, 3600000); // 1 hour
22
23
  connection.on('error', function(err) {
23
- console.log("Mysql error: "+err.code); // 'ER_BAD_DB_ERROR'
24
+ logger.info("Mysql error: "+err.code); // 'ER_BAD_DB_ERROR'
24
25
  process.exit(1);
25
26
  });
26
27
  cb();
@@ -37,7 +38,7 @@ var self = module.exports = {
37
38
  pingMySQL : (connection)=>{
38
39
  connection.ping(function (err) {
39
40
  if (err) throw err;
40
- //console.log(String(Date.now())+'Server responded to ping');
41
+ //logger.info(String(Date.now())+'Server responded to ping');
41
42
  });
42
43
  },
43
44