iotagent-node-lib 4.6.0 → 4.8.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 (70) hide show
  1. package/.github/workflows/ci.yml +2 -3
  2. package/CHANGES_NEXT_RELEASE +1 -0
  3. package/Changelog +20 -0
  4. package/config.js +3 -1
  5. package/doc/README.md +1 -0
  6. package/doc/admin.md +39 -5
  7. package/doc/api.md +74 -9
  8. package/doc/devel/northboundinteractions.md +122 -15
  9. package/doc/models/models.md +260 -0
  10. package/doc/requirements.txt +1 -1
  11. package/docker/Mosquitto/Dockerfile +1 -1
  12. package/lib/commonConfig.js +21 -2
  13. package/lib/fiware-iotagent-lib.js +15 -11
  14. package/lib/jexlTranformsMap.js +182 -35
  15. package/lib/model/Command.js +11 -2
  16. package/lib/model/Device.js +8 -3
  17. package/lib/model/Group.js +5 -3
  18. package/lib/model/dbConn.js +53 -112
  19. package/lib/services/commands/commandRegistryMongoDB.js +130 -76
  20. package/lib/services/commands/commandService.js +3 -3
  21. package/lib/services/common/iotManagerService.js +3 -1
  22. package/lib/services/devices/deviceRegistryMemory.js +36 -0
  23. package/lib/services/devices/deviceRegistryMongoDB.js +161 -88
  24. package/lib/services/devices/deviceService.js +44 -5
  25. package/lib/services/devices/devices-NGSI-v2.js +6 -1
  26. package/lib/services/groups/groupRegistryMongoDB.js +120 -83
  27. package/lib/services/ngsi/entities-NGSI-v2.js +14 -1
  28. package/lib/services/ngsi/ngsiService.js +32 -1
  29. package/lib/services/northBound/contextServer-NGSI-v2.js +12 -3
  30. package/lib/services/northBound/contextServer.js +2 -1
  31. package/lib/services/northBound/deviceProvisioningServer.js +12 -3
  32. package/lib/services/northBound/northboundServer.js +1 -0
  33. package/lib/templates/createDevice.json +4 -0
  34. package/lib/templates/updateDevice.json +16 -0
  35. package/lib/templates/updateDeviceLax.json +12 -0
  36. package/package.json +4 -4
  37. package/test/functional/config-test.js +3 -2
  38. package/test/functional/testUtils.js +15 -4
  39. package/test/unit/examples/groupProvisioningRequests/provisionFullGroup.json +1 -0
  40. package/test/unit/expressions/jexlExpression-test.js +165 -1
  41. package/test/unit/general/config-multi-core-test.js +1 -2
  42. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +5 -4
  43. package/test/unit/general/deviceService-test.js +6 -5
  44. package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +6 -5
  45. package/test/unit/mongodb/mongodb-connectionoptions-test.js +7 -39
  46. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +1 -2
  47. package/test/unit/ngsi-ld/general/config-jsonld-contexts-test.js +1 -2
  48. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +8 -5
  49. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +42 -41
  50. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +11 -10
  51. package/test/unit/ngsiv2/general/deviceService-test.js +6 -5
  52. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  53. package/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +4 -3
  54. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +6 -5
  55. package/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +17 -16
  56. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +10 -18
  57. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +21 -20
  58. package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +8 -7
  59. package/test/unit/ngsiv2/plugins/alias-plugin_test.js +12 -11
  60. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +3 -2
  61. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +28 -27
  62. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +6 -4
  63. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +12 -11
  64. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +11 -10
  65. package/test/unit/ngsiv2/provisioning/device-registration_test.js +5 -4
  66. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +6 -5
  67. package/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +1 -1
  68. package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +5 -4
  69. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +8 -7
  70. package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +0 -326
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  const logger = require('logops');
25
- const dbService = require('../../model/dbConn');
25
+ const mongoose = require('mongoose');
26
26
  const config = require('../../commonConfig');
27
27
  const fillService = require('./../common/domain').fillService;
28
28
  const alarmsInt = require('../common/alarmManagement').intercept;
@@ -57,27 +57,11 @@ const attributeList = [
57
57
  'explicitAttrs',
58
58
  'ngsiVersion',
59
59
  'subscriptions',
60
- 'payloadType'
60
+ 'payloadType',
61
+ 'useCBflowControl',
62
+ 'storeLastMeasure'
61
63
  ];
62
64
 
63
- /**
64
- * Generates a handler for the save device operations. The handler will take the customary error and the saved device
65
- * as the parameters (and pass the serialized DAO as the callback value).
66
- *
67
- * @return {Function} The generated handler.
68
- */
69
- function saveDeviceHandler(callback) {
70
- return function saveHandler(error, deviceDAO) {
71
- if (error) {
72
- logger.debug(fillService(context, deviceDAO), 'Error storing device information: %s', error);
73
-
74
- callback(new errors.InternalDbError(error));
75
- } else {
76
- callback(null, deviceDAO.toObject());
77
- }
78
- };
79
- }
80
-
81
65
  /**
82
66
  * Create a new register for a device. The device object should contain the id, type and registrationId
83
67
  *
@@ -97,21 +81,22 @@ function storeDevice(newDevice, callback) {
97
81
 
98
82
  logger.debug(context, 'Storing device with id [%s] and type [%s]', newDevice.id, newDevice.type);
99
83
 
100
- deviceObj.save(function saveHandler(error, deviceDAO) {
101
- if (error) {
84
+ deviceObj
85
+ .save({})
86
+ .then((deviceDAO) => {
87
+ callback(null, deviceDAO.toObject());
88
+ })
89
+ .catch((error) => {
102
90
  if (error.code === 11000) {
103
91
  logger.debug(context, 'Tried to insert a device with duplicate ID in the database: %s', error);
104
92
 
105
- callback(new errors.DuplicateDeviceId(newDevice));
93
+ callback(new errors.DuplicateDeviceId(newDevice), newDevice);
106
94
  } else {
107
95
  logger.debug(context, 'Error storing device information: %s', error);
108
96
 
109
97
  callback(new errors.InternalDbError(error));
110
98
  }
111
- } else {
112
- callback(null, deviceDAO.toObject());
113
- }
114
- });
99
+ });
115
100
  }
116
101
 
117
102
  /**
@@ -132,17 +117,17 @@ function removeDevice(id, apikey, service, subservice, callback) {
132
117
  }
133
118
  logger.debug(context, 'Removing device with id [%s]', id);
134
119
 
135
- Device.model.deleteOne(condition, function (error) {
136
- if (error) {
137
- logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
138
-
139
- callback(new errors.InternalDbError(error));
140
- } else {
120
+ const query = Device.model.deleteOne(condition);
121
+ query
122
+ .exec({})
123
+ .then(() => {
141
124
  logger.debug(context, 'Device [%s] successfully removed.', id);
142
-
143
125
  callback(null);
144
- }
145
- });
126
+ })
127
+ .catch((error) => {
128
+ logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
129
+ callback(new errors.InternalDbError(error));
130
+ });
146
131
  }
147
132
 
148
133
  /**
@@ -170,7 +155,7 @@ function listDevices(type, service, subservice, limit, offset, callback) {
170
155
  }
171
156
 
172
157
  const query = Device.model.find(condition).sort();
173
-
158
+ const queryCount = Device.model.countDocuments(condition);
174
159
  if (limit) {
175
160
  query.limit(parseInt(limit, 10));
176
161
  }
@@ -179,36 +164,55 @@ function listDevices(type, service, subservice, limit, offset, callback) {
179
164
  query.skip(parseInt(offset, 10));
180
165
  }
181
166
 
182
- async.series(
183
- [query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)],
184
- function (error, results) {
185
- callback(error, {
186
- count: results[1],
187
- devices: results[0]
167
+ function funcQuery(cb) {
168
+ query
169
+ .exec({})
170
+ .then((res) => {
171
+ cb(null, res);
172
+ })
173
+ .catch((error) => {
174
+ cb(error);
188
175
  });
189
- }
190
- );
176
+ }
177
+ function funcQueryCount(cb) {
178
+ queryCount
179
+ .exec({})
180
+ .then((res) => {
181
+ cb(null, res);
182
+ })
183
+ .catch((error) => {
184
+ cb(error);
185
+ });
186
+ }
187
+ async.series([funcQuery, funcQueryCount], function (error, results) {
188
+ callback(error, {
189
+ count: results[1],
190
+ devices: results[0]
191
+ });
192
+ });
191
193
  }
192
194
 
193
195
  function findOneInMongoDB(queryParams, id, callback) {
194
196
  const query = Device.model.findOne(queryParams);
195
197
  query.select({ __v: 0 });
196
-
197
- query.lean().exec(function handleGet(error, data) {
198
- if (error) {
198
+ query.lean();
199
+
200
+ query
201
+ .exec({})
202
+ .then((data) => {
203
+ if (data) {
204
+ context = fillService(context, data);
205
+ logger.debug(context, 'Device data found: %j', data);
206
+ callback(null, data);
207
+ } else {
208
+ logger.debug(context, 'Device [%s] not found.', id);
209
+ callback(new errors.DeviceNotFound(id, queryParams));
210
+ }
211
+ })
212
+ .catch((error) => {
199
213
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
200
-
201
214
  callback(new errors.InternalDbError(error));
202
- } else if (data) {
203
- context = fillService(context, data);
204
- logger.debug(context, 'Device data found: %j', data);
205
- callback(null, data);
206
- } else {
207
- logger.debug(context, 'Device [%s] not found.', id);
208
-
209
- callback(new errors.DeviceNotFound(id, queryParams));
210
- }
211
- });
215
+ });
212
216
  }
213
217
 
214
218
  /**
@@ -220,7 +224,7 @@ function findOneInMongoDB(queryParams, id, callback) {
220
224
  * @param {String} subservice Division inside the service (optional).
221
225
  */
222
226
  function getDeviceById(id, apikey, service, subservice, callback) {
223
- let queryParams = {
227
+ const queryParams = {
224
228
  id,
225
229
  service,
226
230
  subservice
@@ -252,9 +256,9 @@ function getDevice(id, apikey, service, subservice, callback) {
252
256
 
253
257
  function getByNameAndType(name, type, service, servicepath, callback) {
254
258
  context = fillService(context, { service, subservice: servicepath });
255
- let optionsQuery = {
256
- name: name,
257
- service: service,
259
+ const optionsQuery = {
260
+ name,
261
+ service,
258
262
  subservice: servicepath
259
263
  };
260
264
  if (type) {
@@ -264,20 +268,23 @@ function getByNameAndType(name, type, service, servicepath, callback) {
264
268
  const query = Device.model.findOne(optionsQuery);
265
269
 
266
270
  query.select({ __v: 0 });
267
-
268
- query.lean().exec(function handleGet(error, data) {
269
- if (error) {
271
+ query.lean();
272
+ query
273
+ .exec({})
274
+ .then((data) => {
275
+ if (data) {
276
+ context = fillService(context, data);
277
+ logger.debug(context, 'Device data found: %j', data);
278
+ callback(null, data);
279
+ } else {
280
+ logger.debug(context, 'Device [%s] not found.', name);
281
+ callback(new errors.DeviceNotFound(name, optionsQuery));
282
+ }
283
+ })
284
+ .catch((error) => {
270
285
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
271
-
272
286
  callback(new errors.InternalDbError(error));
273
- } else if (data) {
274
- callback(null, data);
275
- } else {
276
- logger.debug(context, 'Device [%s] not found.', name);
277
-
278
- callback(new errors.DeviceNotFound(name, optionsQuery));
279
- }
280
- });
287
+ });
281
288
  }
282
289
 
283
290
  function getByName(name, service, servicepath, callback) {
@@ -314,11 +321,22 @@ function update(previousDevice, device, callback) {
314
321
  data.timestamp = device.timestamp;
315
322
  data.subscriptions = device.subscriptions;
316
323
  data.payloadType = device.payloadType;
324
+ data.useCBflowControl = device.useCBflowControl;
325
+ data.storeLastMeasure = device.storeLastMeasure;
326
+ data.lastMeasure = device.lastMeasure;
317
327
 
318
328
  /* eslint-disable-next-line new-cap */
319
329
  const deviceObj = new Device.model(data);
320
330
  deviceObj.isNew = false;
321
- deviceObj.save(saveDeviceHandler(callback));
331
+ deviceObj
332
+ .save({})
333
+ .then((deviceDAO) => {
334
+ callback(null, deviceDAO.toObject());
335
+ })
336
+ .catch((error) => {
337
+ logger.debug(fillService(context, device), 'Error storing device information: %s', error);
338
+ callback(new errors.InternalDbError(error));
339
+ });
322
340
  }
323
341
  });
324
342
  }
@@ -327,7 +345,14 @@ function update(previousDevice, device, callback) {
327
345
  * Cleans all the information in the database, leaving it in a clean state.
328
346
  */
329
347
  function clear(callback) {
330
- dbService.db.db.dropDatabase(callback);
348
+ mongoose.connection
349
+ .dropDatabase()
350
+ .then(() => {
351
+ callback(null);
352
+ })
353
+ .catch((error) => {
354
+ callback(error);
355
+ });
331
356
  }
332
357
 
333
358
  function itemToObject(i) {
@@ -355,24 +380,72 @@ function getDevicesByAttribute(name, value, service, subservice, callback) {
355
380
 
356
381
  const query = Device.model.find(filter);
357
382
  query.select({ __v: 0 });
358
-
359
- query.exec(function handleGet(error, devices) {
360
- if (error) {
383
+ query.lean();
384
+ query
385
+ .exec({})
386
+ .then((devices) => {
387
+ if (devices) {
388
+ callback(null, devices.map(itemToObject));
389
+ } else {
390
+ logger.debug(context, 'Device [%s] not found.', name);
391
+ callback(new errors.DeviceNotFound(name, filter));
392
+ }
393
+ })
394
+ .catch((error) => {
361
395
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
362
-
363
396
  callback(new errors.InternalDbError(error));
364
- } else if (devices) {
365
- callback(null, devices.map(itemToObject));
366
- } else {
367
- logger.debug(context, 'Device [%s] not found.', name);
397
+ });
398
+ }
368
399
 
369
- callback(new errors.DeviceNotFound(name, filter));
370
- }
371
- });
400
+ function storeDeviceField(fieldName, fieldValue, typeInformation, callback) {
401
+ if (
402
+ typeInformation &&
403
+ typeInformation.id &&
404
+ typeInformation.apikey &&
405
+ typeInformation.service &&
406
+ typeInformation.subservice
407
+ ) {
408
+ getDevice(
409
+ typeInformation.id,
410
+ typeInformation.apikey,
411
+ typeInformation.service,
412
+ typeInformation.subservice,
413
+ function (error, data) {
414
+ if (error) {
415
+ callback(error);
416
+ } else {
417
+ if (fieldName === 'lastMeasure') {
418
+ data.lastMeasure = { timestamp: new Date().toISOString(), measure: fieldValue };
419
+ } else {
420
+ data[fieldName] = fieldValue;
421
+ }
422
+ /* eslint-disable-next-line new-cap */
423
+ const deviceObj = new Device.model(data);
424
+ deviceObj.isNew = false;
425
+ deviceObj
426
+ .save({})
427
+ .then((deviceDao) => {
428
+ callback(null, deviceDao.toObject());
429
+ })
430
+ .catch((error) => {
431
+ logger.debug(
432
+ fillService(context, deviceObj),
433
+ 'Error storing device information: %s',
434
+ error
435
+ );
436
+ callback(new errors.InternalDbError(error));
437
+ });
438
+ }
439
+ }
440
+ );
441
+ } else {
442
+ callback(null, null);
443
+ }
372
444
  }
373
445
 
374
446
  exports.getDevicesByAttribute = alarmsInt(constants.MONGO_ALARM, getDevicesByAttribute);
375
447
  exports.store = alarmsInt(constants.MONGO_ALARM, storeDevice);
448
+ exports.storeDeviceField = alarmsInt(constants.MONGO_ALARM, storeDeviceField);
376
449
  exports.update = alarmsInt(constants.MONGO_ALARM, update);
377
450
  exports.remove = alarmsInt(constants.MONGO_ALARM, removeDevice);
378
451
  exports.list = alarmsInt(constants.MONGO_ALARM, listDevices);
@@ -40,6 +40,8 @@ const registrationUtils = require('./registrationUtils');
40
40
  const subscriptions = require('../ngsi/subscriptionService');
41
41
  const expressionPlugin = require('./../../plugins/expressionPlugin');
42
42
  const pluginUtils = require('./../../plugins/pluginUtils');
43
+ const alarms = require('../common/alarmManagement');
44
+ const constants = require('../../constants');
43
45
  const _ = require('underscore');
44
46
  const context = {
45
47
  op: 'IoTAgentNGSI.DeviceService'
@@ -179,6 +181,12 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio
179
181
  if (configuration && configuration.payloadType !== undefined && deviceData.payloadType === undefined) {
180
182
  deviceData.payloadType = configuration.payloadType;
181
183
  }
184
+ if (configuration && configuration.useCBflowControl !== undefined && deviceData.useCBflowControl === undefined) {
185
+ deviceData.useCBflowControl = configuration.useCBflowControl;
186
+ }
187
+ if (configuration && configuration.storeLastMeasure !== undefined && deviceData.storeLastMeasure === undefined) {
188
+ deviceData.storeLastMeasure = configuration.storeLastMeasure;
189
+ }
182
190
  logger.debug(context, 'deviceData after merge with conf: %j', deviceData);
183
191
  callback(null, deviceData);
184
192
  }
@@ -244,7 +252,7 @@ function registerDevice(deviceObj, callback) {
244
252
  /* eslint-disable-next-line no-unused-vars */
245
253
  function (error, device) {
246
254
  if (!error) {
247
- innerCb(new errors.DuplicateDeviceId(deviceObj));
255
+ innerCb(new errors.DuplicateDeviceId(deviceObj), device);
248
256
  } else {
249
257
  innerCb();
250
258
  }
@@ -277,7 +285,20 @@ function registerDevice(deviceObj, callback) {
277
285
  deviceData.ngsiVersion = configuration.ngsiVersion;
278
286
  }
279
287
  }
280
-
288
+ // Set polling and transport for autoprovisioned devices
289
+ if (!deviceData.transport && config.getConfig().defaultTransport) {
290
+ deviceData.transport =
291
+ configuration && configuration.transport
292
+ ? configuration.transport
293
+ : config.getConfig().defaultTransport;
294
+ }
295
+ if (deviceData.transport === 'HTTP') {
296
+ if (deviceData.endpoint) {
297
+ deviceData.polling = false;
298
+ } else {
299
+ deviceData.polling = !(configuration && configuration.endpoint);
300
+ }
301
+ }
281
302
  if (!deviceData.name) {
282
303
  let entityName = null;
283
304
  if (configuration && configuration.entityNameExp !== undefined && configuration.entityNameExp !== '') {
@@ -285,7 +306,7 @@ function registerDevice(deviceObj, callback) {
285
306
  let attrList = pluginUtils.getIdTypeServSubServiceFromDevice(deviceData);
286
307
  attrList = deviceData.staticAttributes ? attrList.concat(deviceData.staticAttributes) : attrList;
287
308
  attrList = configuration.staticAttributes ? attrList.concat(configuration.staticAttributes) : attrList;
288
- let ctxt = expressionPlugin.extractContext(attrList);
309
+ const ctxt = expressionPlugin.extractContext(attrList);
289
310
  try {
290
311
  entityName = expressionPlugin.applyExpression(configuration.entityNameExp, ctxt, deviceData);
291
312
  } catch (e) {
@@ -357,6 +378,12 @@ function registerDevice(deviceObj, callback) {
357
378
  if ('apikey' in deviceData && deviceData.apikey !== undefined) {
358
379
  deviceObj.apikey = deviceData.apikey;
359
380
  }
381
+ if ('transport' in deviceData && deviceData.transport !== undefined) {
382
+ deviceObj.transport = deviceData.transport;
383
+ }
384
+ if ('polling' in deviceData && deviceData.polling !== undefined) {
385
+ deviceObj.polling = deviceData.polling;
386
+ }
360
387
  logger.debug(context, 'Storing device :\n%s', JSON.stringify(deviceObj, null, 4));
361
388
  config.getRegistry().store(deviceObj, callback);
362
389
  }
@@ -616,7 +643,7 @@ function findOrCreate(deviceId, apikey, group, callback) {
616
643
  } else if (error.name === 'DEVICE_NOT_FOUND') {
617
644
  const newDevice = {
618
645
  id: deviceId,
619
- apikey: apikey,
646
+ apikey,
620
647
  service: group.service,
621
648
  subservice: group.subservice,
622
649
  type: group.type
@@ -639,7 +666,14 @@ function findOrCreate(deviceId, apikey, group, callback) {
639
666
  if (group.autoprovision === undefined || group.autoprovision === true) {
640
667
  logger.debug(context, 'Registering autoprovision of Device %j for its conf %j', newDevice, group);
641
668
  registerDevice(newDevice, function (error, device) {
642
- callback(error, device, group);
669
+ if (error && error.name === 'DUPLICATE_DEVICE_ID') {
670
+ alarms.release(constants.MONGO_ALARM, error);
671
+ logger.warn(context, 'Error %j already registered autoprovisioned device: %j ', error, device);
672
+ callback(null, device, group);
673
+ } else {
674
+ logger.debug(context, 'registered autoprovisioned device: %j ', device);
675
+ callback(error, device, group);
676
+ }
643
677
  });
644
678
  } else {
645
679
  logger.info(
@@ -692,6 +726,10 @@ function retrieveDevice(deviceId, apiKey, callback) {
692
726
  }
693
727
  }
694
728
 
729
+ function storeDeviceField(fieldName, fieldValue, typeInformation, callback) {
730
+ config.getRegistry().storeDeviceField(fieldName, fieldValue, typeInformation, callback);
731
+ }
732
+
695
733
  exports.listDevices = intoTrans(context, checkRegistry)(listDevices);
696
734
  exports.listDevicesWithType = intoTrans(context, checkRegistry)(listDevicesWithType);
697
735
  exports.getDevice = intoTrans(context, checkRegistry)(getDevice);
@@ -708,4 +746,5 @@ exports.retrieveDevice = intoTrans(context, checkRegistry)(retrieveDevice);
708
746
  exports.mergeDeviceWithConfiguration = mergeDeviceWithConfiguration;
709
747
  exports.findOrCreate = findOrCreate;
710
748
  exports.findConfigurationGroup = findConfigurationGroup;
749
+ exports.storeDeviceField = storeDeviceField;
711
750
  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));