iotagent-node-lib 4.6.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 (56) hide show
  1. package/.github/workflows/ci.yml +0 -1
  2. package/Changelog +12 -0
  3. package/config.js +3 -1
  4. package/doc/admin.md +39 -5
  5. package/doc/api.md +67 -6
  6. package/doc/requirements.txt +1 -1
  7. package/lib/commonConfig.js +21 -2
  8. package/lib/model/Command.js +2 -2
  9. package/lib/model/Device.js +7 -3
  10. package/lib/model/Group.js +5 -3
  11. package/lib/model/dbConn.js +53 -112
  12. package/lib/services/commands/commandRegistryMongoDB.js +115 -75
  13. package/lib/services/common/iotManagerService.js +3 -1
  14. package/lib/services/devices/deviceRegistryMemory.js +36 -0
  15. package/lib/services/devices/deviceRegistryMongoDB.js +160 -87
  16. package/lib/services/devices/deviceService.js +33 -3
  17. package/lib/services/devices/devices-NGSI-v2.js +6 -1
  18. package/lib/services/groups/groupRegistryMongoDB.js +120 -83
  19. package/lib/services/ngsi/entities-NGSI-v2.js +14 -1
  20. package/lib/services/ngsi/ngsiService.js +32 -1
  21. package/lib/services/northBound/deviceProvisioningServer.js +12 -3
  22. package/lib/templates/updateDevice.json +12 -0
  23. package/lib/templates/updateDeviceLax.json +12 -0
  24. package/package.json +4 -4
  25. package/test/functional/config-test.js +3 -2
  26. package/test/functional/testUtils.js +2 -2
  27. package/test/unit/examples/groupProvisioningRequests/provisionFullGroup.json +1 -0
  28. package/test/unit/general/config-multi-core-test.js +1 -2
  29. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +5 -4
  30. package/test/unit/general/deviceService-test.js +6 -5
  31. package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +6 -5
  32. package/test/unit/mongodb/mongodb-connectionoptions-test.js +7 -39
  33. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +1 -2
  34. package/test/unit/ngsi-ld/general/config-jsonld-contexts-test.js +1 -2
  35. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +8 -5
  36. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +42 -41
  37. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +11 -10
  38. package/test/unit/ngsiv2/general/deviceService-test.js +6 -5
  39. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  40. package/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +4 -3
  41. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +6 -5
  42. package/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +17 -16
  43. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +10 -18
  44. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +21 -20
  45. package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +8 -7
  46. package/test/unit/ngsiv2/plugins/alias-plugin_test.js +12 -11
  47. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +3 -2
  48. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +28 -27
  49. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +6 -4
  50. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +12 -11
  51. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +11 -10
  52. package/test/unit/ngsiv2/provisioning/device-registration_test.js +5 -4
  53. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +6 -5
  54. package/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +1 -1
  55. package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +5 -4
  56. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +8 -7
@@ -179,6 +179,12 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio
179
179
  if (configuration && configuration.payloadType !== undefined && deviceData.payloadType === undefined) {
180
180
  deviceData.payloadType = configuration.payloadType;
181
181
  }
182
+ if (configuration && configuration.useCBflowControl !== undefined && deviceData.useCBflowControl === undefined) {
183
+ deviceData.useCBflowControl = configuration.useCBflowControl;
184
+ }
185
+ if (configuration && configuration.storeLastMeasure !== undefined && deviceData.storeLastMeasure === undefined) {
186
+ deviceData.storeLastMeasure = configuration.storeLastMeasure;
187
+ }
182
188
  logger.debug(context, 'deviceData after merge with conf: %j', deviceData);
183
189
  callback(null, deviceData);
184
190
  }
@@ -277,7 +283,20 @@ function registerDevice(deviceObj, callback) {
277
283
  deviceData.ngsiVersion = configuration.ngsiVersion;
278
284
  }
279
285
  }
280
-
286
+ // Set polling and transport for autoprovisioned devices
287
+ if (!deviceData.transport && config.getConfig().defaultTransport) {
288
+ deviceData.transport =
289
+ configuration && configuration.transport
290
+ ? configuration.transport
291
+ : config.getConfig().defaultTransport;
292
+ }
293
+ if (deviceData.transport === 'HTTP') {
294
+ if (deviceData.endpoint) {
295
+ deviceData.polling = false;
296
+ } else {
297
+ deviceData.polling = !(configuration && configuration.endpoint);
298
+ }
299
+ }
281
300
  if (!deviceData.name) {
282
301
  let entityName = null;
283
302
  if (configuration && configuration.entityNameExp !== undefined && configuration.entityNameExp !== '') {
@@ -285,7 +304,7 @@ function registerDevice(deviceObj, callback) {
285
304
  let attrList = pluginUtils.getIdTypeServSubServiceFromDevice(deviceData);
286
305
  attrList = deviceData.staticAttributes ? attrList.concat(deviceData.staticAttributes) : attrList;
287
306
  attrList = configuration.staticAttributes ? attrList.concat(configuration.staticAttributes) : attrList;
288
- let ctxt = expressionPlugin.extractContext(attrList);
307
+ const ctxt = expressionPlugin.extractContext(attrList);
289
308
  try {
290
309
  entityName = expressionPlugin.applyExpression(configuration.entityNameExp, ctxt, deviceData);
291
310
  } catch (e) {
@@ -357,6 +376,12 @@ function registerDevice(deviceObj, callback) {
357
376
  if ('apikey' in deviceData && deviceData.apikey !== undefined) {
358
377
  deviceObj.apikey = deviceData.apikey;
359
378
  }
379
+ if ('transport' in deviceData && deviceData.transport !== undefined) {
380
+ deviceObj.transport = deviceData.transport;
381
+ }
382
+ if ('polling' in deviceData && deviceData.polling !== undefined) {
383
+ deviceObj.polling = deviceData.polling;
384
+ }
360
385
  logger.debug(context, 'Storing device :\n%s', JSON.stringify(deviceObj, null, 4));
361
386
  config.getRegistry().store(deviceObj, callback);
362
387
  }
@@ -616,7 +641,7 @@ function findOrCreate(deviceId, apikey, group, callback) {
616
641
  } else if (error.name === 'DEVICE_NOT_FOUND') {
617
642
  const newDevice = {
618
643
  id: deviceId,
619
- apikey: apikey,
644
+ apikey,
620
645
  service: group.service,
621
646
  subservice: group.subservice,
622
647
  type: group.type
@@ -692,6 +717,10 @@ function retrieveDevice(deviceId, apiKey, callback) {
692
717
  }
693
718
  }
694
719
 
720
+ function storeDeviceField(fieldName, fieldValue, typeInformation, callback) {
721
+ config.getRegistry().storeDeviceField(fieldName, fieldValue, typeInformation, callback);
722
+ }
723
+
695
724
  exports.listDevices = intoTrans(context, checkRegistry)(listDevices);
696
725
  exports.listDevicesWithType = intoTrans(context, checkRegistry)(listDevicesWithType);
697
726
  exports.getDevice = intoTrans(context, checkRegistry)(getDevice);
@@ -708,4 +737,5 @@ exports.retrieveDevice = intoTrans(context, checkRegistry)(retrieveDevice);
708
737
  exports.mergeDeviceWithConfiguration = mergeDeviceWithConfiguration;
709
738
  exports.findOrCreate = findOrCreate;
710
739
  exports.findConfigurationGroup = findConfigurationGroup;
740
+ exports.storeDeviceField = storeDeviceField;
711
741
  exports.init = init;
@@ -285,7 +285,12 @@ function updateRegisterDeviceNgsi2(deviceObj, previousDevice, entityInfoUpdated,
285
285
  if ('transport' in newDevice && newDevice.transport !== undefined) {
286
286
  oldDevice.transport = newDevice.transport;
287
287
  }
288
-
288
+ if ('useCBflowControl' in newDevice && newDevice.useCBflowControl !== undefined) {
289
+ oldDevice.useCBflowControl = newDevice.useCBflowControl;
290
+ }
291
+ if ('storeLastMeasure' in newDevice && newDevice.storeLastMeasure !== undefined) {
292
+ oldDevice.storeLastMeasure = newDevice.storeLastMeasure;
293
+ }
289
294
  callback(null, oldDevice);
290
295
  } else {
291
296
  callback(new errors.DeviceNotFound(newDevice.id, newDevice));
@@ -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));
@@ -347,6 +347,10 @@ function sendUpdateValueNgsi2(entityName, originMeasures, originTypeInformation,
347
347
  //metadata static attributes
348
348
  jexlctxt = reduceMetadataAttrToPlainObject(typeInformation.staticAttributes, jexlctxt);
349
349
 
350
+ //recover oldctxt
351
+ if (typeInformation.oldCtxt) {
352
+ jexlctxt.oldCtxt = typeInformation.oldCtxt;
353
+ }
350
354
  logger.debug(
351
355
  context,
352
356
  'sendUpdateValueNgsi2 loop with: entityName=%s, measures=%j, typeInformation=%j, initial jexlContext=%j, timestamp=%j',
@@ -652,9 +656,15 @@ function sendUpdateValueNgsi2(entityName, originMeasures, originTypeInformation,
652
656
  }
653
657
  }
654
658
  }
659
+ //Add jexlctxt to typeInformation without oldCtxt
660
+ const oldCJexlctxt = { ...jexlctxt };
661
+ delete oldCJexlctxt.oldCtxt;
662
+ originTypeInformation['oldCtxt'] = oldCJexlctxt;
655
663
  } // end for (let measures of originMeasures)
656
-
657
664
  let url = '/v2/op/update';
665
+ if (originTypeInformation.useCBflowControl) {
666
+ url += '?options=flowControl';
667
+ }
658
668
  let options = NGSIUtils.createRequestObject(url, originTypeInformation, token);
659
669
  options.json = payload;
660
670
 
@@ -680,6 +690,9 @@ function sendUpdateValueNgsi2(entityName, originMeasures, originTypeInformation,
680
690
  if (!multi) {
681
691
  // recreate options object to use single entity update
682
692
  url = '/v2/entities?options=upsert';
693
+ if (originTypeInformation.useCBflowControl) {
694
+ url += ',flowControl';
695
+ }
683
696
  options = NGSIUtils.createRequestObject(url, originTypeInformation, token);
684
697
  delete payload.actionType;
685
698
 
@@ -27,6 +27,7 @@
27
27
  const async = require('async');
28
28
  const apply = async.apply;
29
29
  const statsRegistry = require('../stats/statsRegistry');
30
+ const deviceService = require('../devices/deviceService');
30
31
  const intoTrans = require('../common/domain').intoTrans;
31
32
  const fillService = require('./../common/domain').fillService;
32
33
  const errors = require('../../errors');
@@ -69,7 +70,37 @@ function init() {
69
70
  */
70
71
  function sendUpdateValue(entityName, attributes, typeInformation, token, callback) {
71
72
  const newCallback = statsRegistry.withStats('updateEntityRequestsOk', 'updateEntityRequestsError', callback);
72
- entityHandler.sendUpdateValue(entityName, attributes, typeInformation, token, newCallback);
73
+ const additionalCallback = (data, next) => {
74
+ if (typeInformation.oldCtxt) {
75
+ logger.debug(context, 'StoreOldCtxt %j', typeInformation.oldCtxt);
76
+ deviceService.storeDeviceField('oldCtxt', typeInformation.oldCtxt, typeInformation, function () {
77
+ next(null, data);
78
+ });
79
+ } else {
80
+ next(null, data);
81
+ }
82
+ };
83
+ const wrappedNewCallback = (err, result) => {
84
+ if (err) {
85
+ newCallback(err);
86
+ } else {
87
+ additionalCallback(result, (additionalErr, modifiedResult) => {
88
+ if (additionalErr) {
89
+ newCallback(additionalErr);
90
+ }
91
+ newCallback(null, modifiedResult || result);
92
+ });
93
+ }
94
+ };
95
+ // check config about store last measure
96
+ if (typeInformation.storeLastMeasure) {
97
+ logger.debug(context, 'StoreLastMeasure for %j', typeInformation);
98
+ deviceService.storeDeviceField('lastMeasure', attributes, typeInformation, function () {
99
+ return entityHandler.sendUpdateValue(entityName, attributes, typeInformation, token, wrappedNewCallback);
100
+ });
101
+ } else {
102
+ entityHandler.sendUpdateValue(entityName, attributes, typeInformation, token, wrappedNewCallback);
103
+ }
73
104
  }
74
105
 
75
106
  /**
@@ -64,7 +64,10 @@ const provisioningAPITranslation = {
64
64
  explicitAttrs: 'explicitAttrs',
65
65
  ngsiVersion: 'ngsiVersion',
66
66
  entityNameExp: 'entityNameExp',
67
- payloadType: 'payloadType'
67
+ payloadType: 'payloadType',
68
+ useCBflowControl: 'useCBflowControl',
69
+ storeLastMeasure: 'storeLastMeasure',
70
+ lastMeasure: 'lastMeasure'
68
71
  };
69
72
 
70
73
  /**
@@ -143,7 +146,10 @@ function handleProvision(req, res, next) {
143
146
  autoprovision: body.autoprovision,
144
147
  explicitAttrs: body.explicitAttrs,
145
148
  ngsiVersion: body.ngsiVersion,
146
- payloadType: body.payloadType
149
+ payloadType: body.payloadType,
150
+ useCBflowControl: body.useCBflowControl,
151
+ storeLastMeasure: body.storeLastMeasure,
152
+ lastMeasure: body.lastMeasure
147
153
  });
148
154
  }
149
155
 
@@ -220,7 +226,10 @@ function toProvisioningAPIFormat(device) {
220
226
  autoprovision: device.autoprovision,
221
227
  explicitAttrs: device.explicitAttrs,
222
228
  ngsiVersion: device.ngsiVersion,
223
- payloadType: device.payloadType
229
+ payloadType: device.payloadType,
230
+ useCBflowControl: device.useCBflowControl,
231
+ storeLastMeasure: device.storeLastMeasure,
232
+ lastMeasure: device.lastMeasure
224
233
  };
225
234
  }
226
235
 
@@ -149,6 +149,10 @@
149
149
  "description": "Payload type",
150
150
  "type": "string"
151
151
  },
152
+ "useCBflowControl": {
153
+ "description": "use CB flowControl option",
154
+ "type": "boolean"
155
+ },
152
156
  "contentType": {
153
157
  "description": "Content type",
154
158
  "type": "string"
@@ -194,6 +198,14 @@
194
198
  "payloadType": {
195
199
  "description": "Payload type allowed for measures for this device",
196
200
  "type": "string"
201
+ },
202
+ "storeLastMeasure": {
203
+ "description": "Store last measure",
204
+ "type": "boolean"
205
+ },
206
+ "lastMeasure": {
207
+ "description": "last measure",
208
+ "type": "object"
197
209
  }
198
210
  }
199
211
  }
@@ -146,6 +146,18 @@
146
146
  "payloadType": {
147
147
  "description": "Payload type allowed for measures for this device",
148
148
  "type": "string"
149
+ },
150
+ "useCBflowControl": {
151
+ "description": "use CB flowControl option",
152
+ "type": "boolean"
153
+ },
154
+ "storeLastMeasure": {
155
+ "description": "Store last measure",
156
+ "type": "boolean"
157
+ },
158
+ "lastMeasure": {
159
+ "description": "last measure",
160
+ "type": "object"
149
161
  }
150
162
  }
151
163
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "iotagent-node-lib",
3
3
  "license": "AGPL-3.0-only",
4
4
  "description": "IoT Agent library to interface with NGSI Context Broker",
5
- "version": "4.6.0",
5
+ "version": "4.7.0",
6
6
  "homepage": "https://github.com/telefonicaid/iotagent-node-lib",
7
7
  "keywords": [
8
8
  "fiware",
@@ -45,14 +45,14 @@
45
45
  "dependencies": {
46
46
  "async": "2.6.4",
47
47
  "body-parser": "~1.20.3",
48
- "express": "~4.19.2",
48
+ "express": "~4.21.2",
49
49
  "got": "~11.8.5",
50
50
  "jexl": "2.3.0",
51
51
  "jison": "0.4.18",
52
52
  "logops": "2.1.2",
53
53
  "moment": "~2.29.2",
54
54
  "moment-timezone": "~0.5.34",
55
- "mongoose": "5.13.20",
55
+ "mongoose": "8.9.5",
56
56
  "query-string": "7.1.1",
57
57
  "revalidator": "~0.3.1",
58
58
  "underscore": "~1.13.4",
@@ -69,7 +69,7 @@
69
69
  "husky": "~4.2.5",
70
70
  "lint-staged": "~12.3.8",
71
71
  "mocha": "10.0.0",
72
- "mongodb": "4.17.1",
72
+ "mongodb": "4.17.2",
73
73
  "nock": "13.2.7",
74
74
  "nyc": "~15.1.0",
75
75
  "prettier": "~2.7.1",
@@ -45,7 +45,7 @@ config.amqp = {
45
45
  };
46
46
 
47
47
  config.iota = {
48
- logLevel: 'FATAL',
48
+ logLevel: 'DEBUG',
49
49
  contextBroker: {
50
50
  host: '192.168.1.1',
51
51
  port: '1026',
@@ -61,7 +61,8 @@ config.iota = {
61
61
  service: 'smartgondor',
62
62
  subservice: '/gardens',
63
63
  providerUrl: 'http://localhost:4041',
64
- types: {}
64
+ types: {},
65
+ useCBflowControl: true
65
66
  };
66
67
 
67
68
  config.defaultKey = '1234';
@@ -204,9 +204,9 @@ async function testCase(measure, expectation, provision, env, config, type, tran
204
204
  let cbMockRoute = '';
205
205
  // Set the correct route depending if the test is multientity or not
206
206
  if (type === 'multientity' || type === 'multimeasure') {
207
- cbMockRoute = '/v2/op/update';
207
+ cbMockRoute = '/v2/op/update?options=flowControl';
208
208
  } else {
209
- cbMockRoute = '/v2/entities?options=upsert';
209
+ cbMockRoute = '/v2/entities?options=upsert,flowControl';
210
210
  }
211
211
 
212
212
  // Set the correct mock times depending if the test is multimeasure or not
@@ -6,6 +6,7 @@
6
6
  "entity_type": "SensorMachine",
7
7
  "trust": "8970A9078A803H3BL98PINEQRW8342HBAMS",
8
8
  "cbHost": "http://unexistentHost:1026",
9
+ "useCBflowControl": true,
9
10
  "commands": [
10
11
  {
11
12
  "name": "wheel1",
@@ -54,8 +54,7 @@ const iotAgentConfig = {
54
54
  }
55
55
  },
56
56
  providerUrl: 'http://smartgondor.com',
57
- deviceRegistrationDuration: 'P1M',
58
- throttling: 'PT5S'
57
+ deviceRegistrationDuration: 'P1M'
59
58
  };
60
59
 
61
60
  describe('Startup Multi-Core tests', function () {