iotagent-node-lib 3.1.0 → 3.3.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 (163) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +134 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +16 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +55 -0
  4. package/.github/advanced-issue-labeler.yml +30 -0
  5. package/.github/workflows/issue-labeler.yml +43 -0
  6. package/CHANGES_NEXT_RELEASE +0 -2
  7. package/config.js +5 -5
  8. package/doc/api.md +1483 -298
  9. package/doc/deprecated.md +7 -1
  10. package/doc/development.md +120 -0
  11. package/doc/howto.md +58 -62
  12. package/doc/installationguide.md +3 -11
  13. package/doc/requirements.txt +1 -1
  14. package/docker/Mosquitto/Dockerfile +1 -1
  15. package/lib/commonConfig.js +7 -10
  16. package/lib/fiware-iotagent-lib.js +0 -10
  17. package/lib/jexlTranformsMap.js +2 -1
  18. package/lib/model/Device.js +0 -1
  19. package/lib/model/Group.js +0 -1
  20. package/lib/model/dbConn.js +1 -7
  21. package/lib/plugins/bidirectionalData.js +8 -26
  22. package/lib/plugins/expressionPlugin.js +8 -40
  23. package/lib/plugins/jexlParser.js +28 -0
  24. package/lib/services/commands/commandService.js +1 -1
  25. package/lib/services/common/iotManagerService.js +0 -1
  26. package/lib/services/devices/deviceRegistryMongoDB.js +10 -10
  27. package/lib/services/devices/deviceService.js +16 -20
  28. package/lib/services/devices/devices-NGSI-v2.js +2 -5
  29. package/lib/services/ngsi/entities-NGSI-LD.js +16 -60
  30. package/lib/services/ngsi/entities-NGSI-v2.js +179 -119
  31. package/lib/services/northBound/deviceProvisioningServer.js +17 -17
  32. package/lib/templates/createDevice.json +5 -6
  33. package/lib/templates/createDeviceLax.json +6 -8
  34. package/lib/templates/deviceGroup.json +1 -5
  35. package/lib/templates/updateDevice.json +9 -2
  36. package/lib/templates/updateDeviceLax.json +14 -5
  37. package/package.json +1 -1
  38. package/scripts/legacy_expression_tool/README.md +262 -0
  39. package/scripts/legacy_expression_tool/legacy_expression_tool.py +423 -0
  40. package/scripts/legacy_expression_tool/requirements.txt +3 -0
  41. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +5 -5
  42. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +4 -4
  43. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +3 -13
  44. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -2
  45. package/test/unit/ngsi-ld/lazyAndCommands/merge-patch-test.js +31 -30
  46. package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +8 -8
  47. package/test/unit/ngsi-ld/plugins/custom-plugin_test.js +152 -0
  48. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +1 -1
  49. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +33 -37
  50. package/test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json +5 -1
  51. package/test/unit/ngsiv2/examples/contextRequests/updateContext.json +2 -0
  52. package/test/unit/ngsiv2/examples/contextRequests/updateContext1.json +3 -1
  53. package/test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json +2 -0
  54. package/test/unit/ngsiv2/examples/contextRequests/updateContext4.json +4 -1
  55. package/test/unit/ngsiv2/examples/contextRequests/updateContext5.json +12 -0
  56. package/test/unit/ngsiv2/examples/contextRequests/updateContext6.json +10 -0
  57. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin1.json +2 -0
  58. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin2.json +3 -1
  59. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json +3 -1
  60. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin4.json +3 -1
  61. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin5.json +3 -1
  62. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin6.json +3 -1
  63. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin7.json +3 -1
  64. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin8.json +3 -1
  65. package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin9.json +3 -1
  66. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast1.json +2 -0
  67. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast2.json +2 -0
  68. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast3.json +3 -1
  69. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast4.json +3 -1
  70. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast5.json +3 -1
  71. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast6.json +3 -1
  72. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast7.json +3 -1
  73. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandError.json +3 -1
  74. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandExpired.json +3 -1
  75. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandFinish.json +3 -1
  76. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json +2 -0
  77. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus2.json +2 -0
  78. package/test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp1.json +3 -1
  79. package/test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp2.json +3 -1
  80. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json +2 -0
  81. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json +2 -0
  82. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json +2 -0
  83. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json +3 -1
  84. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json +2 -0
  85. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin29.json +2 -0
  86. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json +2 -0
  87. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin30.json +2 -0
  88. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin31.json +2 -8
  89. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin32.json +2 -0
  90. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin33.json +2 -0
  91. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin34.json +2 -0
  92. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin35.json +22 -0
  93. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json +1 -0
  94. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin4.json +2 -0
  95. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin40.json +42 -0
  96. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +33 -0
  97. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json +2 -0
  98. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json +2 -0
  99. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json +2 -0
  100. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json +2 -0
  101. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json +2 -0
  102. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionSkip.json +12 -0
  103. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityJexlExpressionPlugin1.json +1 -1
  104. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin1.json +1 -1
  105. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin10.json +1 -1
  106. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin11.json +1 -1
  107. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin12.json +1 -1
  108. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin13.json +1 -1
  109. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin14.json +1 -1
  110. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin15.json +1 -1
  111. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin16.json +1 -1
  112. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json +1 -1
  113. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin2.json +1 -1
  114. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +37 -0
  115. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin3.json +1 -1
  116. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin4.json +1 -1
  117. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin5.json +1 -1
  118. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin6.json +1 -1
  119. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin7.json +1 -1
  120. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin8.json +1 -1
  121. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin9.json +1 -1
  122. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin1.json +1 -1
  123. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +1 -1
  124. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin3.json +1 -1
  125. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin4.json +2 -0
  126. package/test/unit/ngsiv2/examples/contextRequests/updateContextProcessTimestamp.json +2 -0
  127. package/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json +2 -0
  128. package/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributesMetadata.json +3 -1
  129. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestamp.json +3 -1
  130. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampFalse.json +12 -0
  131. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampFalseTimeInstant.json +12 -0
  132. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json +2 -0
  133. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverrideWithoutMilis.json +2 -0
  134. package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampTimezone.json +3 -1
  135. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +355 -75
  136. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +18 -51
  137. package/test/unit/ngsiv2/general/https-support-test.js +1 -5
  138. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +4 -10
  139. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +9 -26
  140. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +143 -57
  141. package/test/unit/ngsiv2/ngsiService/autocast-test.js +14 -21
  142. package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +3 -5
  143. package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +1 -10
  144. package/test/unit/ngsiv2/plugins/alias-plugin_test.js +20 -30
  145. package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +6 -69
  146. package/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js +4 -6
  147. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +150 -0
  148. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +87 -16
  149. package/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js +2 -3
  150. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +2 -3
  151. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +15 -55
  152. package/test/unit/ngsiv2/provisioning/device-registration_test.js +1 -7
  153. package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +2 -9
  154. package/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js +0 -11
  155. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +0 -7
  156. package/test/unit/plugins/capture-provision-inPlugins_test.js +0 -6
  157. package/doc/advanced-topics.md +0 -626
  158. package/doc/expressionLanguage.md +0 -762
  159. package/lib/plugins/expressionParser.js +0 -205
  160. package/test/unit/expressions/expression-test.js +0 -197
  161. package/test/unit/ngsi-ld/expressions/expressionBasedTransformations-test.js +0 -882
  162. package/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js +0 -951
  163. package/test/unit/ngsiv2/expressions/expressionCombinedTransformations-test.js +0 -296
@@ -106,13 +106,7 @@ function init(host, db, port, options, callback) {
106
106
  }
107
107
 
108
108
  function connectionAttempt(url, options, callback) {
109
- logger.info(
110
- context,
111
- 'Attempting to connect to MongoDB instance with url %j and options %j. Attempt %d',
112
- url,
113
- options,
114
- retries
115
- );
109
+ logger.info(context, 'Attempting to connect to MongoDB instance with url %j. Attempt %d', url, retries);
116
110
  // FIXME: useNewUrlParser is no longer used in underlying mongodb driver 4.x
117
111
  // (see https://github.com/mongodb/node-mongodb-native/blob/HEAD/etc/notes/CHANGES_4.0.0.md)
118
112
  // but not sure if current mongoose version is still using mongodb 3.x internally
@@ -75,9 +75,7 @@ function extractVariables(item) {
75
75
 
76
76
  function extractFromExpression(value) {
77
77
  if (value.expression) {
78
- return value.expression.match(/@[a-zA-Z]+/g).map(function (item) {
79
- return item.substr(1);
80
- });
78
+ return parser.extractVariables(value.expression);
81
79
  }
82
80
  return [];
83
81
  }
@@ -157,9 +155,7 @@ function getReverseTransformations(list, values, callback) {
157
155
  let transformations = [];
158
156
 
159
157
  function getVariable(expression) {
160
- return expression.match(/@[a-zA-Z]+/g).map(function (item) {
161
- return item.substr(1);
162
- });
158
+ return parser.extractVariables(expression);
163
159
  }
164
160
 
165
161
  if (list && list.length > 0) {
@@ -191,7 +187,7 @@ function getReverseTransformations(list, values, callback) {
191
187
  */
192
188
  function processTransformationsNGSIv2(values, typeInformation, transformations, callback) {
193
189
  let cleanedExpression;
194
- const ctx = parser.extractContext(values, typeInformation);
190
+ const ctx = parser.extractContext(values);
195
191
  let resultTransformations = [];
196
192
 
197
193
  for (let j = 0; j < 2; j++) {
@@ -201,10 +197,7 @@ function processTransformationsNGSIv2(values, typeInformation, transformations,
201
197
  }
202
198
 
203
199
  for (let i = 0; i < resultTransformations.length; i++) {
204
- cleanedExpression = resultTransformations[i].expression.substr(
205
- 2,
206
- resultTransformations[i].expression.length - 3
207
- );
200
+ cleanedExpression = resultTransformations[i].expression;
208
201
 
209
202
  values.push({
210
203
  name: resultTransformations[i].object_id,
@@ -252,20 +245,12 @@ function processTransformationsNGSILD(values, typeInformation, transformations,
252
245
  // This is the direct equivalent of the NGSI-v2 function
253
246
  if (!_.isEmpty(defaultValues)) {
254
247
  for (let i = 0; i < resultTransformations.length; i++) {
255
- cleanedExpression = resultTransformations[i].expression.substr(
256
- 2,
257
- resultTransformations[i].expression.length - 3
258
- );
248
+ cleanedExpression = resultTransformations[i].expression;
259
249
  values.push({
260
250
  name: resultTransformations[i].object_id,
261
251
  type: resultTransformations[i].type,
262
252
  metadata: {},
263
- value: parser.parse(
264
- cleanedExpression,
265
- parser.extractContext(defaultValues, typeInformation),
266
- 'String',
267
- typeInformation
268
- )
253
+ value: parser.parse(cleanedExpression, parser.extractContext(defaultValues), 'String', typeInformation)
269
254
  });
270
255
  }
271
256
  }
@@ -274,10 +259,7 @@ function processTransformationsNGSILD(values, typeInformation, transformations,
274
259
  // There is no equivalent with NGSI-v2
275
260
  _.keys(datasetIds).forEach((datasetId) => {
276
261
  for (let i = 0; i < resultTransformations.length; i++) {
277
- cleanedExpression = resultTransformations[i].expression.substr(
278
- 2,
279
- resultTransformations[i].expression.length - 3
280
- );
262
+ cleanedExpression = resultTransformations[i].expression;
281
263
  values.push({
282
264
  name: resultTransformations[i].object_id,
283
265
  type: resultTransformations[i].type,
@@ -285,7 +267,7 @@ function processTransformationsNGSILD(values, typeInformation, transformations,
285
267
  metadata: {},
286
268
  value: parser.parse(
287
269
  cleanedExpression,
288
- parser.extractContext(datasetIds[datasetId], typeInformation),
270
+ parser.extractContext(datasetIds[datasetId]),
289
271
  'String',
290
272
  typeInformation
291
273
  )
@@ -24,9 +24,7 @@
24
24
  * Modified by: Federico M. Facca - Martel Innovate
25
25
  */
26
26
 
27
- const legacyParser = require('./expressionParser');
28
27
  const jexlParser = require('./jexlParser');
29
- const config = require('../commonConfig');
30
28
  /* eslint-disable no-unused-vars */
31
29
  const logger = require('logops');
32
30
  const errors = require('../errors');
@@ -44,53 +42,23 @@ function setJEXLTransforms(transformationMap) {
44
42
  }
45
43
 
46
44
  function applyExpression(expression, context, typeInformation) {
47
- let parser = jexlParser;
48
- if (!checkJexl(typeInformation)) {
49
- parser = legacyParser;
50
- }
51
- return parser.applyExpression(expression, context, typeInformation);
45
+ return jexlParser.applyExpression(expression, context, typeInformation);
52
46
  }
53
47
 
54
- function extractContext(attributeList, typeInformation) {
55
- let parser = jexlParser;
56
- if (!checkJexl(typeInformation)) {
57
- parser = legacyParser;
58
- }
59
- return parser.extractContext(attributeList);
48
+ function extractContext(attributeList) {
49
+ return jexlParser.extractContext(attributeList);
60
50
  }
61
51
 
62
- function parse(expression, context, type, typeInformation) {
63
- if (!checkJexl(typeInformation)) {
64
- return legacyParser.parse(expression, context, type);
65
- }
52
+ function parse(expression, context) {
66
53
  return jexlParser.parse(expression, context);
67
54
  }
68
55
 
69
56
  function contextAvailable(expression, context, typeInformation) {
70
- let parser = jexlParser;
71
- if (!checkJexl(typeInformation)) {
72
- parser = legacyParser;
73
- }
74
- return parser.contextAvailable(expression, context);
57
+ return jexlParser.contextAvailable(expression, context);
75
58
  }
76
59
 
77
- function checkJexl(typeInformation) {
78
- if (
79
- config.getConfig().defaultExpressionLanguage === 'jexl' &&
80
- typeInformation.expressionLanguage &&
81
- typeInformation.expressionLanguage !== 'legacy'
82
- ) {
83
- return true;
84
- } else if (config.getConfig().defaultExpressionLanguage === 'jexl' && !typeInformation.expressionLanguage) {
85
- return true;
86
- } else if (
87
- config.getConfig().defaultExpressionLanguage === 'legacy' &&
88
- typeInformation.expressionLanguage &&
89
- typeInformation.expressionLanguage === 'jexl'
90
- ) {
91
- return true;
92
- }
93
- return false;
60
+ function extractVariables(expression) {
61
+ return jexlParser.extractVariables(expression);
94
62
  }
95
63
 
96
64
  exports.parse = parse;
@@ -98,4 +66,4 @@ exports.setJEXLTransforms = setJEXLTransforms;
98
66
  exports.applyExpression = applyExpression;
99
67
  exports.extractContext = extractContext;
100
68
  exports.contextAvailable = contextAvailable;
101
- exports.checkJexl = checkJexl;
69
+ exports.extractVariables = extractVariables;
@@ -28,6 +28,8 @@
28
28
  /* eslint-disable no-unused-vars */
29
29
 
30
30
  const jexl = require('jexl');
31
+ const grammar = require('jexl/dist/grammar').getGrammar();
32
+ const Lexer = require('jexl/dist/Lexer');
31
33
  const errors = require('../errors');
32
34
  const logger = require('logops');
33
35
  const fillService = require('../services/common/domain').fillService;
@@ -62,6 +64,31 @@ function parse(expression, context, callback) {
62
64
  }
63
65
  }
64
66
 
67
+ function extractVariables(expression) {
68
+ const inst = new Lexer(grammar);
69
+ let variables = [];
70
+
71
+ try {
72
+ const tokens = inst.tokenize(expression);
73
+
74
+ // Keep only root attributes, removing the dot and sub-attributes. For example, if we have
75
+ // a.0.b, a.1.b and a.2.b, we will only keep a
76
+ // Additionaly, it will remove the function calls, since they are also detected as identifiers
77
+ variables = tokens.filter(function (token, index, array) {
78
+ return (
79
+ (token.type === ' ' && array[index - 1].type !== 'dot') ||
80
+ (token.type === 'identifier' && array[index + 1] && array[index + 1].type !== 'openParen')
81
+ );
82
+ });
83
+
84
+ // Return only array of values
85
+ return variables.map((a) => a.value);
86
+ } catch (e) {
87
+ logger.warn(logContext, 'Wrong expression found "[%j]" error: "[%s]", it will be ignored', expression, e);
88
+ return false;
89
+ }
90
+ }
91
+
65
92
  function extractContext(attributeList) {
66
93
  const context = {};
67
94
  let value;
@@ -162,6 +189,7 @@ function setTransforms(configMap) {
162
189
  logger.info(logContext, message);
163
190
  }
164
191
 
192
+ exports.extractVariables = extractVariables;
165
193
  exports.extractContext = extractContext;
166
194
  exports.contextAvailable = contextAvailable;
167
195
  exports.applyExpression = applyExpression;
@@ -58,7 +58,7 @@ function addCommandDevice(service, subservice, device, command, callback) {
58
58
  // The context for the JEXL expression should be the ID, TYPE, S, SS
59
59
  let attrList = pluginUtils.getIdTypeServSubServiceFromDevice(device);
60
60
  attrList = device.staticAttributes ? attrList.concat(device.staticAttributes) : attrList.concat([]);
61
- let ctxt = parser.extractContext(attrList, device);
61
+ let ctxt = parser.extractContext(attrList);
62
62
  logger.debug(context, 'attrList [%j] for device %j', attrList, device);
63
63
  // expression result will be the full command payload
64
64
  let cmdValueRes = null;
@@ -58,7 +58,6 @@ function register(callback) {
58
58
  timestamp: service.timestamp,
59
59
  autoprovision: service.autoprovision,
60
60
  explicitAttrs: service.explicitAttrs,
61
- expressionLanguage: service.expressionLanguage,
62
61
  defaultEntityNameConjunction: service.defaultEntityNameConjunction,
63
62
  ngsiVersion: service.ngsiVersion,
64
63
  entityNameExp: service.entityNameExp
@@ -55,7 +55,6 @@ const attributeList = [
55
55
  'polling',
56
56
  'timestamp',
57
57
  'explicitAttrs',
58
- 'expressionLanguage',
59
58
  'ngsiVersion'
60
59
  ];
61
60
 
@@ -176,15 +175,15 @@ function listDevices(type, service, subservice, limit, offset, callback) {
176
175
  query.skip(parseInt(offset, 10));
177
176
  }
178
177
 
179
- async.series([query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)], function (
180
- error,
181
- results
182
- ) {
183
- callback(error, {
184
- count: results[1],
185
- devices: results[0]
186
- });
187
- });
178
+ async.series(
179
+ [query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)],
180
+ function (error, results) {
181
+ callback(error, {
182
+ count: results[1],
183
+ devices: results[0]
184
+ });
185
+ }
186
+ );
188
187
  }
189
188
 
190
189
  function findOneInMongoDB(queryParams, id, callback) {
@@ -303,6 +302,7 @@ function update(device, callback) {
303
302
  data.registrationId = device.registrationId;
304
303
  data.explicitAttrs = device.explicitAttrs;
305
304
  data.ngsiVersion = device.ngsiVersion;
305
+ data.timestamp = device.timestamp;
306
306
 
307
307
  /* eslint-disable-next-line new-cap */
308
308
  const deviceObj = new Device.model(data);
@@ -72,7 +72,12 @@ function init() {
72
72
  * @param {Object} newDevice Device object that will be stored in the database.
73
73
  */
74
74
  function createInitialEntity(deviceData, newDevice, callback) {
75
- deviceHandler.createInitialEntity(deviceData, newDevice, callback);
75
+ if (config.getConfig().appendMode === false || config.ngsiVersion() === 'ld' || deviceData.ngsiVersion === 'ld') {
76
+ deviceHandler.createInitialEntity(deviceData, newDevice, callback);
77
+ } else {
78
+ logger.debug(context, 'Skip create initial entity due appendMode is false or ngsiLD.');
79
+ callback(null, newDevice);
80
+ }
76
81
  }
77
82
 
78
83
  /**
@@ -178,13 +183,12 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio
178
183
  if (configuration && configuration.ngsiVersion) {
179
184
  deviceData.ngsiVersion = configuration.ngsiVersion;
180
185
  }
181
- if (configuration && configuration.expressionLanguage && deviceData.expressionLanguage === undefined) {
182
- deviceData.expressionLanguage = configuration.expressionLanguage;
183
- }
184
186
  if (configuration && configuration.explicitAttrs !== undefined && deviceData.explicitAttrs === undefined) {
185
187
  deviceData.explicitAttrs = configuration.explicitAttrs;
186
188
  }
187
-
189
+ if (configuration && configuration.entityNameExp !== undefined) {
190
+ deviceData.entityNameExp = configuration.entityNameExp;
191
+ }
188
192
  logger.debug(context, 'deviceData after merge with conf: %j', deviceData);
189
193
  callback(null, deviceData);
190
194
  }
@@ -265,7 +269,7 @@ function registerDevice(deviceObj, callback) {
265
269
  function prepareDeviceData(deviceObj, configuration, callback) {
266
270
  const deviceData = _.clone(deviceObj);
267
271
  let selectedConfiguration;
268
-
272
+ logger.debug(context, 'Prepare device data:\n%s', JSON.stringify(deviceData, null, 4));
269
273
  if (!deviceData.type) {
270
274
  if (configuration && configuration.type) {
271
275
  deviceData.type = configuration.type;
@@ -294,7 +298,8 @@ function registerDevice(deviceObj, callback) {
294
298
  // Add device ID, TYPE, S, SS to the context for the JEXL expression
295
299
  let attrList = pluginUtils.getIdTypeServSubServiceFromDevice(deviceData);
296
300
  attrList = deviceData.staticAttributes ? attrList.concat(deviceData.staticAttributes) : attrList;
297
- let ctxt = expressionPlugin.extractContext(attrList, deviceData);
301
+ attrList = configuration.staticAttributes ? attrList.concat(configuration.staticAttributes) : attrList;
302
+ let ctxt = expressionPlugin.extractContext(attrList);
298
303
  try {
299
304
  entityName = expressionPlugin.applyExpression(configuration.entityNameExp, ctxt, deviceData);
300
305
  } catch (e) {
@@ -361,9 +366,9 @@ function registerDevice(deviceObj, callback) {
361
366
  deviceObj.service = deviceData.service;
362
367
  deviceObj.subservice = deviceData.subservice;
363
368
  deviceObj.type = deviceData.type;
364
- deviceObj.staticAttributes = deviceData.staticAttributes;
365
- deviceObj.commands = deviceData.commands;
366
- deviceObj.lazy = deviceData.lazy;
369
+ deviceObj.staticAttributes = deviceObj.staticAttributes ? deviceObj.staticAttributes : [];
370
+ deviceObj.commands = deviceObj.commands ? deviceObj.commands : [];
371
+ deviceObj.lazy = deviceObj.lazy ? deviceObj.lazy : [];
367
372
  if ('timestamp' in deviceData && deviceData.timestamp !== undefined) {
368
373
  deviceObj.timestamp = deviceData.timestamp;
369
374
  }
@@ -373,6 +378,7 @@ function registerDevice(deviceObj, callback) {
373
378
  if ('apikey' in deviceData && deviceData.apikey !== undefined) {
374
379
  deviceObj.apikey = deviceData.apikey;
375
380
  }
381
+ logger.debug(context, 'Storing device :\n%s', JSON.stringify(deviceObj, null, 4));
376
382
  config.getRegistry().store(deviceObj, callback);
377
383
  }
378
384
  }
@@ -617,19 +623,9 @@ function findOrCreate(deviceId, group, callback) {
617
623
  if (config.getConfig().iotManager && config.getConfig().iotManager.protocol) {
618
624
  newDevice.protocol = config.getConfig().iotManager.protocol;
619
625
  }
620
-
621
- if ('timestamp' in group && group.timestamp !== undefined) {
622
- newDevice.timestamp = group.timestamp;
623
- }
624
626
  if ('ngsiVersion' in group && group.ngsiVersion !== undefined) {
625
627
  newDevice.ngsiVersion = group.ngsiVersion;
626
628
  }
627
- if ('explicitAttrs' in group && group.explicitAttrs !== undefined) {
628
- newDevice.explicitAttrs = group.explicitAttrs;
629
- }
630
- if ('expressionLanguage' in group && group.expressionLanguage !== undefined) {
631
- newDevice.expressionLanguage = group.expressionLanguage;
632
- }
633
629
  if (
634
630
  (!('apikey' in newDevice) || newDevice.apikey === undefined) &&
635
631
  'apikey' in group &&
@@ -240,7 +240,7 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) {
240
240
  }
241
241
  }
242
242
 
243
- logger.debug(context, 'deviceData: %j', deviceData);
243
+ logger.debug(context, 'Creating initial entity with deviceData: %j', deviceData);
244
244
  if (
245
245
  ('timestamp' in deviceData && deviceData.timestamp !== undefined
246
246
  ? deviceData.timestamp
@@ -356,11 +356,8 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
356
356
  if ('explicitAttrs' in newDevice && newDevice.explicitAttrs !== undefined) {
357
357
  oldDevice.explicitAttrs = newDevice.explicitAttrs;
358
358
  }
359
- if ('expressionLanguage' in newDevice && newDevice.expressionLanguage !== undefined) {
360
- oldDevice.expressionLanguage = newDevice.expressionLanguage;
361
- }
362
359
  if ('apikey' in newDevice && newDevice.apikey !== undefined) {
363
- oldDevice.explicitAttrs = newDevice.apikey;
360
+ oldDevice.apikey = newDevice.apikey;
364
361
  }
365
362
  oldDevice.endpoint = newDevice.endpoint || oldDevice.endpoint;
366
363
 
@@ -410,16 +410,6 @@ function addLinkedEntities(typeInformation, json) {
410
410
  });
411
411
  }
412
412
 
413
- /**
414
- * Determines if a value is of type float
415
- *
416
- * @param {String} value Value to be analyzed
417
- * @return {boolean} True if float, False otherwise.
418
- */
419
- function isFloat(value) {
420
- return !isNaN(value) && value.toString().indexOf('.') !== -1;
421
- }
422
-
423
413
  /**
424
414
  * Makes an update in the Device's entity in the context broker, with the values given in the 'attributes' array.
425
415
  * This array should comply to the NGSI-LD's attribute format.
@@ -449,10 +439,10 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
449
439
  payload[0].type = typeInformation.type;
450
440
  }
451
441
 
452
- if (config.getConfig().appendMode === true) {
453
- payload.actionType = 'append';
454
- } else {
442
+ if (config.getConfig().appendMode === false) {
455
443
  payload.actionType = 'update';
444
+ } else {
445
+ payload.actionType = 'append';
456
446
  }
457
447
 
458
448
  const options = NGSIUtils.createRequestObject(url, typeInformation, token);
@@ -535,7 +525,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
535
525
  }
536
526
  }
537
527
  // This context is just to calculate explicitAttrs when is an expression
538
- let ctxt = expressionPlugin.extractContext(attributesCtxt.concat(idTypeSSSList), typeInformation);
528
+ let ctxt = expressionPlugin.extractContext(attributesCtxt.concat(idTypeSSSList));
539
529
  // typeInformation.active attrs with expressions expanded by current ctxt
540
530
  if (typeInformation.active) {
541
531
  typeInformation.active.forEach(function (att) {
@@ -547,10 +537,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
547
537
  type: att.type
548
538
  };
549
539
  attributesCtxt.push(expandedAttr);
550
- ctxt = expressionPlugin.extractContext(
551
- attributesCtxt.concat(idTypeSSSList),
552
- typeInformation
553
- );
540
+ ctxt = expressionPlugin.extractContext(attributesCtxt.concat(idTypeSSSList));
554
541
  }
555
542
  }
556
543
  });
@@ -689,7 +676,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
689
676
  });
690
677
  }
691
678
  attributesCtxt = attributesCtxt.concat(idTypeSSSList);
692
- const ctxt = expressionPlugin.extractContext(attributesCtxt, typeInformation);
679
+ const ctxt = expressionPlugin.extractContext(attributesCtxt);
693
680
  logger.debug(context, 'sendUpdateValueNgsiLD \n initial ctxt %j ', ctxt);
694
681
 
695
682
  // Sort currentEntity to get first attrs without expressions (checking attrs in typeInformation.active)
@@ -791,47 +778,12 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
791
778
  }
792
779
  } catch (e) {
793
780
  logger.error(context, 'sendUpdateValueNgsiLD \n apply expression exception %j \n', e);
794
- if (!expressionPlugin.checkJexl(typeInformation)) {
795
- return callback(e); // just throw error with legacy parser for backward compatiblity
796
- } else {
797
- res = ctxt[attr.name]; // TBD: add reference to test
798
- }
799
- }
800
- if (!expressionPlugin.checkJexl(typeInformation)) {
801
- // legacy expression plugin: Involves some legacy checks performed by applierExpression
802
- if (
803
- res &&
804
- res !== 'undefined' &&
805
- res !== 'null' &&
806
- (typeof res === 'string' || res instanceof String) &&
807
- !res.includes('NaN')
808
- ) {
809
- newAttr.value = res;
810
- if (newAttr.type === 'Number' && isFloat(newAttr.value)) {
811
- newAttr.value = Number.parseFloat(newAttr.value);
812
- } else if (newAttr.type === 'Number' && !Number.isNaN(Number.parseInt(newAttr.value))) {
813
- newAttr.value = Number.parseInt(newAttr.value);
814
- } else if (newAttr.type === 'Boolean') {
815
- newAttr.value = newAttr.value === 'true' || newAttr.value === '1';
816
- } else if (newAttr.type === 'None') {
817
- newAttr.value = null;
818
- }
819
- } else if (isNaN(res) || res === 'undefined' || res === 'null') {
820
- logger.debug(
821
- context,
822
- 'sendUpdateValueNgsiLD \n apply expression result: isNaN || undefined || null'
823
- );
824
- if (res === 'null' && newAttr.type === 'None') {
825
- newAttr.value = null;
826
- } else {
827
- delete payload[0][j]; // remove measure attr
828
- attr = undefined; // stop process attr
829
- }
830
- }
831
- } else {
832
- // jexl expression plugin
833
- newAttr.value = res;
781
+ res = ctxt[attr.name]; // TBD: add reference to test
834
782
  }
783
+
784
+ // jexl expression plugin
785
+ newAttr.value = res;
786
+
835
787
  logger.debug(
836
788
  context,
837
789
  'sendUpdateValueNgsiLD \n apply expression result %j \n newAttr %j',
@@ -1048,5 +1000,9 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
1048
1000
 
1049
1001
  exports.convertAttrNGSILD = convertAttrNGSILD;
1050
1002
  exports.formatAsNGSILD = formatAsNGSILD;
1051
- exports.sendUpdateValue = sendUpdateValueNgsiLD;
1003
+ exports.sendUpdateValue = function (entityName, attributes, typeInformation, token, callback) {
1004
+ NGSIUtils.applyMiddlewares(NGSIUtils.updateMiddleware, attributes, typeInformation, () => {
1005
+ return sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, callback);
1006
+ });
1007
+ };
1052
1008
  exports.sendQueryValue = sendQueryValueNgsiLD;