iotagent-node-lib 4.5.0 → 4.7.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.
Files changed (124) hide show
  1. package/.github/workflows/ci.yml +0 -1
  2. package/Changelog +12 -0
  3. package/README.md +67 -272
  4. package/config.js +3 -1
  5. package/doc/README.md +1 -1
  6. package/doc/admin.md +40 -18
  7. package/doc/api.md +532 -136
  8. package/doc/deprecated.md +4 -0
  9. package/doc/devel/architecture.md +5 -135
  10. package/doc/devel/development.md +224 -12
  11. package/doc/getting-started.md +114 -53
  12. package/doc/requirements.txt +1 -1
  13. package/doc/roadmap.md +5 -5
  14. package/docker/Mosquitto/Dockerfile +2 -2
  15. package/docker/Mosquitto/README.md +14 -11
  16. package/lib/commonConfig.js +21 -2
  17. package/lib/constants.js +3 -0
  18. package/lib/fiware-iotagent-lib.js +12 -15
  19. package/lib/jexlTranformsMap.js +3 -1
  20. package/lib/model/Command.js +2 -2
  21. package/lib/model/Device.js +7 -3
  22. package/lib/model/Group.js +5 -3
  23. package/lib/model/dbConn.js +53 -115
  24. package/lib/services/commands/commandRegistryMongoDB.js +115 -75
  25. package/lib/services/common/alarmManagement.js +3 -0
  26. package/lib/services/common/iotManagerService.js +3 -1
  27. package/lib/services/devices/deviceRegistryMemory.js +36 -0
  28. package/lib/services/devices/deviceRegistryMongoDB.js +160 -87
  29. package/lib/services/devices/deviceService.js +33 -3
  30. package/lib/services/devices/devices-NGSI-v2.js +6 -1
  31. package/lib/services/groups/groupRegistryMongoDB.js +120 -83
  32. package/lib/services/groups/groupService.js +1 -1
  33. package/lib/services/ngsi/entities-NGSI-LD.js +320 -570
  34. package/lib/services/ngsi/entities-NGSI-v2.js +51 -3
  35. package/lib/services/ngsi/ngsiService.js +34 -1
  36. package/lib/services/northBound/deviceGroupAdministrationServer.js +42 -6
  37. package/lib/services/northBound/deviceProvisioningServer.js +12 -4
  38. package/lib/services/northBound/northboundServer.js +2 -0
  39. package/lib/services/stats/statsRegistry.js +128 -101
  40. package/lib/templates/createDevice.json +0 -24
  41. package/lib/templates/createDeviceLax.json +0 -23
  42. package/lib/templates/deviceGroup.json +1 -25
  43. package/lib/templates/updateDevice.json +12 -24
  44. package/lib/templates/updateDeviceLax.json +12 -23
  45. package/package.json +5 -5
  46. package/scripts/legacy_expression_tool/README.md +0 -1
  47. package/test/functional/README.md +22 -17
  48. package/test/functional/config-test.js +3 -2
  49. package/test/functional/functional-tests-runner.js +9 -4
  50. package/test/functional/functional-tests.js +4 -4
  51. package/test/functional/testCases.js +245 -4
  52. package/test/functional/testUtils.js +2 -2
  53. package/test/unit/examples/deviceProvisioningRequests/provisionFullDevice.json +1 -13
  54. package/test/unit/examples/groupProvisioningRequests/multipleConfigGroupsCreation.json +44 -0
  55. package/test/unit/examples/groupProvisioningRequests/provisionDuplicateConfigGroup.json +35 -0
  56. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroup.json +36 -0
  57. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroupAlternate.json +36 -0
  58. package/test/unit/examples/groupProvisioningRequests/provisionFullGroup.json +1 -0
  59. package/test/unit/general/config-multi-core-test.js +1 -2
  60. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +5 -4
  61. package/test/unit/general/deviceService-test.js +106 -3
  62. package/test/unit/general/statistics-service_test.js +1 -74
  63. package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +6 -5
  64. package/test/unit/mongodb/mongodb-configGroup-registry-test.js +452 -0
  65. package/test/unit/mongodb/mongodb-connectionoptions-test.js +9 -42
  66. package/test/unit/mongodb/mongodb-group-registry-test.js +34 -33
  67. package/test/unit/mongodb/mongodb-service-registry-test.js +477 -0
  68. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +4 -4
  69. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json +22 -22
  70. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +4 -4
  71. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json +14 -15
  72. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin1.json +23 -23
  73. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin15.json +0 -5
  74. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin4.json +11 -16
  75. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin5.json +23 -28
  76. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin6.json +8 -13
  77. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin7.json +0 -5
  78. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin8.json +24 -29
  79. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +12 -17
  80. package/test/unit/ngsi-ld/examples/contextRequests/updateContextStaticLinkedAttributes.json +12 -10
  81. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +1 -104
  82. package/test/unit/ngsi-ld/general/config-jsonld-contexts-test.js +1 -2
  83. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +4 -5
  84. package/test/unit/ngsi-ld/provisioning/listProvisionedDevices-test.js +0 -4
  85. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +8 -5
  86. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +42 -41
  87. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +11 -10
  88. package/test/unit/ngsiv2/general/deviceService-test.js +98 -4
  89. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  90. package/test/unit/ngsiv2/general/iotam-autoregistration-test.js +195 -0
  91. package/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +4 -3
  92. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +6 -5
  93. package/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +17 -16
  94. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +10 -18
  95. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +21 -20
  96. package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +8 -7
  97. package/test/unit/ngsiv2/plugins/alias-plugin_test.js +12 -11
  98. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +3 -2
  99. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +28 -27
  100. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +265 -4
  101. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +12 -11
  102. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +1190 -0
  103. package/test/unit/ngsiv2/provisioning/device-registration_test.js +5 -4
  104. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +6 -9
  105. package/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +1 -1
  106. package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +5 -4
  107. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +8 -7
  108. package/test/unit/statsRegistry/openmetrics-test.js +167 -0
  109. package/lib/templates/queryContext.json +0 -25
  110. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +0 -35
  111. package/test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json +0 -17
  112. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +0 -31
  113. package/test/unit/general/statistics-persistence_test.js +0 -121
  114. package/test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json +0 -17
  115. package/test/unit/ngsi-ld/examples/contextRequests/updateContextProcessTimestamp.json +0 -12
  116. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  117. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json +0 -21
  118. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -17
  119. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -23
  120. package/test/unit/ngsi-ld/plugins/timestamp-processing-plugin_test.js +0 -132
  121. package/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +0 -8
  122. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  123. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -19
  124. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -24
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  const logger = require('logops');
27
- const dbService = require('../../model/dbConn');
27
+ const mongoose = require('mongoose');
28
28
  const intoTrans = require('../common/domain').intoTrans;
29
29
  const fillService = require('./../common/domain').fillService;
30
30
  const alarmsInt = require('../common/alarmManagement').intercept;
@@ -61,28 +61,11 @@ const attributeList = [
61
61
  'defaultEntityNameConjunction',
62
62
  'ngsiVersion',
63
63
  'entityNameExp',
64
- 'payloadType'
64
+ 'payloadType',
65
+ 'useCBflowControl',
66
+ 'storeLastMeasure'
65
67
  ];
66
68
 
67
- /**
68
- * Generates a handler for the save device group operations. The handler will take the customary error and the saved
69
- * device group as the parameters (and pass the serialized DAO as the callback value).
70
- *
71
- * @return {Function} The generated handler.
72
- */
73
- function saveGroupHandler(groupDAO, callback) {
74
- /* eslint-disable-next-line no-unused-vars */
75
- return function saveHandler(error, result) {
76
- if (error) {
77
- logger.debug(fillService(context, groupDAO), 'Error storing device group information: %s', error);
78
-
79
- callback(new errors.InternalDbError(error));
80
- } else {
81
- callback(null, groupDAO.toObject());
82
- }
83
- };
84
- }
85
-
86
69
  function createGroup(group, callback) {
87
70
  /* eslint-disable-next-line new-cap */
88
71
  const groupObj = new Group.model();
@@ -99,9 +82,12 @@ function createGroup(group, callback) {
99
82
  groupObj.apikey,
100
83
  groupObj.resource
101
84
  );
102
-
103
- groupObj.save(function saveHandler(error, groupDAO) {
104
- if (error) {
85
+ groupObj
86
+ .save({})
87
+ .then((groupDAO) => {
88
+ callback(null, groupDAO.toObject());
89
+ })
90
+ .catch((error) => {
105
91
  if (error.code === 11000) {
106
92
  logger.debug(
107
93
  context,
@@ -109,17 +95,12 @@ function createGroup(group, callback) {
109
95
  group.resource,
110
96
  group.apikey
111
97
  );
112
-
113
98
  callback(new errors.DuplicateGroup(group));
114
99
  } else {
115
100
  logger.debug(context, 'Error storing device group information: %s', error);
116
-
117
101
  callback(new errors.InternalDbError(error));
118
102
  }
119
- } else {
120
- callback(null, groupDAO.toObject());
121
- }
122
- });
103
+ });
123
104
  }
124
105
 
125
106
  /**
@@ -141,7 +122,7 @@ function listGroups(service, limit, offset, callback) {
141
122
  }
142
123
 
143
124
  const query = Group.model.find(condition).sort();
144
-
125
+ const queryCount = Group.model.countDocuments(condition);
145
126
  if (limit) {
146
127
  query.limit(parseInt(limit, 10));
147
128
  }
@@ -149,16 +130,32 @@ function listGroups(service, limit, offset, callback) {
149
130
  if (offset) {
150
131
  query.skip(parseInt(offset, 10));
151
132
  }
152
-
153
- async.series(
154
- [query.exec.bind(query), Group.model.countDocuments.bind(Group.model, condition)],
155
- function (error, results) {
156
- callback(error, {
157
- count: results[1],
158
- services: results[0].map(toObjectFn)
133
+ function funcQuery(cb) {
134
+ query
135
+ .exec({})
136
+ .then((res) => {
137
+ cb(null, res);
138
+ })
139
+ .catch((error) => {
140
+ cb(error);
159
141
  });
160
- }
161
- );
142
+ }
143
+ function funcQueryCount(cb) {
144
+ queryCount
145
+ .exec({})
146
+ .then((res) => {
147
+ cb(null, res);
148
+ })
149
+ .catch((error) => {
150
+ cb(error);
151
+ });
152
+ }
153
+ async.series([funcQuery, funcQueryCount], function (error, results) {
154
+ callback(error, {
155
+ count: results[1],
156
+ services: results[0].map(toObjectFn)
157
+ });
158
+ });
162
159
  }
163
160
 
164
161
  function getById(id, callback) {
@@ -168,21 +165,22 @@ function getById(id, callback) {
168
165
  const query = Group.model.findOne({ _id: id });
169
166
  query.select({ __v: 0 });
170
167
 
171
- query.lean().exec(function handleGet(error, data) {
172
- if (error) {
168
+ query
169
+ .exec({})
170
+ .then((data) => {
171
+ if (data) {
172
+ context = fillService(context, data);
173
+ logger.debug(context, 'Device group data found: %j', data);
174
+ callback(null, data);
175
+ } else {
176
+ logger.debug(context, 'Device group [%s] not found.', id);
177
+ callback(new errors.DeviceGroupNotFound(id));
178
+ }
179
+ })
180
+ .catch((error) => {
173
181
  logger.debug(context, 'Internal MongoDB Error getting group: %s', error);
174
-
175
182
  callback(new errors.InternalDbError(error));
176
- } else if (data) {
177
- context = fillService(context, data);
178
- logger.debug(context, 'Device group data found: %j', data);
179
- callback(null, data);
180
- } else {
181
- logger.debug(context, 'Device group [%s] not found.', id);
182
-
183
- callback(new errors.DeviceGroupNotFound(id));
184
- }
185
- });
183
+ });
186
184
  }
187
185
 
188
186
  /**
@@ -203,34 +201,56 @@ function find(service, subservice, callback) {
203
201
  condition.subservice = subservice;
204
202
 
205
203
  const query = Group.model.find(condition).sort();
206
-
207
- async.series(
208
- [query.exec.bind(query), Group.model.countDocuments.bind(Group.model, condition)],
209
- function (error, results) {
210
- callback(error, {
211
- count: results[1],
212
- services: results[0].map(toObjectFn)
204
+ const queryCount = Group.model.countDocuments(condition);
205
+ function funcQuery(cb) {
206
+ query
207
+ .exec({})
208
+ .then((res) => {
209
+ cb(null, res);
210
+ })
211
+ .catch((error) => {
212
+ cb(error);
213
213
  });
214
- }
215
- );
214
+ }
215
+ function funcQueryCount(cb) {
216
+ queryCount
217
+ .exec({})
218
+ .then((res) => {
219
+ cb(null, res);
220
+ })
221
+ .catch((error) => {
222
+ cb(error);
223
+ });
224
+ }
225
+ async.series([funcQuery, funcQueryCount], function (error, results) {
226
+ callback(error, {
227
+ count: results[1],
228
+ services: results[0].map(toObjectFn)
229
+ });
230
+ });
216
231
  }
217
232
 
218
233
  function findOneInMongoDB(queryObj, fields, callback) {
219
234
  const query = Group.model.findOne(queryObj);
220
235
  query.select({ __v: 0 });
221
- query.lean().exec(function handleGet(error, data) {
222
- if (error) {
236
+ query.lean();
237
+
238
+ query
239
+ .exec({})
240
+ .then((data) => {
241
+ if (data) {
242
+ context = fillService(context, data);
243
+ logger.debug(context, 'Device group data found: %j', data);
244
+ callback(null, data);
245
+ } else {
246
+ logger.debug(context, 'Device group for fields [%j] not found: [%j]', fields, queryObj);
247
+ callback(new errors.DeviceGroupNotFound(fields, queryObj));
248
+ }
249
+ })
250
+ .catch((error) => {
223
251
  logger.debug(context, 'Internal MongoDB Error getting group: %s', error);
224
252
  callback(new errors.InternalDbError(error));
225
- } else if (data) {
226
- context = fillService(context, data);
227
- logger.debug(context, 'Device group data found: %j', data);
228
- callback(null, data);
229
- } else {
230
- logger.debug(context, 'Device group for fields [%j] not found: [%j]', fields, queryObj);
231
- callback(new errors.DeviceGroupNotFound(fields, queryObj));
232
- }
233
- });
253
+ });
234
254
  }
235
255
 
236
256
  function findBy(fields) {
@@ -269,7 +289,15 @@ function update(id, body, callback) {
269
289
  /* eslint-disable-next-line new-cap */
270
290
  const groupObj = new Group.model(group);
271
291
  groupObj.isNew = false;
272
- groupObj.save(saveGroupHandler(groupObj, callback));
292
+ groupObj
293
+ .save({})
294
+ .then((groupDAO) => {
295
+ callback(null, groupDAO.toObject());
296
+ })
297
+ .catch((error) => {
298
+ logger.debug(fillService(context, group), 'Error storing device group information: %s', error);
299
+ callback(new errors.InternalDbError(error));
300
+ });
273
301
  }
274
302
  });
275
303
  }
@@ -281,16 +309,18 @@ function remove(id, callback) {
281
309
  if (error) {
282
310
  callback(error);
283
311
  } else {
284
- Group.model.deleteOne({ _id: id }, function (error) {
285
- if (error) {
286
- logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
312
+ const query = Group.model.deleteOne({ _id: id });
313
+ query
314
+ .exec({})
315
+ .then(() => {
316
+ logger.debug(context, 'Device group [%s] successfully removed.', id);
317
+ callback(null, deviceGroup);
318
+ })
319
+ .catch((error) => {
320
+ logger.debug(context, 'Internal MongoDB Error getting device group: %s', error);
287
321
 
288
322
  callback(new errors.InternalDbError(error));
289
- } else {
290
- logger.debug(context, 'Device [%s] successfully removed.', id);
291
- callback(null, deviceGroup);
292
- }
293
- });
323
+ });
294
324
  }
295
325
  });
296
326
  }
@@ -300,7 +330,14 @@ function init(newConfig, callback) {
300
330
  }
301
331
 
302
332
  function clear(callback) {
303
- dbService.db.db.dropDatabase(callback);
333
+ mongoose.connection
334
+ .dropDatabase()
335
+ .then(() => {
336
+ callback(null);
337
+ })
338
+ .catch((error) => {
339
+ callback(error);
340
+ });
304
341
  }
305
342
 
306
343
  exports.create = alarmsInt(constants.MONGO_ALARM + '_01', intoTrans(context, createGroup));
@@ -123,7 +123,7 @@ function listGroups(service, limit, offset, callback) {
123
123
  }
124
124
 
125
125
  function checkServiceIdentity(service, subservice, deviceGroup, callback) {
126
- if (deviceGroup.service === service && deviceGroup.subservice === subservice) {
126
+ if (deviceGroup.service === service.toLowerCase() && deviceGroup.subservice === subservice) {
127
127
  callback(null, deviceGroup);
128
128
  } else {
129
129
  callback(new errors.MismatchedService(service, subservice));