mqtt-devices-parser 1.0.0

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.
@@ -0,0 +1,26 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("permissions", {
4
+ client_id: {
5
+ type: DataTypes.INTEGER,
6
+ references: {
7
+ model: 'clients',
8
+ key: 'id'
9
+ }
10
+ },
11
+ device_id: {
12
+ type: DataTypes.INTEGER,
13
+ references: {
14
+ model: 'devices',
15
+ key: 'id'
16
+ }
17
+ },
18
+ level: {
19
+ type: DataTypes.INTEGER,
20
+ }
21
+ },
22
+ {
23
+ tableName: 'permissions',
24
+ freezeTableName: true
25
+ })
26
+ }
@@ -0,0 +1,24 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("projects", {
4
+ name: {
5
+ type: DataTypes.STRING,
6
+ unique: true
7
+ },
8
+ description: {
9
+ type: DataTypes.STRING
10
+ },
11
+ project_table: {
12
+ type: DataTypes.STRING,
13
+ allowNull: true
14
+ },
15
+ logs_table: {
16
+ type: DataTypes.STRING,
17
+ allowNull: true
18
+ },
19
+ },
20
+ {
21
+ tableName: 'projects',
22
+ freezeTableName: true
23
+ })
24
+ }
@@ -0,0 +1,41 @@
1
+ module.exports = (sequelize,DataTypes)=>{
2
+ return sequelize.define("sensor_logs", {
3
+ device_id: {
4
+ type: DataTypes.INTEGER,
5
+ unique: false,
6
+ allowNull: false,
7
+ references: {
8
+ model: 'devices',
9
+ key: 'id'
10
+ }
11
+ },
12
+ sensor_id: {
13
+ type: DataTypes.INTEGER,
14
+ unique: false,
15
+ allowNull: false,
16
+ references: {
17
+ model: 'sensors',
18
+ key: 'id'
19
+ }
20
+ },
21
+ value: {
22
+ type: DataTypes.STRING,
23
+ allowNull: true,
24
+ },
25
+ cliend_id: {
26
+ type: DataTypes.INTEGER,
27
+ unique: false,
28
+ allowNull: true,
29
+ references: {
30
+ model: 'clients',
31
+ key: 'id'
32
+ }
33
+ },
34
+
35
+ },
36
+ {
37
+ tableName: 'sensor_logs',
38
+ freezeTableName: true
39
+ })
40
+ }
41
+
@@ -0,0 +1,40 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("sensors", {
4
+ model_id: {
5
+ type: DataTypes.INTEGER,
6
+ unique: false,
7
+ allowNull: false,
8
+ references: {
9
+ model: 'models',
10
+ key: 'id'
11
+ }
12
+ },
13
+ active: {
14
+ type: DataTypes.BOOLEAN,
15
+ allowNull: false,
16
+ defaultValue: true
17
+ },
18
+ ref: {
19
+ type: DataTypes.STRING,
20
+ allowNull: false,
21
+ },
22
+ name: {
23
+ type: DataTypes.STRING,
24
+ allowNull: false,
25
+ },
26
+ type: {
27
+ type: DataTypes.STRING,
28
+ allowNull: false,
29
+ },
30
+ graph: {
31
+ type: DataTypes.JSON,
32
+ allowNull: true,
33
+ }
34
+ },
35
+ {
36
+ tableName: 'sensors',
37
+ freezeTableName: true
38
+ })
39
+ }
40
+
@@ -0,0 +1,19 @@
1
+
2
+ module.exports = (sequelize,DataTypes)=>{
3
+ return sequelize.define("users", {
4
+ type: {
5
+ type: DataTypes.STRING(32),
6
+ unique: true
7
+ },
8
+ password: {
9
+ type: DataTypes.STRING
10
+ },
11
+ level: {
12
+ type: DataTypes.INTEGER
13
+ }
14
+ },
15
+ {
16
+ tableName: 'users',
17
+ freezeTableName: true
18
+ })
19
+ }
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "mqtt-devices-parser",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "async": "^3.2.4",
14
+ "lodash": "^4.17.21",
15
+ "md5": "^2.3.0",
16
+ "moment": "^2.29.4",
17
+ "mqtt": "^5.0.3",
18
+ "mysql2": "^3.2.0",
19
+ "net": "^1.0.2",
20
+ "path": "^0.12.7",
21
+ "semver": "^7.3.8",
22
+ "sequelize": "^6.32.1",
23
+ "websocket-stream": "^5.5.2"
24
+ }
25
+ }
@@ -0,0 +1,20 @@
1
+
2
+ module.exports = {
3
+
4
+ pathIntoObject : (path,data)=>{
5
+ const segments = path.split("/").filter(segment => segment !== "");
6
+
7
+ let obj = {};
8
+ let currentObj = obj;
9
+
10
+ segments.forEach((segment, index) => {
11
+ if (index === segments.length - 1) {
12
+ currentObj[segment] = data;
13
+ } else {
14
+ currentObj[segment] = {};
15
+ currentObj = currentObj[segment];
16
+ }
17
+ });
18
+ return obj;
19
+ }
20
+ }
package/src/db/data.js ADDED
@@ -0,0 +1,197 @@
1
+ const moment = require('moment');
2
+ var mysql = require('mysql2')
3
+
4
+ var self = module.exports = {
5
+
6
+ checkEntry : async (table,deviceId)=>{
7
+
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
+ },
27
+
28
+ update : async (table, deviceId, topic, payload)=>{
29
+
30
+ return new Promise( async (resolve,reject) => {
31
+
32
+ if(!payload) return resolve();
33
+
34
+ let data = null;
35
+ // check if data is in JSON format
36
+ try{
37
+ data = JSON.parse(payload);
38
+ }catch(e){
39
+ data = payload;
40
+ }
41
+
42
+ let obj = {
43
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
44
+ }
45
+
46
+ let db_columns = $.models.get(table);
47
+
48
+ if(db_columns == null) return resolve();
49
+
50
+ let index = topic.indexOf("/");
51
+
52
+ if(index > -1){ // check if topic has subtopics
53
+ let key = topic.substring(0,index);
54
+ topic = topic.substring(index+1);
55
+
56
+ if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
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
+
93
+ }else return resolve();
94
+ }else{
95
+
96
+ let key = topic;
97
+ if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
98
+ // build object with respective data
99
+ if(typeof data === "object")
100
+ obj[key] = JSON.stringify(data);
101
+ else
102
+ obj[key] = data;
103
+
104
+ let exists = await self.checkEntry(table,deviceId);
105
+ if(!exists){
106
+ obj['device_id'] = deviceId;
107
+ obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
108
+ $.db.insert(table,obj)
109
+ .then((rows)=>{
110
+ return resolve(rows);
111
+ })
112
+ .catch((err)=>{
113
+ console.log(err);
114
+ return resolve(null);
115
+ })
116
+ }else{
117
+ let filter = {
118
+ device_id : deviceId
119
+ }
120
+
121
+ $.db.update(table,obj,filter)
122
+ .then((rows)=>{
123
+ return resolve(rows);
124
+ })
125
+ .catch((err)=>{
126
+ console.log(err);
127
+ return resolve(null);
128
+ })
129
+ }
130
+ }else return resolve();
131
+ }
132
+ })
133
+ },
134
+
135
+ addLog : async (table, deviceId, topic, payload)=>{
136
+
137
+ return new Promise((resolve,reject) => {
138
+
139
+ if(!payload) return resolve();
140
+
141
+ let data = null;
142
+ // check if data is in JSON format
143
+ try{
144
+ data = JSON.parse(payload);
145
+ }catch(e){
146
+ data = payload;
147
+ }
148
+
149
+ let obj = {
150
+ updatedAt : moment().utc().format('YYYY-MM-DD HH:mm:ss')
151
+ }
152
+
153
+ let db_columns = $.models.get(table);
154
+ if(db_columns == null)
155
+ return resolve();
156
+
157
+ let index = topic.indexOf("/");
158
+
159
+ if(index > -1){ // check if topic has subtopics
160
+ let key = topic.substring(0,index);
161
+ topic = topic.substring(index+1);
162
+
163
+ if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
164
+ // create JSON struct with the remaining topic
165
+ // key is the column
166
+
167
+ // build object with the remaining topic and respective data
168
+ if(typeof data === "object")
169
+ obj[key] = JSON.stringify(parser.pathIntoObject(topic,JSON.stringify(data)))
170
+ else
171
+ obj[key] = JSON.stringify(parser.pathIntoObject(topic,data));
172
+
173
+ obj['device_id'] = deviceId;
174
+ obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
175
+ $.db.insert(table,obj)
176
+
177
+ }
178
+ }else{
179
+
180
+ let key = topic;
181
+ if(db_columns.hasOwnProperty(key)){ // check if db has a column for this key
182
+ // build object with respective data
183
+ if(typeof data === "object")
184
+ obj[key] = JSON.stringify(data);
185
+ else
186
+ obj[key] = data;
187
+
188
+ obj['device_id'] = deviceId;
189
+ obj['createdAt'] = moment().utc().format('YYYY-MM-DD HH:mm:ss');
190
+ $.db.insert(table,obj);
191
+ }
192
+ }
193
+
194
+ return resolve();
195
+ });
196
+ }
197
+ };
package/src/db/db.js ADDED
@@ -0,0 +1,315 @@
1
+ var config = require('../../config');
2
+ var mysql = require('mysql2');
3
+
4
+ var pool;
5
+
6
+ var self = module.exports = {
7
+ connect : (cb)=>{
8
+ pool = mysql.createPool({
9
+ connectionLimit : config.mysqldb.conn_limit,
10
+ host : config.mysqldb.host,
11
+ port : config.mysqldb.port,
12
+ user : config.mysqldb.user,
13
+ password : config.mysqldb.pwd,
14
+ database : config.mysqldb.name,
15
+ debug : false
16
+ });
17
+ pool.getConnection(function(err,connection){
18
+ if(err) {
19
+ console.log("ISSUE WITH MYSQL \n" + err);
20
+ process.exit(1);
21
+ } else {
22
+ setInterval(function(){self.pingMySQL(connection);}, 3600000); // 1 hour
23
+ connection.on('error', function(err) {
24
+ console.log("Mysql error: "+err.code); // 'ER_BAD_DB_ERROR'
25
+ process.exit(1);
26
+ });
27
+ cb();
28
+ }
29
+ });
30
+ },
31
+
32
+ getConnection : (cb)=>{
33
+ pool.getConnection(function(err, connection) {
34
+ cb(err,connection);
35
+ });
36
+ },
37
+
38
+ pingMySQL : (connection)=>{
39
+ connection.ping(function (err) {
40
+ if (err) throw err;
41
+ //console.log(String(Date.now())+'Server responded to ping');
42
+ });
43
+ },
44
+
45
+ get_non_persistent_db_connection : (db_name,cb)=>{
46
+ let pool2 = mysql.createPool({
47
+ connectionLimit : 100,
48
+ host : config.mysqldb.host,
49
+ user : config.mysqldb.user,
50
+ password : config.mysqldb.pwd,
51
+ database : db_name,
52
+ debug : false,
53
+ multipleStatements: true
54
+ });
55
+ pool2.getConnection(function(err,connection){
56
+ cb(err,connection);
57
+ });
58
+ },
59
+
60
+ close_db_connection : (connection)=>{
61
+ if(connection != null){
62
+ connection.release();
63
+ }
64
+ },
65
+
66
+ queryRow : async (query)=>{
67
+ return new Promise((resolve,reject) => {
68
+
69
+ self.getConnection((err,conn)=>{
70
+ if(err) return reject(err);
71
+
72
+ conn.query(query,function(err,rows){
73
+ self.close_db_connection(conn);
74
+ if(err) return reject(err)
75
+ else return resolve(rows);
76
+ });
77
+ });
78
+ });
79
+ },
80
+
81
+ insert : async(table,data)=>{
82
+
83
+ return new Promise((resolve,reject) => {
84
+ self.getConnection((err,conn)=>{
85
+ if(err) return reject(err);
86
+
87
+ let query = "";
88
+ let values = [];
89
+
90
+ if(typeof data === "object"){
91
+ const keys = Object.keys(data);
92
+ values = Object.values(data);
93
+ const placeholders = values.map(() => '?').join(', ');
94
+ query = `INSERT INTO ?? (${keys.join(', ')}) VALUES (${placeholders})`;
95
+ }else{
96
+ return reject("data passed is not an object");
97
+ }
98
+ values.unshift(table);
99
+ query = mysql.format(query,values);
100
+
101
+ conn.query(query,function(err,rows){
102
+ self.close_db_connection(conn);
103
+ if(err) return reject(err)
104
+ else return resolve(rows);
105
+ });
106
+ });
107
+ });
108
+ },
109
+
110
+ update : async (table, data, filter) => {
111
+
112
+ return new Promise((resolve, reject) => {
113
+ self.getConnection((err, conn) => {
114
+ if (err) return reject(err);
115
+
116
+ let query = "";
117
+ let values = [];
118
+
119
+ if (typeof data === "object") {
120
+ const keys = Object.keys(data);
121
+ values = Object.values(data);
122
+ query = `UPDATE ?? SET ${keys.map(key => `${key} = ?`).join(', ')}`;
123
+ } else {
124
+ return reject("data passed is not an object");
125
+ }
126
+
127
+ if (typeof filter === "object") {
128
+ const filterKeys = Object.keys(filter);
129
+ const filterValues = Object.values(filter);
130
+ query += ` WHERE ${filterKeys.map(key => `${key} = ?`).join(' AND ')}`;
131
+ values.push(...filterValues);
132
+ } else {
133
+ return reject("filter passed is not an object");
134
+ }
135
+
136
+ values.unshift(table);
137
+ query = mysql.format(query, values);
138
+
139
+ conn.query(query, function (err, rows) {
140
+ self.close_db_connection(conn);
141
+ if (err) return reject(err);
142
+ else return resolve(rows);
143
+ });
144
+ });
145
+ });
146
+ },
147
+
148
+ updateJSON : async (table, column, data, filter) => {
149
+
150
+ return new Promise((resolve, reject) => {
151
+ self.getConnection((err, conn) => {
152
+ if (err) return reject(err);
153
+
154
+ let query = "";
155
+ let values = [];
156
+
157
+ if (typeof data === "object") {
158
+ const keys = Object.keys(data);
159
+ query = `UPDATE ${table} SET ${column} = `;
160
+ keys.forEach((key, index) => {
161
+ query += `JSON_SET(${column}, '$.${key}', ?)`;
162
+ values.push(data[key]);
163
+ if (index !== keys.length - 1) {
164
+ query += ', ';
165
+ }
166
+ });
167
+ } else {
168
+ return reject("data passed is not an object");
169
+ }
170
+
171
+ if (typeof filter === "object") {
172
+ const filterKeys = Object.keys(filter);
173
+ const filterValues = Object.values(filter);
174
+ query += ` WHERE ${filterKeys.map(key => `${key} = ?`).join(' AND ')}`;
175
+ values.push(...filterValues);
176
+ } else {
177
+ return reject("filter passed is not an object");
178
+ }
179
+
180
+ query = mysql.format(query, values);
181
+ conn.query(query, function (err, rows) {
182
+ self.close_db_connection(conn);
183
+ if(rows.affectedRows && !rows.changedRows){
184
+ self.insertJSON(table,column,data,filter)
185
+ .then( rows => {
186
+ return resolve(rows);
187
+ })
188
+ .catch( err => {
189
+ return reject(err);
190
+ })
191
+ }else{
192
+ if (err) return reject(err);
193
+ else return resolve(rows);
194
+ }
195
+ });
196
+ });
197
+ });
198
+ },
199
+
200
+ insertJSON : async (table, column, data, filter) => {
201
+
202
+ return new Promise((resolve, reject) => {
203
+ self.getConnection((err, conn) => {
204
+ if (err) return reject(err);
205
+
206
+ let query = "";
207
+ let values = [];
208
+
209
+ if (typeof data === "object") {
210
+ const jsonString = JSON.stringify(data);
211
+ query = `UPDATE ?? SET ?? = ?`;
212
+ const inserts = [table, column, jsonString];
213
+ query = mysql.format(query, inserts);
214
+ } else {
215
+ return reject("data passed is not an object");
216
+ }
217
+
218
+ if (typeof filter === "object") {
219
+ const filterKeys = Object.keys(filter);
220
+ const filterValues = Object.values(filter);
221
+ query += ` WHERE ${filterKeys.map(key => `${key} = ?`).join(' AND ')}`;
222
+ values.push(...filterValues);
223
+ } else {
224
+ return reject("filter passed is not an object");
225
+ }
226
+
227
+ query = mysql.format(query, values);
228
+ conn.query(query, function (err, rows) {
229
+ self.close_db_connection(conn);
230
+ if (err) return reject(err);
231
+ else return resolve(rows);
232
+ });
233
+ });
234
+ });
235
+ },
236
+
237
+ delete : async(table,filter)=>{
238
+
239
+ return new Promise((resolve,reject) => {
240
+
241
+ self.getConnection((err,conn)=>{
242
+ if(err) return reject(err);
243
+
244
+ let query = "";
245
+ if(typeof filter === "object"){
246
+ let values = [];
247
+ query = `DELETE FROM ${table} WHERE `;
248
+ for (let key in filter){
249
+ if(values.length > 0)
250
+ query += " AND ";
251
+ query += key + " = ?"
252
+ values.push(filter[key]);
253
+ }
254
+ query = mysql.format(query,values);
255
+ }else{
256
+ return reject("filter passed is not an object");
257
+ }
258
+
259
+ conn.query(query,function(err,rows){
260
+ self.close_db_connection(conn);
261
+ if(err) return reject(err)
262
+ else return resolve(rows);
263
+ });
264
+ });
265
+ });
266
+ },
267
+
268
+ getFieldFromDeviceId : async (table,deviceId,field)=>{
269
+
270
+ return new Promise((resolve,reject) => {
271
+
272
+ self.getConnection((err,conn)=>{
273
+ if(err) return reject(err);
274
+
275
+ let query = "SELECT ?? FROM ?? where device_id = ?";
276
+ let args = [field,table,deviceId];
277
+ query = mysql.format(query,args);
278
+ conn.query(query,function(err,rows){
279
+ $.db.close_db_connection(conn);
280
+ if(err) return reject(err)
281
+ else{
282
+ if(rows.length == 1 ){
283
+ return resolve(rows[0][field]);
284
+ }else return resolve(null);
285
+ }
286
+ });
287
+ });
288
+ });
289
+ },
290
+
291
+ getPropertyFromDeviceId : async(table,deviceId,field,key)=>{
292
+
293
+ return new Promise((resolve,reject) => {
294
+
295
+ self.getConnection((err,conn)=>{
296
+ if(err) return reject(err);
297
+
298
+ let query = "SELECT ?? FROM ?? where device_id = ?";
299
+ let args = [field,table,deviceId];
300
+
301
+ query = mysql.format(query,args);
302
+ conn.query(query,function(err,rows){
303
+ $.db.close_db_connection(conn);
304
+ if(err) return reject(err)
305
+ else{
306
+ if(rows.length == 1 && rows[0]?.field && rows[0][field]?.key){
307
+ return resolve(rows[0][field][key]);
308
+ }else return resolve(null);
309
+ }
310
+ });
311
+ });
312
+ });
313
+ }
314
+ }
315
+