iotagent-node-lib 3.3.0 → 3.4.1

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 (80) hide show
  1. package/CHANGES_NEXT_RELEASE +1 -0
  2. package/README.md +10 -11
  3. package/doc/README.md +16 -0
  4. package/doc/admin.md +565 -0
  5. package/doc/api.md +9 -5
  6. package/doc/deprecated.md +16 -14
  7. package/doc/{architecture.md → devel/architecture.md} +3 -3
  8. package/doc/{Contribution.md → devel/contribution-guidelines.md} +43 -35
  9. package/doc/devel/development.md +1879 -0
  10. package/doc/{northboundinteractions.md → devel/northboundinteractions.md} +18 -33
  11. package/doc/index.md +3 -5
  12. package/docker/Mosquitto/README.md +1 -0
  13. package/lib/commonConfig.js +0 -5
  14. package/lib/fiware-iotagent-lib.js +1 -1
  15. package/lib/jexlTranformsMap.js +2 -1
  16. package/lib/request-shim.js +2 -2
  17. package/lib/services/commands/commandService.js +1 -1
  18. package/lib/services/common/genericMiddleware.js +1 -1
  19. package/lib/services/devices/deviceRegistryMemory.js +2 -2
  20. package/lib/services/devices/deviceRegistryMongoDB.js +22 -9
  21. package/lib/services/devices/deviceService.js +36 -30
  22. package/lib/services/devices/devices-NGSI-LD.js +14 -2
  23. package/lib/services/devices/devices-NGSI-mixed.js +0 -2
  24. package/lib/services/devices/devices-NGSI-v2.js +22 -100
  25. package/lib/services/groups/groupService.js +1 -1
  26. package/lib/services/ngsi/entities-NGSI-v2.js +14 -27
  27. package/lib/services/northBound/deviceProvisioningServer.js +14 -5
  28. package/mkdocs.yml +6 -11
  29. package/package.json +3 -3
  30. package/scripts/legacy_expression_tool/README.md +56 -38
  31. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +2 -2
  32. package/test/unit/mongodb/mongodb-registry-test.js +1 -1
  33. package/test/unit/ngsi-ld/general/contextBrokerOAuthSecurityAccess-test.js +66 -65
  34. package/test/unit/ngsi-ld/general/https-support-test.js +1 -1
  35. package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +8 -7
  36. package/test/unit/ngsi-ld/lazyAndCommands/polling-commands-test.js +12 -11
  37. package/test/unit/ngsi-ld/ngsiService/subscriptions-test.js +41 -39
  38. package/test/unit/ngsi-ld/provisioning/device-provisioning-api_test.js +122 -122
  39. package/test/unit/ngsi-ld/provisioning/device-registration_test.js +28 -28
  40. package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +18 -17
  41. package/test/unit/ngsi-ld/provisioning/singleConfigurationMode-test.js +7 -7
  42. package/test/unit/ngsi-ld/provisioning/updateProvisionedDevices-test.js +8 -7
  43. package/test/unit/ngsiv2/examples/contextRequests/updateContext6.json +2 -0
  44. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json +0 -12
  45. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json +0 -4
  46. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json +1 -5
  47. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json +0 -12
  48. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin29.json +0 -12
  49. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json +0 -4
  50. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +0 -10
  51. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json +0 -4
  52. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json +0 -4
  53. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json +0 -4
  54. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json +0 -12
  55. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json +0 -4
  56. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +1 -5
  57. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +13 -12
  58. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +2 -2
  59. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  60. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +3 -8
  61. package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +10 -10
  62. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +8 -103
  63. package/test/unit/ngsiv2/provisioning/device-registration_test.js +8 -6
  64. package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +2 -1
  65. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +0 -1
  66. package/.nyc_output/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
  67. package/.nyc_output/processinfo/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
  68. package/.nyc_output/processinfo/index.json +0 -1
  69. package/doc/config-basic-example.js +0 -20
  70. package/doc/development.md +0 -285
  71. package/doc/howto.md +0 -641
  72. package/doc/installationguide.md +0 -365
  73. package/doc/operations.md +0 -127
  74. package/doc/usermanual.md +0 -900
  75. package/lib/plugins/bidirectionalData.js +0 -356
  76. package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +0 -697
  77. package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +0 -536
  78. /package/doc/{NorthboundInteractions.postman_collection → devel/NorthboundInteractions.postman_collection} +0 -0
  79. /package/doc/{echo.js → devel/echo.js} +0 -0
  80. /package/doc/{finalResult.js → devel/finalResult.js} +0 -0
@@ -61,46 +61,6 @@ function jsonConcat(json1, json2) {
61
61
  }
62
62
  }
63
63
 
64
- /**
65
- * Creates the response handler for the initial entity creation request using NGSIv2.
66
- * This handler basically deals with the errors that could have been rised during
67
- * the communication with the Context Broker.
68
- *
69
- * @param {Object} deviceData Object containing all the deviceData needed to send the registration.
70
- * @param {Object} newDevice Device object that will be stored in the database.
71
- * @return {function} Handler to pass to the request() function.
72
- */
73
- function createInitialEntityHandlerNgsi2(deviceData, newDevice, callback) {
74
- return function handleInitialEntityResponse(error, response, body) {
75
- if (error) {
76
- logger.error(
77
- context,
78
- 'ORION-001: Connection error creating inital entity in the Context Broker: %s',
79
- error
80
- );
81
-
82
- alarms.raise(constants.ORION_ALARM, error);
83
-
84
- callback(error);
85
- } else if (response && response.statusCode === 204) {
86
- alarms.release(constants.ORION_ALARM);
87
- logger.debug(context, 'Initial entity created successfully.');
88
- callback(null, newDevice);
89
- } else {
90
- logger.error(
91
- context,
92
- 'Protocol error connecting to the Context Broker [%d]: %s',
93
- response.statusCode,
94
- body
95
- );
96
-
97
- const errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body, response.statusCode);
98
-
99
- callback(errorObj);
100
- }
101
- };
102
- }
103
-
104
64
  /**
105
65
  * Creates the response handler for the update entity request using NGSIv2. This handler basically deals with the errors
106
66
  * that could have been rised during the communication with the Context Broker.
@@ -199,62 +159,12 @@ function formatCommandsNgsi2(originalVector) {
199
159
  return attributeList;
200
160
  }
201
161
 
202
- /**
203
- * Creates the initial entity representing the device in the Context Broker using NGSIv2.
204
- * This is important mainly to allow the rest of the updateContext operations to be performed.
205
- *
206
- * @param {Object} deviceData Object containing all the deviceData needed to send the registration.
207
- * @param {Object} newDevice Device object that will be stored in the database.
162
+ /*
163
+ * This methods makes a bypass in updateRegisterDeviceNgsi2 to allow not change
164
+ * extractDeviceDifference and combineWithNewDevice methods
208
165
  */
209
- function createInitialEntityNgsi2(deviceData, newDevice, callback) {
210
- const options = {
211
- url: config.getConfig().contextBroker.url + '/v2/entities?options=upsert',
212
- method: 'POST',
213
- json: {
214
- id: String(deviceData.name),
215
- type: deviceData.type
216
- },
217
- headers: {
218
- 'fiware-service': deviceData.service,
219
- 'fiware-servicepath': deviceData.subservice,
220
- 'fiware-correlator': (domain.active && domain.active.corr) || uuid.v4()
221
- }
222
- };
223
-
224
- if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) {
225
- options.url = deviceData.cbHost + '/v2/entities?options=upsert';
226
- } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) {
227
- options.url = 'http://' + deviceData.cbHost + '/v2/entities?options=upsert';
228
- }
229
-
230
- jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false));
231
- jsonConcat(options.json, formatAttributesNgsi2(deviceData.staticAttributes, true));
232
- jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands));
233
-
234
- for (const att in options.json) {
235
- try {
236
- // Format any GeoJSON attrs properly
237
- options.json[att] = NGSIv2.formatGeoAttrs(options.json[att]);
238
- } catch (error) {
239
- return callback(new errors.BadGeocoordinates(JSON.stringify(options.json)));
240
- }
241
- }
242
-
243
- logger.debug(context, 'Creating initial entity with deviceData: %j', deviceData);
244
- if (
245
- ('timestamp' in deviceData && deviceData.timestamp !== undefined
246
- ? deviceData.timestamp
247
- : config.getConfig().timestamp) &&
248
- !utils.isTimestampedNgsi2(options.json)
249
- ) {
250
- logger.debug(context, 'config.timestamp %s %s', deviceData.timestamp, config.getConfig().timestamp);
251
- options.json[constants.TIMESTAMP_ATTRIBUTE] = {
252
- type: constants.TIMESTAMP_TYPE_NGSI2,
253
- value: moment()
254
- };
255
- }
256
- logger.debug(context, 'Creating initial entity in the Context Broker:\n %s', JSON.stringify(options, null, 4));
257
- utils.executeWithSecurity(options, newDevice, createInitialEntityHandlerNgsi2(deviceData, newDevice, callback));
166
+ function createInitialEntityNgsi2Fake(deviceData, newDevice, callback) {
167
+ callback(null, newDevice);
258
168
  }
259
169
 
260
170
  /**
@@ -337,9 +247,10 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
337
247
  return;
338
248
  }
339
249
 
340
- logger.debug(context, 'Update provisioned v2 device in Device Service');
250
+ logger.debug(context, 'Update provisioned v2 device in Device Service %j %j', deviceObj, entityInfoUpdated);
341
251
 
342
252
  function combineWithNewDevice(newDevice, oldDevice, callback) {
253
+ logger.debug(context, 'combineWithNewDevice %j %j', newDevice, oldDevice);
343
254
  if (oldDevice) {
344
255
  oldDevice.internalId = newDevice.internalId;
345
256
  oldDevice.lazy = newDevice.lazy;
@@ -424,9 +335,15 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
424
335
  if (entityInfoUpdated) {
425
336
  async.waterfall(
426
337
  [
427
- apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice),
338
+ apply(
339
+ config.getRegistry().get,
340
+ deviceObj.id,
341
+ deviceObj.apikey,
342
+ deviceObj.service,
343
+ deviceObj.subservice
344
+ ),
428
345
  apply(extractDeviceDifference, deviceObj),
429
- createInitialEntityNgsi2,
346
+ createInitialEntityNgsi2Fake,
430
347
  apply(combineWithNewDevice, deviceObj),
431
348
  apply(registrationUtils.sendRegistrations, false),
432
349
  apply(registrationUtils.processContextRegistration, deviceObj),
@@ -437,7 +354,13 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
437
354
  } else {
438
355
  async.waterfall(
439
356
  [
440
- apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice),
357
+ apply(
358
+ config.getRegistry().get,
359
+ deviceObj.id,
360
+ deviceObj.apikey,
361
+ deviceObj.service,
362
+ deviceObj.subservice
363
+ ),
441
364
  apply(extractDeviceDifference, deviceObj),
442
365
  updateEntityNgsi2,
443
366
  apply(combineWithNewDevice, deviceObj),
@@ -450,7 +373,6 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
450
373
  }
451
374
  }
452
375
 
453
- exports.createInitialEntity = createInitialEntityNgsi2;
454
376
  exports.updateRegisterDevice = updateRegisterDeviceNgsi2;
455
377
  exports.formatCommands = formatCommandsNgsi2;
456
378
  exports.formatAttributes = formatAttributesNgsi2;
@@ -172,7 +172,7 @@ function remove(service, subservice, resource, apikey, device, callback) {
172
172
  }
173
173
 
174
174
  function unregisterDevice(device, cb) {
175
- deviceService.unregister(device.id, service, subservice, function (error) {
175
+ deviceService.unregister(device.id, device.apikey, service, subservice, function (error) {
176
176
  if (error) {
177
177
  cb(error);
178
178
  }
@@ -354,11 +354,7 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
354
354
  payload.entities[0].type = typeInformation.type;
355
355
  }
356
356
 
357
- if (config.getConfig().appendMode === false) {
358
- payload.actionType = 'update';
359
- } else {
360
- payload.actionType = 'append';
361
- }
357
+ payload.actionType = 'append';
362
358
 
363
359
  let options = NGSIUtils.createRequestObject(url, typeInformation, token);
364
360
 
@@ -680,8 +676,9 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
680
676
  try {
681
677
  logger.debug(context, 'sendUpdateValueNgsi2 entityNameExp %j ', typeInformation.entityNameExp);
682
678
  entityName = expressionPlugin.applyExpression(typeInformation.entityNameExp, ctxt, typeInformation);
683
- payload.entities[0].id = entityName;
684
- ctxt['entity_name'] = entityName;
679
+ // CB entity id should be always a String
680
+ payload.entities[0].id = String(entityName);
681
+ ctxt['entity_name'] = String(entityName);
685
682
  } catch (e) {
686
683
  logger.debug(
687
684
  context,
@@ -762,9 +759,14 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
762
759
  if (expressionPlugin.contextAvailable(attr.expression, ctxt, typeInformation)) {
763
760
  res = expressionPlugin.applyExpression(attr.expression, ctxt, typeInformation);
764
761
  if (
765
- // By default undefined is equivalent to null: should not progress
766
- (attr.skipValue === undefined && res === null) ||
767
- (attr.skipValue !== undefined && res === attr.skipValue)
762
+ // By default undefined is handled like null: should not progress
763
+ // Some op results (like nonexistent * 2) are a kind of null with a number type
764
+ // but NaN value
765
+ (attr.skipValue === undefined &&
766
+ (res === null || (typeof res === 'number' && isNaN(res)))) ||
767
+ (attr.skipValue !== undefined &&
768
+ (res === attr.skipValue ||
769
+ (typeof res === 'number' && isNaN(res) && attr.skipValue === null)))
768
770
  ) {
769
771
  logger.debug(
770
772
  context,
@@ -987,25 +989,10 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
987
989
  // only in the first case
988
990
  if (options.json.entities.length === 1) {
989
991
  // recreate options object to use single entity update
990
- url = '/v2/entities';
991
- if (config.getConfig().appendMode === false) {
992
- url += '/' + entityName + '/attrs';
993
- if (typeInformation && typeInformation.type) {
994
- url += '?type=' + typeInformation.type;
995
- }
996
- } else {
997
- // appendMode === true
998
- url += '?options=upsert';
999
- }
992
+ url = '/v2/entities?options=upsert';
1000
993
  options = NGSIUtils.createRequestObject(url, typeInformation, token);
1001
994
  options.json = payload.entities[0];
1002
- if (config.getConfig().appendMode === false) {
1003
- options.method = 'PATCH';
1004
- delete options.json.id;
1005
- delete options.json.type;
1006
- } else {
1007
- options.method = 'POST';
1008
- }
995
+ options.method = 'POST';
1009
996
  } // else: keep current options object created for a batch update
1010
997
  logger.debug(context, 'Updating device value in the Context Broker at [%s]', options.url);
1011
998
  logger.debug(context, 'Using the following NGSI v2 request:\n\n%s\n\n', JSON.stringify(options, null, 4));
@@ -251,6 +251,7 @@ function handleListDevices(req, res, next) {
251
251
  function handleGetDevice(req, res, next) {
252
252
  deviceService.getDevice(
253
253
  req.params.deviceId,
254
+ req.query.apikey,
254
255
  req.headers['fiware-service'],
255
256
  req.headers['fiware-servicepath'],
256
257
  function (error, device) {
@@ -269,8 +270,8 @@ function handleGetDevice(req, res, next) {
269
270
  * This middleware handles the removal of a particular device specified with the deviceId.
270
271
  */
271
272
  function handleRemoveDevice(req, res, next) {
272
- function getDevice(deviceId, service, subservice, callback) {
273
- deviceService.getDevice(deviceId, service, subservice, function (error, device) {
273
+ function getDevice(deviceId, apikey, service, subservice, callback) {
274
+ deviceService.getDevice(deviceId, apikey, service, subservice, function (error, device) {
274
275
  if (error) {
275
276
  callback(error);
276
277
  } else if (device) {
@@ -289,18 +290,25 @@ function handleRemoveDevice(req, res, next) {
289
290
  }
290
291
  }
291
292
 
292
- function unregisterDevice(deviceId, service, subservice, device, callback) {
293
- return deviceService.unregister(deviceId, service, subservice, callback);
293
+ function unregisterDevice(deviceId, apikey, service, subservice, device, callback) {
294
+ return deviceService.unregister(deviceId, apikey, service, subservice, callback);
294
295
  }
295
296
 
296
297
  async.waterfall(
297
298
  [
298
299
  apply(statsRegistry.add, 'deviceRemovalRequests', 1),
299
- apply(getDevice, req.params.deviceId, req.headers['fiware-service'], req.headers['fiware-servicepath']),
300
+ apply(
301
+ getDevice,
302
+ req.params.deviceId,
303
+ req.query.apikey,
304
+ req.headers['fiware-service'],
305
+ req.headers['fiware-servicepath']
306
+ ),
300
307
  applyRemoveDeviceHandler,
301
308
  apply(
302
309
  unregisterDevice,
303
310
  req.params.deviceId,
311
+ req.query.apikey,
304
312
  req.headers['fiware-service'],
305
313
  req.headers['fiware-servicepath']
306
314
  )
@@ -334,6 +342,7 @@ function handleUpdateDevice(req, res, next) {
334
342
  } else {
335
343
  deviceService.getDevice(
336
344
  req.params.deviceId,
345
+ req.query.apikey,
337
346
  req.headers['fiware-service'],
338
347
  req.headers['fiware-servicepath'],
339
348
  function (error, device) {
package/mkdocs.yml CHANGED
@@ -13,15 +13,10 @@ pages:
13
13
  - Home: 'index.md'
14
14
  - 'Getting Started' : 'getting-started.md'
15
15
  - 'User & Programmers Manual':
16
- - 'Architecture' : 'architecture.md'
17
16
  - 'IoT Agent API' : 'api.md'
18
- - 'Advanced Topics' : 'advanced-topics.md'
19
- - 'Library Functions': 'usermanual.md'
20
- - 'Measurement Transformation Expression Language': 'expressionLanguage.md'
21
- - 'How to develop a new IoT Agent': 'howto.md'
22
- - 'North Port - NGSI Interactions': 'northboundinteractions.md'
23
- - 'Development Documentation': development.md
24
- - 'Installation & Administration Manual':
25
- - 'Installation Guide': 'installationguide.md'
26
- - 'Operations (logs & alarms)': 'operations.md'
27
-
17
+ - 'Installation and administration manual': 'admin.md'
18
+ - 'Development documentation':
19
+ - 'Development manual': 'devel/development.md'
20
+ - 'Contributing guide': 'devel/contribution-guidelines.md'
21
+ - 'Architecture' : 'devel/architecture.md'
22
+ - 'North Port - NGSI Interactions': 'devel/northboundinteractions.md'
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": "3.3.0",
5
+ "version": "3.4.1",
6
6
  "homepage": "https://github.com/telefonicaid/iotagent-node-lib",
7
7
  "keywords": [
8
8
  "fiware",
@@ -51,7 +51,7 @@
51
51
  "logops": "2.1.2",
52
52
  "moment": "~2.29.2",
53
53
  "moment-timezone": "~0.5.34",
54
- "mongoose": "5.13.14",
54
+ "mongoose": "5.13.20",
55
55
  "query-string": "7.1.1",
56
56
  "revalidator": "~0.3.1",
57
57
  "underscore": "~1.13.4",
@@ -65,7 +65,7 @@
65
65
  "husky": "~4.2.5",
66
66
  "lint-staged": "~12.3.8",
67
67
  "mocha": "10.0.0",
68
- "mongodb": "4.7.0",
68
+ "mongodb": "4.17.0",
69
69
  "nock": "13.2.7",
70
70
  "nyc": "~15.1.0",
71
71
  "prettier": "~2.7.1",
@@ -82,34 +82,50 @@ python legacy_expression_tool.py \
82
82
 
83
83
  The list of possible arguments that the scripts accepts are:
84
84
 
85
- | Argument | Description | Default value | Mandatory |
86
- | ---------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------- | --------- |
87
- | `--mongouri` | The MongoDB URI to connect to | `mongodb://localhost:27017/` | No |
88
- | `--database` | The database name to replace the expressions | NA | Yes |
89
- | `--collection` | The collection name to replace the expressions | NA | Yes |
90
- | `--translation` | The translation dictionary file to replace the expressions | `translation.json` | No |
91
- | `--debug` | Enable debug mode | `False` | No |
92
- | `--commit` | Commit the changes to the database | `False` | No |
85
+ | Argument | Description | Default value | Mandatory |
86
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | --------- |
87
+ | `--mongouri` | The MongoDB URI to connect to | `mongodb://localhost:27017/` | No |
88
+ | `--database` | The database name to replace the expressions | NA | Yes |
89
+ | `--collection` | The collection name to replace the expressions | NA | Yes |
90
+ | `--translation` | The translation dictionary file to replace the expressions | `translation.json` | No |
91
+ | `--debug` | Enable debug mode | `False` | No |
92
+ | `--commit` | Commit the changes to the database | `False` | No |
93
93
  | `--expressionlanguage` | What to do with the expression language field. Possibles values: `delete`, `ignore`, `jexl` or `jexlall`. More detail on this bellow. | `ignore` | No |
94
- | `--statistics` | Print match statistics. Aggregation modes are the possible values: `service` and `subservice` | `service` | No |
95
- | `--service` | The fiware service filter to replace the expressions | All subservices | No |
96
- | `--service-path` | The fiware service path filter to replace the expressions | All subservices | No |
97
- | `--deviceid` | The device id filter to replace the expressions | All devices | No |
98
- | `--entitytype` | The entity type filter to replace the expressions | All entity types | No |
99
- | `--regexservice` | The fiware service regex filter to replace the expressions | All subservices | No |
100
- | `--regexservicepath` | The fiware service path regex filter to replace the expressions | All subservices | No |
101
- | `--regexdeviceid` | The device id regex filter to replace the expressions | All devices | No |
102
- | `--regexentitytype` | The entity type regex filter to replace the expressions | All entity types | No |
94
+ | `--statistics` | Print match statistics. Aggregation modes are the possible values: `service` and `subservice` | `service` | No |
95
+ | `--service` | The fiware service filter to replace the expressions | All subservices | No |
96
+ | `--service-path` | The fiware service path filter to replace the expressions | All subservices | No |
97
+ | `--deviceid` | The device id filter to replace the expressions | All devices | No |
98
+ | `--entitytype` | The entity type filter to replace the expressions | All entity types | No |
99
+ | `--regexservice` | The fiware service regex filter to replace the expressions | All subservices | No |
100
+ | `--regexservicepath` | The fiware service path regex filter to replace the expressions | All subservices | No |
101
+ | `--regexdeviceid` | The device id regex filter to replace the expressions | All devices | No |
102
+ | `--regexentitytype` | The entity type regex filter to replace the expressions | All entity types | No |
103
103
 
104
104
  Note that filters (`--service`, `--service-path`, `--deviceid` and `--entitytype`, and the regex versions) are
105
105
  interpreted in additive way (i.e. like a logical AND).
106
106
 
107
107
  With regards to `--expressionlanguage`:
108
108
 
109
- * `delete`: changes expressions from legacy to JEXL equivalence in the [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation dictionary specified by `--translations`). In addition, deletes the `expressionLanguage` field (no matter its value) in the case it exists in the group/device.
110
- * `ignore`: changes expressions from legacy to JEXL equivalence in the [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation dictionary specified by `--translations`). In addition, it leaves untouched the `expressionLanguage` field. This may cause inconsistencies, if the value of the `expressionLanguage` is `legacy`, as detailed [in this section](#replacing-expression-without-setting-jexl-at-group-or-device-level).
111
- * `jexl`: changes expressions from legacy to JEXL equivalence in the [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation dictionary specified by `--translations`). In addition, it set `expressionLanguage` field to `jexl` (no matter if the field originally exists in the group/device or not) **if some JEXL expression were translated**.
112
- * `jexlall`: changes expression from legacy to JEXL equivalence in the [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation dictionary specified by `--translations`). In addition, it set `expressionLanguage` field to `jexl` (no matter if the field originally exists in the group/device or not). The difference between `jexl`and `jexlall` is in the second case, the script is not only looking for documents that contains legacy expressions, it also includes all groups/devices that have `expressionLanguage` field defined. The `expressionLanguage` field on those documents (and also on the documents that contains legacy expresions) is set to `jexl`.
109
+ - `delete`: changes expressions from legacy to JEXL equivalence in the
110
+ [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation
111
+ dictionary specified by `--translations`). In addition, deletes the `expressionLanguage` field (no matter its value)
112
+ in the case it exists in the group/device.
113
+ - `ignore`: changes expressions from legacy to JEXL equivalence in the
114
+ [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation
115
+ dictionary specified by `--translations`). In addition, it leaves untouched the `expressionLanguage` field. This may
116
+ cause inconsistencies, if the value of the `expressionLanguage` is `legacy`, as detailed
117
+ [in this section](#replacing-expression-without-setting-jexl-at-group-or-device-level).
118
+ - `jexl`: changes expressions from legacy to JEXL equivalence in the
119
+ [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation
120
+ dictionary specified by `--translations`). In addition, it set `expressionLanguage` field to `jexl` (no matter if
121
+ the field originally exists in the group/device or not) **if some JEXL expression were translated**.
122
+ - `jexlall`: changes expression from legacy to JEXL equivalence in the
123
+ [fields where expressions may be used](#fields-in-which-expressions-may-be-used) (based on the translation
124
+ dictionary specified by `--translations`). In addition, it set `expressionLanguage` field to `jexl` (no matter if
125
+ the field originally exists in the group/device or not). The difference between `jexl`and `jexlall` is in the second
126
+ case, the script is not only looking for documents that contains legacy expressions, it also includes all
127
+ groups/devices that have `expressionLanguage` field defined. The `expressionLanguage` field on those documents (and
128
+ also on the documents that contains legacy expresions) is set to `jexl`.
113
129
 
114
130
  ## Usage
115
131
 
@@ -231,32 +247,34 @@ All 1 1 2
231
247
 
232
248
  The script implements expression detection and translation in the following fields in group/device documents at DB:
233
249
 
234
- * active.expression
235
- * active.entity_name
236
- * active.reverse
237
- * attributes.expression
238
- * attributes.entity_name
239
- * attributes.expression
240
- * commands.expression
241
- * endpoint
242
- * entityNameExp
243
- * explicitAttrs
250
+ - active.expression
251
+ - active.entity_name
252
+ - active.reverse
253
+ - attributes.expression
254
+ - attributes.entity_name
255
+ - attributes.expression
256
+ - commands.expression
257
+ - endpoint
258
+ - entityNameExp
259
+ - explicitAttrs
244
260
 
245
261
  ### Known issues
246
262
 
247
263
  #### Execution with `expressionlanguage` set to `jexlall`
248
264
 
249
265
  When executing the script with `expressionlanguage` set to `jexlall`, the script will look for all the documents
250
- containing legacy expressions (in some of the [expression capable fields](#fields-in-which-expressions-may-be-used)) or the existence of the `expressionLanguage` field.
251
- This would change the number of documents found, and the statistics will include extra documents.
266
+ containing legacy expressions (in some of the [expression capable fields](#fields-in-which-expressions-may-be-used)) or
267
+ the existence of the `expressionLanguage` field. This would change the number of documents found, and the statistics
268
+ will include extra documents.
252
269
 
253
270
  Running the script with the option set to `jexl` would not include such extra documents in statistics.
254
271
 
255
272
  #### Replacing expression without setting jexl at group or device level
256
273
 
257
- When executing the script setting `--expressionlanguage` to `ignore` (or when `--expressionlanguage` is not used), the script will not
258
- change the`expressionLanguage` field in the document. This means that the legacy expressions will be replaced, but the
259
- `expressionLanguage` field will still be set to the default value or legacy. This would make expression evaluation to
260
- fail, propagating the value of the attribute as the expression literal to the context broker.
274
+ When executing the script setting `--expressionlanguage` to `ignore` (or when `--expressionlanguage` is not used), the
275
+ script will not change the`expressionLanguage` field in the document. This means that the legacy expressions will be
276
+ replaced, but the `expressionLanguage` field will still be set to the default value or legacy. This would make
277
+ expression evaluation to fail, propagating the value of the attribute as the expression literal to the context broker.
261
278
 
262
- To avoid this, it is recommended use always the `--expressionlangauge` parameter set to `jexl`, so doing it a value different from `ignore` will be used.
279
+ To avoid this, it is recommended use always the `--expressionlangauge` parameter set to `jexl`, so doing it a value
280
+ different from `ignore` will be used.
@@ -293,7 +293,7 @@ describe('NGSI-v2 - Secured access to the Context Broker with Keystone', functio
293
293
  });
294
294
 
295
295
  it('subscribe requests use auth header', function (done) {
296
- iotAgentLib.getDevice('Light1', 'smartgondor', 'electricity', function (error, device) {
296
+ iotAgentLib.getDevice('Light1', null, 'smartgondor', 'electricity', function (error, device) {
297
297
  iotAgentLib.subscribe(device, ['dimming'], null, function (error) {
298
298
  should.not.exist(error);
299
299
 
@@ -314,7 +314,7 @@ describe('NGSI-v2 - Secured access to the Context Broker with Keystone', functio
314
314
  'X-Subject-Token': '12345679ABCDEF'
315
315
  });
316
316
 
317
- iotAgentLib.getDevice('Light1', 'smartgondor', 'electricity', function (error, device) {
317
+ iotAgentLib.getDevice('Light1', null, 'smartgondor', 'electricity', function (error, device) {
318
318
  iotAgentLib.subscribe(device, ['dimming'], null, function (error) {
319
319
  iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function (error) {
320
320
  contextBrokerMock.done();
@@ -387,7 +387,7 @@ describe('NGSI-v2 - MongoDB Device Registry', function () {
387
387
  });
388
388
 
389
389
  it('should be removed from MongoDB', function (done) {
390
- iotAgentLib.unregister(device1.id, 'smartgondor', 'gardens', function (error) {
390
+ iotAgentLib.unregister(device1.id, null, 'smartgondor', 'gardens', function (error) {
391
391
  iotAgentDb
392
392
  .db()
393
393
  .collection('devices')