iotagent-node-lib 4.8.0 → 4.9.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 (89) hide show
  1. package/.github/workflows/ci.yml +4 -1
  2. package/.nyc_output/e4b1fe20-197e-4221-9f8d-6db65ff234b2.json +1 -0
  3. package/.nyc_output/processinfo/e4b1fe20-197e-4221-9f8d-6db65ff234b2.json +1 -0
  4. package/.nyc_output/processinfo/index.json +1 -0
  5. package/Changelog +785 -0
  6. package/doc/admin.md +8 -4
  7. package/doc/api.md +1 -1
  8. package/lib/commonConfig.js +11 -2
  9. package/lib/services/common/domain.js +4 -3
  10. package/lib/services/devices/devices-NGSI-LD.js +1 -2
  11. package/lib/services/devices/devices-NGSI-v2.js +1 -2
  12. package/lib/services/ngsi/entities-NGSI-LD.js +69 -13
  13. package/lib/services/ngsi/ngsiService.js +3 -1
  14. package/lib/services/northBound/contextServer-NGSI-LD.js +5 -3
  15. package/lib/services/northBound/northboundServer.js +1 -1
  16. package/lib/services/northBound/restUtils.js +6 -2
  17. package/package.json +1 -1
  18. package/test/functional/config-test.js +1 -1
  19. package/test/unit/ngsi-ld/examples/contextRequests/createDatetimeProvisionedDevice.json +1 -4
  20. package/test/unit/ngsi-ld/examples/contextRequests/createProvisionedDevice.json +3 -12
  21. package/test/unit/ngsi-ld/examples/contextRequests/createProvisionedDeviceMultientity.json +3 -12
  22. package/test/unit/ngsi-ld/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic.json +6 -24
  23. package/test/unit/ngsi-ld/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic2.json +1 -4
  24. package/test/unit/ngsi-ld/examples/contextRequests/updateContext1.json +1 -4
  25. package/test/unit/ngsi-ld/examples/contextRequests/updateContext3WithStatic.json +1 -4
  26. package/test/unit/ngsi-ld/examples/contextRequests/updateContext4.json +1 -4
  27. package/test/unit/ngsi-ld/examples/contextRequests/updateContext5.json +1 -4
  28. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAliasPlugin6.json +1 -4
  29. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAliasPlugin7.json +1 -4
  30. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAliasPlugin8.json +4 -2
  31. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAliasPlugin9.json +1 -4
  32. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCommandError.json +3 -9
  33. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCommandExpired.json +13 -19
  34. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCommandFinish.json +13 -19
  35. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCommandStatus1.json +4 -9
  36. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCompressTimestamp1.json +1 -4
  37. package/test/unit/ngsi-ld/examples/contextRequests/updateContextCompressTimestamp2.json +1 -4
  38. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +1 -4
  39. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json +2 -8
  40. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +1 -4
  41. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin4.json +2 -8
  42. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin4a.json +3 -12
  43. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin6.json +3 -5
  44. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin7.json +1 -4
  45. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin8a.json +1 -4
  46. package/test/unit/ngsi-ld/examples/contextRequests/updateContextJsonProperty.json +13 -0
  47. package/test/unit/ngsi-ld/examples/contextRequests/updateContextListProperty.json +14 -0
  48. package/test/unit/ngsi-ld/examples/contextRequests/updateContextListRelationship.json +14 -0
  49. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin1.json +2 -8
  50. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin2.json +2 -8
  51. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin3.json +3 -8
  52. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin4.json +1 -4
  53. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin5.json +2 -8
  54. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin8.json +2 -8
  55. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin1.json +2 -8
  56. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +1 -4
  57. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin3.json +1 -4
  58. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin4.json +2 -8
  59. package/test/unit/ngsi-ld/examples/contextRequests/updateContextRelationship.json +11 -0
  60. package/test/unit/ngsi-ld/examples/contextRequests/updateContextValueType1.json +51 -0
  61. package/test/unit/ngsi-ld/examples/contextRequests/updateContextValueType2.json +65 -0
  62. package/test/unit/ngsi-ld/examples/contextRequests/updateContextVocabProperty.json +11 -0
  63. package/test/unit/ngsi-ld/examples/contextRequests/updateProvisionCommands1.json +2 -8
  64. package/test/unit/ngsi-ld/examples/contextRequests/updateProvisionDeviceStatic.json +1 -4
  65. package/test/unit/ngsi-ld/general/startup-test.js +3 -0
  66. package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +1 -1
  67. package/test/unit/ngsi-ld/lazyAndCommands/lazy-devices-test.js +71 -1
  68. package/test/unit/ngsi-ld/ngsiService/attributeTypes-test.js +293 -0
  69. package/test/unit/ngsi-ld/ngsiService/unsupported-endpoints-test.js +0 -10
  70. package/test/unit/ngsi-ld/ngsiService/value-types-test.js +221 -0
  71. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast1.json +0 -11
  72. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast10.json +0 -14
  73. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast2.json +0 -11
  74. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast3.json +0 -11
  75. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast4.json +0 -11
  76. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast5.json +0 -7
  77. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast6.json +0 -17
  78. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast7.json +0 -19
  79. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast8.json +0 -14
  80. package/test/unit/ngsi-ld/examples/contextRequests/updateContextAutocast9.json +0 -14
  81. package/test/unit/ngsi-ld/ngsiService/languageProperties-test.js +0 -109
  82. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast1.json +0 -8
  83. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast2.json +0 -8
  84. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast3.json +0 -8
  85. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast4.json +0 -8
  86. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast5.json +0 -8
  87. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast6.json +0 -8
  88. package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast7.json +0 -8
  89. /package/test/unit/ngsi-ld/examples/contextRequests/{updateContextLanguageProperties1.json → updateContextLanguageProperty.json} +0 -0
package/doc/admin.md CHANGED
@@ -145,7 +145,8 @@ used by default. E.g.:
145
145
  When connected to an **NGSI-LD** context broker, an IoT Agent is able to indicate whether it is willing to accept `null`
146
146
  values and also whether it is able to process the **NGSI-LD** `datasetId` metadata element. Setting these values to
147
147
  `false` will cause the IoT Agent to return a 400 **Bad Request** HTTP status code explaining that the IoT Agent does not
148
- support nulls or multi-attribute requests if they are encountered.
148
+ support nulls or multi-attribute requests if they are encountered. It is also possible to pass on attribute datatypes
149
+ using `@type` or `valueType` if desired.
149
150
 
150
151
  ```javascript
151
152
  {
@@ -153,7 +154,8 @@ support nulls or multi-attribute requests if they are encountered.
153
154
  port: 4041,
154
155
  ldSupport : {
155
156
  null: true,
156
- datasetId: true
157
+ datasetId: true,
158
+ datatype: 'valueType'
157
159
  }
158
160
  }
159
161
  ```
@@ -446,8 +448,9 @@ For example in a device document stored in MongoDB will be extended with a subdo
446
448
 
447
449
  #### `useCBflowControl`
448
450
 
449
- If this flag is activated, when iotAgent invokes Context Broker will use [flowControl option](https://github.com/telefonicaid/fiware-orion/blob/master/doc/manuals/admin/perf_tuning.md#updates-flow-control-mechanism). This flag is overwritten by
450
- `useCBflowControl` flag in group or device. This flag is disabled by default.
451
+ If this flag is activated, when iotAgent invokes Context Broker will use
452
+ [flowControl option](https://github.com/telefonicaid/fiware-orion/blob/master/doc/manuals/admin/perf_tuning.md#updates-flow-control-mechanism).
453
+ This flag is overwritten by `useCBflowControl` flag in group or device. This flag is disabled by default.
451
454
 
452
455
  ### Configuration using environment variables
453
456
 
@@ -465,6 +468,7 @@ overrides.
465
468
  | IOTA_CB_NGSI_VERSION | `contextBroker.ngsiVersion` |
466
469
  | IOTA_NORTH_HOST | `server.host` |
467
470
  | IOTA_NORTH_PORT | `server.port` |
471
+ | IOTA_LD_SUPPORT_DATA_TYPE | `server.ldSupport.datatype` |
468
472
  | IOTA_LD_SUPPORT_NULL | `server.ldSupport.null` |
469
473
  | IOTA_LD_SUPPORT_DATASET_ID | `server.ldSupport.datasetId` |
470
474
  | IOTA_PROVIDER_URL | `providerUrl` |
package/doc/api.md CHANGED
@@ -2463,4 +2463,4 @@ updateEntityRequestsError 5
2463
2463
  [18]:
2464
2464
  https://czosel.github.io/jexl-playground/#/?context=%7B%0A%20%20%22value%22%20%3A%206%2C%0A%20%20%22ts%22%3A%201637245214901%2C%0A%20%22name%22%3A%20%22DevId629%22%2C%0A%20%22object%22%3A%7Bname%3A%20%22John%22%2C%20surname%3A%20%22Doe%22%7D%2C%0A%20%20%22array%22%3A%5B1%2C3%5D%0A%7D&input=name%7Csubstr(0%2Cname%7CindexOf(%22e%22)%2B1)&transforms=%7B%0A%20%20%20%20jsonparse%3A%20(str)%20%3D%3E%20JSON.parse(str)%2C%0A%20%20%20%20jsonstringify%3A%20(obj)%20%3D%3E%20JSON.stringify(obj)%2C%0A%20%20%20%20indexOf%3A%20(val%2C%20char)%20%3D%3E%20String(val).indexOf(char)%2C%0A%20%20%20%20length%3A%20(val)%20%3D%3E%20String(val).length%2C%0A%20%20%20%20trim%3A%20(val)%20%3D%3E%20String(val).trim()%2C%0A%20%20%20%20substr%3A%20(val%2C%20int1%2C%20int2)%20%3D%3E%20String(val).substr(int1%2C%20int2)%2C%0A%20%20%20%20addreduce%3A%20(arr)%20%3D%3E%20arr.reduce((i%2C%20v)%20%3D%3E%20i%20%2B%20v)%2C%0A%20%20%20%20lengtharray%3A%20(arr)%20%3D%3E%20arr.length%2C%0A%20%20%20%20typeof%3A%20(val)%20%3D%3E%20typeof%20val%2C%0A%20%20%20%20isarray%3A%20(arr)%20%3D%3E%20Array.isArray(arr)%2C%0A%20%20%20%20isnan%3A%20(val)%20%3D%3E%20isNaN(val)%2C%0A%20%20%20%20parseint%3A%20(val)%20%3D%3E%20parseInt(val)%2C%0A%20%20%20%20parsefloat%3A%20(val)%20%3D%3E%20parseFloat(val)%2C%0A%20%20%20%20toisodate%3A%20(val)%20%3D%3E%20new%20Date(val).toISOString()%2C%0A%20%20%20%20timeoffset%3A%20(isostr)%20%3D%3E%20new%20Date(isostr).getTimezoneOffset()%2C%0A%20%20%20%20tostring%3A%20(val)%20%3D%3E%20val.toString()%2C%0A%20%20%20%20urlencode%3A%20(val)%20%3D%3E%20encodeURI(val)%2C%0A%20%20%20%20urldecode%3A%20(val)%20%3D%3E%20decodeURI(val)%2C%0A%20%20%20%20replacestr%3A%20(str%2C%20from%2C%20to)%20%3D%3E%20str.replace(from%2C%20to)%2C%0A%20%20%20%20replaceregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20str.replace(new%20RegExp(reg)%2C%20to)%2C%0A%20%20%20%20replaceallstr%3A%20(str%2C%20from%2C%20to)%20%3D%3E%20str.replaceAll(from%2C%20to)%2C%0A%20%20%20%20replaceallregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20str.replaceAll(new%20RegExp(reg%2C%20'g')%2C%20to)%2C%0A%20%20%20%20split%3A%20(str%2C%20ch)%20%3D%3E%20str.split(ch)%2C%0A%20%20%20%20mapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%20choices%5Bvalues.findIndex((target)%20%3D%3E%20target%20%3D%3D%3D%20val)%5D%2C%0A%20%20%20%20thmapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%0A%20%20%20%20%20%20%20%20choices%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20values.reduce((acc%2C%20curr%2C%20i)%20%3D%3E%20(acc%20%3D%3D%3D%200%20%7C%7C%20acc%20%3F%20acc%20%3A%20val%20%3C%3D%20curr%20%3F%20(acc%20%3D%20i)%20%3A%20(acc%20%3D%20null))%2C%20null)%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20bitwisemask%3A%20(i%2C%20mask%2C%20op%2C%20shf)%20%3D%3E%0A%20%20%20%20%20%20%20%20(op%20%3D%3D%3D%20'%26'%20%3F%20parseInt(i)%20%26%20mask%20%3A%20op%20%3D%3D%3D%20'%7C'%20%3F%20parseInt(i)%20%7C%20mask%20%3A%20op%20%3D%3D%3D%20'%5E'%20%3F%20parseInt(i)%20%5E%20mask%20%3A%20i)%20%3E%3E%0A%20%20%20%20%20%20%20%20shf%2C%0A%20%20%20%20slice%3A%20(arr%2C%20init%2C%20end)%20%3D%3E%20arr.slice(init%2C%20end)%0A%7D
2465
2465
  [99]:
2466
- https://czosel.github.io/jexl-playground/#/?context=%7B%0A%20%20%22text%22%20%3A%20%22%20%20foobar%7B%7D%20%20%22%0A%7D&input=text%20%7C%20replacestr(%22foo%22%2C%22FOO%22)%7Ctrim%7Curlencode&transforms=%7B%0A%20%20%20%20jsonparse%3A%20(str)%20%3D%3E%20JSON.parse(str)%2C%0A%20%20%20%20jsonstringify%3A%20(obj)%20%3D%3E%20JSON.stringify(obj)%2C%0A%20%20%20%20indexOf%3A%20(val%2C%20char)%20%3D%3E%20String(val).indexOf(char)%2C%0A%20%20%20%20length%3A%20(val)%20%3D%3E%20String(val).length%2C%0A%20%20%20%20trim%3A%20(val)%20%3D%3E%20String(val).trim()%2C%0A%20%20%20%20substr%3A%20(val%2C%20int1%2C%20int2)%20%3D%3E%20String(val).substr(int1%2C%20int2)%2C%0A%20%20%20%20addreduce%3A%20(arr)%20%3D%3E%20arr.reduce((i%2C%20v)%20%3D%3E%20i%20%2B%20v)%2C%0A%20%20%20%20lengtharray%3A%20(arr)%20%3D%3E%20arr.length%2C%0A%20%20%20%20typeof%3A%20(val)%20%3D%3E%20typeof%20val%2C%0A%20%20%20%20isarray%3A%20(arr)%20%3D%3E%20Array.isArray(arr)%2C%0A%20%20%20%20isnan%3A%20(val)%20%3D%3E%20isNaN(val)%2C%0A%20%20%20%20parseint%3A%20(val)%20%3D%3E%20parseInt(val)%2C%0A%20%20%20%20parsefloat%3A%20(val)%20%3D%3E%20parseFloat(val)%2C%0A%20%20%20%20toisodate%3A%20(val)%20%3D%3E%20new%20Date(val).toISOString()%2C%0A%20%20%20%20timeoffset%3A%20(isostr)%20%3D%3E%20new%20Date(isostr).getTimezoneOffset()%2C%0A%20%20%20%20tostring%3A%20(val)%20%3D%3E%20val.toString()%2C%0A%20%20%20%20urlencode%3A%20(val)%20%3D%3E%20encodeURI(val)%2C%0A%20%20%20%20urldecode%3A%20(val)%20%3D%3E%20decodeURI(val)%2C%0A%20%20%20%20replacestr%3A%20(str%2C%20from%2C%20to)%20%3D%3E%20str.replace(from%2C%20to)%2C%0A%20%20%20%20replaceregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20str.replace(new%20RegExp(reg)%2C%20to)%2C%0A%20%20%20%20replaceallstr%3A%20(str%2C%20from%2C%20to)%20%3D%3E%20str.replaceAll(from%2C%20to)%2C%0A%20%20%20%20replaceallregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20str.replaceAll(new%20RegExp(reg%2C%20'g')%2C%20to)%2C%0A%20%20%20%20split%3A%20(str%2C%20ch)%20%3D%3E%20str.split(ch)%2C%0A%20%20%20%20joinarrtostr%3A%20(arr%2C%20ch)%20%3D%3E%20arr.join(ch)%2C%0A%20%20%20%20concatarr%3A%20(arr%2C%20arr2)%20%3D%3E%20arr.concat(arr2)%2C%0A%20%20%20%20mapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%20choices%5Bvalues.findIndex((target)%20%3D%3E%20target%20%3D%3D%3D%20val)%5D%2C%0A%20%20%20%20thmapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%0A%20%20%20%20%20%20%20%20choices%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20values.reduce((acc%2C%20curr%2C%20i)%20%3D%3E%20(acc%20%3D%3D%3D%200%20%7C%7C%20acc%20%3F%20acc%20%3A%20val%20%3C%3D%20curr%20%3F%20(acc%20%3D%20i)%20%3A%20(acc%20%3D%20null))%2C%20null)%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20bitwisemask%3A%20(i%2C%20mask%2C%20op%2C%20shf)%20%3D%3E%0A%20%20%20%20%20%20%20%20(op%20%3D%3D%3D%20'%26'%20%3F%20parseInt(i)%20%26%20mask%20%3A%20op%20%3D%3D%3D%20'%7C'%20%3F%20parseInt(i)%20%7C%20mask%20%3A%20op%20%3D%3D%3D%20'%5E'%20%3F%20parseInt(i)%20%5E%20mask%20%3A%20i)%20%3E%3E%0A%20%20%20%20%20%20%20%20shf%2C%0A%20%20%20%20slice%3A%20(arr%2C%20init%2C%20end)%20%3D%3E%20arr.slice(init%2C%20end)%2C%0A%20%20%20%20addset%3A%20(arr%2C%20x)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20return%20Array.from(new%20Set(arr).add(x))%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20removeset%3A%20(arr%2C%20x)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20let%20s%20%3D%20new%20Set(arr)%3B%0A%20%20%20%20%20%20%20%20s.delete(x)%3B%0A%20%20%20%20%20%20%20%20return%20Array.from(s)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20touppercase%3A%20(val)%20%3D%3E%20String(val).toUpperCase()%2C%0A%20%20%20%20tolowercase%3A%20(val)%20%3D%3E%20String(val).toLowerCase()%2C%0A%20%20%20%20floor%3A%20(val)%20%3D%3E%20Math.floor(val)%2C%0A%20%20%20%20ceil%3A%20(val)%20%3D%3E%20Math.ceil(val)%2C%0A%20%20%20%20round%3A%20(val)%20%3D%3E%20Math.round(val)%2C%0A%20%20%20%20tofixed%3A%20(val%2C%20decimals)%20%3D%3E%20Number.parseFloat(val).toFixed(decimals)%2C%0A%20%20%20%20gettime%3A%20(d)%20%3D%3E%20new%20Date(d).getTime()%2C%0A%20%20%20%20toisostring%3A%20(d)%20%3D%3E%20new%20Date(d).toISOString()%2C%0A%20%20%20%20%2F%2F%20https%3A%2F%2Fdeveloper.mozilla.org%2Fes%2Fdocs%2FWeb%2FJavaScript%2FReference%2FGlobal_Objects%2FDate%2FtoLocaleString%0A%20%20%20%20localestring%3A%20(d%2C%20timezone%2C%20options)%20%3D%3E%20new%20Date(d).toLocaleString(timezone%2C%20options)%2C%0A%20%20%20%20now%3A%20()%20%3D%3E%20Date.now()%2C%0A%20%20%20%20hextostring%3A%20(val)%20%3D%3E%0A%20%20%20%20%20%20%20%20new%20TextDecoder().decode(new%20Uint8Array(val.match(%2F.%7B1%2C2%7D%2Fg).map((byte)%20%3D%3E%20parseInt(byte%2C%2016))))%2C%0A%20%20%20%20valuePicker%3A%20(val%2Cpick)%20%3D%3E%20Object.entries(val).filter((%5B%2C%20v%5D)%20%3D%3E%20v%20%3D%3D%3D%20pick).map((%5Bk%2C%5D)%20%3D%3E%20k)%2C%0A%20%20%20%20valuePickerMulti%3A%20(val%2Cpick)%20%3D%3E%20Object.entries(val).filter((%5B%2C%20v%5D)%20%3D%3E%20pick.includes(v)).map((%5Bk%2C%5D)%20%3D%3E%20k)%0A%7D
2466
+ https://czosel.github.io/jexl-playground/#/?context=%7B%0A%20%20%22text%22%20%3A%20%22%20%20foobar%7B%7D%20%20%22%0A%7D&input=text%20%7C%20replacestr(%22foo%22%2C%22FOO%22)%7Ctrim%7Curlencode&transforms=%20%7B%0A%20%20%20%20jsonparse%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation(JSON.parse)(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20jsonstringify%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation(JSON.stringify)(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20indexOf%3A%20(val%2C%20char)%20%3D%3E%20String(val).indexOf(char)%2C%0A%20%20%20%20length%3A%20(val)%20%3D%3E%20String(val).length%2C%0A%20%20%20%20trim%3A%20(val)%20%3D%3E%20String(val).trim()%2C%0A%20%20%20%20substr%3A%20(val%2C%20int1%2C%20int2)%20%3D%3E%20String(val).substr(int1%2C%20int2)%2C%0A%20%20%20%20addreduce%3A%20(arr)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((arr)%20%3D%3E%20arr.reduce((i%2C%20v)%20%3D%3E%20i%20%2B%20v))(arr)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20lengtharray%3A%20(arr)%20%3D%3E%20arr.length%2C%0A%20%20%20%20typeof%3A%20(val)%20%3D%3E%20typeof%20val%2C%0A%20%20%20%20isarray%3A%20Array.isArray%2C%0A%20%20%20%20isnan%3A%20isNaN%2C%0A%20%20%20%20parseint%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeParseNumber%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20result%20%3D%20fn(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(result)%20%3F%20null%20%3A%20result%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeParseNumber((val)%20%3D%3E%20parseInt(val%2C%2010))(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20parsefloat%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeParseNumber%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20result%20%3D%20fn(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(result)%20%3F%20null%20%3A%20result%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeParseNumber(parseFloat)(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20toisodate%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeDateOperation%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20date%20%3D%20new%20Date(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(date.getTime())%20%3F%20null%20%3A%20fn(date)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeDateOperation((date)%20%3D%3E%20date.toISOString())(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20timeoffset%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeDateOperation%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20date%20%3D%20new%20Date(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(date.getTime())%20%3F%20null%20%3A%20fn(date)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeDateOperation((date)%20%3D%3E%20date.getTimezoneOffset())(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20tostring%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((val)%20%3D%3E%20val.toString())(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20urlencode%3A%20encodeURI%2C%0A%20%20%20%20urldecode%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation(decodeURI)(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20replacestr%3A%20(str%2C%20from%2C%20to)%20%3D%3E%20str.replace(from%2C%20to)%2C%0A%20%20%20%20replaceregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((str%2C%20reg%2C%20to)%20%3D%3E%20str.replace(new%20RegExp(reg)%2C%20to))(str%2C%20reg%2C%20to)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20replaceallregexp%3A%20(str%2C%20reg%2C%20to)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((str%2C%20reg%2C%20to)%20%3D%3E%20str.replace(new%20RegExp(reg%2C%20'g')%2C%20to))(str%2C%20reg%2C%20to)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20split%3A%20(str%2C%20ch)%20%3D%3E%20str.split(ch)%2C%0A%20%20%20%20joinarrtostr%3A%20(arr%2C%20ch)%20%3D%3E%20arr.join(ch)%2C%0A%20%20%20%20concatarr%3A%20(arr%2C%20arr2)%20%3D%3E%20arr.concat(arr2)%2C%0A%20%20%20%20mapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%20choices%5Bvalues.findIndex((target)%20%3D%3E%20target%20%3D%3D%3D%20val)%5D%2C%0A%20%20%20%20thmapper%3A%20(val%2C%20values%2C%20choices)%20%3D%3E%0A%20%20%20%20%20%20%20%20choices%5Bvalues.reduce((acc%2C%20curr%2C%20i)%20%3D%3E%20(acc%20!%3D%3D%20null%20%3F%20acc%20%3A%20val%20%3C%3D%20curr%20%3F%20i%20%3A%20null)%2C%20null)%5D%2C%0A%20%20%20%20bitwisemask%3A%20(i%2C%20mask%2C%20op%2C%20shf)%20%3D%3E%0A%20%20%20%20%20%20%20%20(op%20%3D%3D%3D%20'%26'%20%3F%20parseInt(i)%20%26%20mask%20%3A%20op%20%3D%3D%3D%20'%7C'%20%3F%20parseInt(i)%20%7C%20mask%20%3A%20op%20%3D%3D%3D%20'%5E'%20%3F%20parseInt(i)%20%5E%20mask%20%3A%20i)%20%3E%3E%0A%20%20%20%20%20%20%20%20shf%2C%0A%20%20%20%20slice%3A%20(arr%2C%20init%2C%20end)%20%3D%3E%20arr.slice(init%2C%20end)%2C%0A%20%20%20%20addset%3A%20(arr%2C%20x)%20%3D%3E%20Array.from(new%20Set(arr).add(x))%2C%0A%20%20%20%20removeset%3A%20(arr%2C%20x)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20s%20%3D%20new%20Set(arr)%3B%0A%20%20%20%20%20%20%20%20s.delete(x)%3B%0A%20%20%20%20%20%20%20%20return%20Array.from(s)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20touppercase%3A%20(val)%20%3D%3E%20String(val).toUpperCase()%2C%0A%20%20%20%20tolowercase%3A%20(val)%20%3D%3E%20String(val).toLowerCase()%2C%0A%20%20%20%20floor%3A%20Math.floor%2C%0A%20%20%20%20ceil%3A%20Math.ceil%2C%0A%20%20%20%20round%3A%20Math.round%2C%0A%20%20%20%20tofixed%3A%20(val%2C%20decimals)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20num%20%3D%20Number.parseFloat(val)%3B%0A%20%20%20%20%20%20%20%20const%20dec%20%3D%20Number.parseInt(decimals)%3B%0A%20%20%20%20%20%20%20%20return%20isNaN(num)%20%7C%7C%20isNaN(dec)%20%3F%20null%20%3A%20num.toFixed(dec)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20gettime%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeDateOperation%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20date%20%3D%20new%20Date(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(date.getTime())%20%3F%20null%20%3A%20fn(date)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeDateOperation((date)%20%3D%3E%20date.getTime())(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20toisostring%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeDateOperation%20%3D%20(fn)%20%3D%3E%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20date%20%3D%20new%20Date(val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20isNaN(date.getTime())%20%3F%20null%20%3A%20fn(date)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeDateOperation((date)%20%3D%3E%20date.toISOString())(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20localestring%3A%20(d%2C%20timezone%2C%20options)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((d%2C%20timezone%2C%20options)%20%3D%3E%20new%20Date(d).toLocaleString(timezone%2C%20options))(d%2C%20timezone%2C%20options)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20now%3A%20Date.now%2C%0A%20%20%20%20hextostring%3A%20(val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%20(fn)%20%3D%3E%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((val)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20val%20!%3D%3D%20'string'%20%7C%7C%20!%2F%5E%5B0-9a-fA-F%5D%2B%24%2F.test(val)%20%7C%7C%20val.length%20%25%202%20!%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20TextDecoder().decode(new%20Uint8Array(val.match(%2F.%7B1%2C2%7D%2Fg).map((byte)%20%3D%3E%20parseInt(byte%2C%2016))))%3B%0A%20%20%20%20%20%20%20%20%7D)(val)%3B%0A%20%20%20%20%7D%2C%0A%20%20%20%20valuePicker%3A%20(val%2C%20pick)%20%3D%3E%0A%20%20%20%20%20%20%20%20Object.entries(val)%0A%20%20%20%20%20%20%20%20%20%20%20%20.filter((%5B%2C%20v%5D)%20%3D%3E%20v%20%3D%3D%3D%20pick)%0A%20%20%20%20%20%20%20%20%20%20%20%20.map((%5Bk%5D)%20%3D%3E%20k)%2C%0A%20%20%20%20valuePickerMulti%3A%20(val%2C%20pick)%20%3D%3E%0A%20%20%20%20%20%20%20%20Object.entries(val)%0A%20%20%20%20%20%20%20%20%20%20%20%20.filter((%5B%2C%20v%5D)%20%3D%3E%20pick.includes(v))%0A%20%20%20%20%20%20%20%20%20%20%20%20.map((%5Bk%5D)%20%3D%3E%20k)%0A%7D
@@ -157,6 +157,7 @@ function processEnvironmentVariables() {
157
157
  'IOTA_FALLBACK_PATH',
158
158
  'IOTA_LD_SUPPORT_NULL',
159
159
  'IOTA_LD_SUPPORT_DATASET_ID',
160
+ 'IOTA_LD_SUPPORT_DATA_TYPE',
160
161
  'IOTA_EXPRESS_LIMIT',
161
162
  'IOTA_USE_CB_FLOW_CONTROL',
162
163
  'IOTA_STORE_LAST_MEASURE'
@@ -264,7 +265,12 @@ function processEnvironmentVariables() {
264
265
  config.server.port = process.env.IOTA_NORTH_PORT;
265
266
  }
266
267
 
267
- config.server.ldSupport = config.server.ldSupport || { null: true, datasetId: true, merge: false };
268
+ config.server.ldSupport = config.server.ldSupport || {
269
+ null: true,
270
+ datasetId: true,
271
+ merge: false,
272
+ dataType: 'none'
273
+ };
268
274
 
269
275
  if (process.env.IOTA_LD_SUPPORT_NULL) {
270
276
  config.server.ldSupport.null = process.env.IOTA_LD_SUPPORT_NULL === 'true';
@@ -275,6 +281,9 @@ function processEnvironmentVariables() {
275
281
  if (process.env.IOTA_LD_SUPPORT_MERGE) {
276
282
  config.server.ldSupport.datasetId = process.env.IOTA_LD_SUPPORT_MERGE === 'true';
277
283
  }
284
+ if (process.env.IOTA_LD_SUPPORT_DATA_TYPE) {
285
+ config.server.ldSupport.dataType = process.env.IOTA_LD_SUPPORT_DATA_TYPE;
286
+ }
278
287
 
279
288
  if (process.env.IOTA_PROVIDER_URL) {
280
289
  config.providerUrl = process.env.IOTA_PROVIDER_URL;
@@ -511,7 +520,7 @@ function getConfig() {
511
520
  function getConfigForTypeInformation() {
512
521
  // Just return relevant configuration flags
513
522
  // avoid to include server, authentication, mongodb, orion and iotamanger info
514
- let conf = {
523
+ const conf = {
515
524
  timestamp: config.timestamp,
516
525
  defaultResource: config.defaultResource,
517
526
  explicitAttrs: config.explicitAttrs,
@@ -68,7 +68,7 @@ function requestDomain(req, res, next) {
68
68
  reqDomain.path = req.path;
69
69
  reqDomain.op = req.url;
70
70
  reqDomain.start = Date.now();
71
-
71
+ reqDomain.from = req.ip || req.connection.remoteAddress;
72
72
  reqDomain.add(req);
73
73
  reqDomain.add(res);
74
74
 
@@ -145,14 +145,15 @@ function ensureSouthboundTransaction(context, callback) {
145
145
  if (context.op) {
146
146
  reqDomain.op = context.op;
147
147
  }
148
-
149
148
  if (context.srv) {
150
149
  reqDomain.service = context.srv;
151
150
  }
152
-
153
151
  if (context.subsrv) {
154
152
  reqDomain.subservice = context.subsrv;
155
153
  }
154
+ if (context.from) {
155
+ reqDomain.from = context.from;
156
+ }
156
157
  }
157
158
 
158
159
  return reqDomain.run(callback);
@@ -33,7 +33,6 @@ const logger = require('logops');
33
33
  const config = require('../../commonConfig');
34
34
  const ngsiLD = require('../ngsi/entities-NGSI-LD');
35
35
  const utils = require('../northBound/restUtils');
36
- const moment = require('moment');
37
36
  const _ = require('underscore');
38
37
  const registrationUtils = require('./registrationUtils');
39
38
  const NGSIv2 = require('./devices-NGSI-v2');
@@ -153,7 +152,7 @@ function updateEntityNgsiLD(deviceData, updatedDevice, callback) {
153
152
  ) {
154
153
  options.json[constants.TIMESTAMP_ATTRIBUTE] = {
155
154
  type: constants.TIMESTAMP_TYPE_NGSI2,
156
- value: moment()
155
+ value: new Date().toISOString()
157
156
  };
158
157
  }
159
158
 
@@ -41,7 +41,6 @@ const registrationUtils = require('./registrationUtils');
41
41
  const _ = require('underscore');
42
42
  const utils = require('../northBound/restUtils');
43
43
  const NGSIv2 = require('../ngsi/entities-NGSI-v2');
44
- const moment = require('moment');
45
44
  const context = {
46
45
  op: 'IoTAgentNGSI.Devices-v2'
47
46
  };
@@ -222,7 +221,7 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) {
222
221
  ) {
223
222
  options.json[constants.TIMESTAMP_ATTRIBUTE] = {
224
223
  type: constants.TIMESTAMP_TYPE_NGSI2,
225
- value: moment()
224
+ value: new Date().toISOString()
226
225
  };
227
226
  }
228
227
 
@@ -59,10 +59,13 @@ function convertAttrNGSILD(attr) {
59
59
  return undefined;
60
60
  }
61
61
  let obj = { type: 'Property', value: attr.value };
62
+ let hasValueType = true;
62
63
 
63
64
  switch (attr.type.toLowerCase()) {
64
65
  // Properties
65
66
  case 'property':
67
+ hasValueType = false;
68
+ break;
66
69
  case 'string':
67
70
  case 'text':
68
71
  case 'textunrestricted':
@@ -96,24 +99,26 @@ function convertAttrNGSILD(attr) {
96
99
  }
97
100
  break;
98
101
 
102
+ case 'object':
103
+ case 'array':
104
+ try {
105
+ obj.value = JSON.parse(attr.value);
106
+ } catch (e) {
107
+ // Do nothing
108
+ }
109
+ break;
110
+
99
111
  // Temporal Properties
100
112
  case 'datetime':
101
- obj.value = {
102
- '@type': 'DateTime',
103
- '@value': moment.tz(attr.value, 'Etc/UTC').toISOString()
104
- };
113
+ obj.value = moment.tz(attr.value, 'Etc/UTC').toISOString();
105
114
  break;
106
115
  case 'date':
107
- obj.value = {
108
- '@type': 'Date',
109
- '@value': moment.tz(attr.value, 'Etc/UTC').format(moment.HTML5_FMT.DATE)
110
- };
116
+ obj.value = moment.tz(attr.value, 'Etc/UTC').format(moment.HTML5_FMT.DATE);
111
117
  break;
112
118
  case 'time':
113
- obj.value = {
114
- '@type': 'Time',
115
- '@value': moment.tz(attr.value, 'Etc/UTC').format(moment.HTML5_FMT.TIME_SECONDS)
116
- };
119
+ obj.value = moment
120
+ .tz(new Date('0000-01-01 ' + attr.value), 'Etc/UTC')
121
+ .format(moment.HTML5_FMT.TIME_SECONDS);
117
122
  break;
118
123
 
119
124
  // GeoProperties
@@ -121,37 +126,44 @@ function convertAttrNGSILD(attr) {
121
126
  case 'point':
122
127
  case 'geo:point':
123
128
  case 'geo:json':
129
+ hasValueType = false;
124
130
  obj.type = 'GeoProperty';
125
131
  obj.value = NGSIUtils.getLngLats('Point', attr.value);
126
132
  break;
127
133
  case 'linestring':
128
134
  case 'geo:linestring':
135
+ hasValueType = false;
129
136
  obj.type = 'GeoProperty';
130
137
  obj.value = NGSIUtils.getLngLats('LineString', attr.value);
131
138
  break;
132
139
  case 'polygon':
133
140
  case 'geo:polygon':
141
+ hasValueType = false;
134
142
  obj.type = 'GeoProperty';
135
143
  obj.value = NGSIUtils.getLngLats('Polygon', attr.value);
136
144
  break;
137
145
  case 'multipoint':
138
146
  case 'geo:multipoint':
147
+ hasValueType = false;
139
148
  obj.type = 'GeoProperty';
140
149
  obj.value = NGSIUtils.getLngLats('MultiPoint', attr.value);
141
150
  break;
142
151
  case 'multilinestring':
143
152
  case 'geo:multilinestring':
153
+ hasValueType = false;
144
154
  obj.type = 'GeoProperty';
145
155
  obj.value = NGSIUtils.getLngLats('MultiLineString', attr.value);
146
156
  break;
147
157
  case 'multipolygon':
148
158
  case 'geo:multipolygon':
159
+ hasValueType = false;
149
160
  obj.type = 'GeoProperty';
150
161
  obj.value = NGSIUtils.getLngLats('MultiPolygon', attr.value);
151
162
  break;
152
163
 
153
164
  // Relationships
154
165
  case 'relationship':
166
+ hasValueType = false;
155
167
  obj.type = 'Relationship';
156
168
  obj.object = attr.value;
157
169
  delete obj.value;
@@ -159,13 +171,57 @@ function convertAttrNGSILD(attr) {
159
171
 
160
172
  // LanguageProperties
161
173
  case 'languageproperty':
174
+ hasValueType = false;
162
175
  obj.type = 'LanguageProperty';
163
176
  obj.languageMap = attr.value;
164
177
  delete obj.value;
165
178
  break;
166
179
 
180
+ // VocabProperties
181
+ case 'vocabproperty':
182
+ hasValueType = false;
183
+ obj.type = 'VocabProperty';
184
+ obj.vocab = attr.value;
185
+ delete obj.value;
186
+ break;
187
+ // JsonProperties
188
+ case 'jsonproperty':
189
+ hasValueType = false;
190
+ obj.type = 'JsonProperty';
191
+ obj.json = attr.value;
192
+ delete obj.value;
193
+ break;
194
+ // ListProperties
195
+ case 'listproperty':
196
+ hasValueType = false;
197
+ obj.type = 'ListProperty';
198
+ obj.listValue = attr.value;
199
+ delete obj.value;
200
+ break;
201
+ // ListRelationship
202
+ case 'listrelationship':
203
+ hasValueType = false;
204
+ obj.type = 'ListRelationship';
205
+ obj.listObject = attr.value;
206
+ delete obj.value;
207
+ break;
208
+
167
209
  default:
168
- obj.value = { '@type': attr.type, '@value': attr.value };
210
+ obj.value = attr.value;
211
+ }
212
+
213
+ if (hasValueType) {
214
+ switch (config.getConfig().server.ldSupport.dataType) {
215
+ case '@type':
216
+ obj.value = {
217
+ '@type': attr.type,
218
+ '@value': obj.value
219
+ };
220
+ break;
221
+ case 'valueType':
222
+ obj.valueType = attr.type;
223
+ break;
224
+ }
169
225
  }
170
226
 
171
227
  if (!!obj && attr.metadata) {
@@ -95,7 +95,9 @@ function sendUpdateValue(entityName, attributes, typeInformation, token, callbac
95
95
  // check config about store last measure
96
96
  if (typeInformation.storeLastMeasure) {
97
97
  logger.debug(context, 'StoreLastMeasure for %j', typeInformation);
98
- deviceService.storeDeviceField('lastMeasure', attributes, typeInformation, function () {
98
+ let originalMeasure = typeInformation.originalMeasure ? typeInformation.originalMeasure : null;
99
+ deviceService.storeDeviceField('lastMeasure', originalMeasure, typeInformation, function () {
100
+ delete typeInformation.originalMeasure;
99
101
  return entityHandler.sendUpdateValue(entityName, attributes, typeInformation, token, wrappedNewCallback);
100
102
  });
101
103
  } else {
@@ -46,7 +46,7 @@ const config = require('../../commonConfig');
46
46
 
47
47
  const overwritePaths = ['/ngsi-ld/v1/entities/:entity/attrs', '/ngsi-ld/v1/entities/:entity/attrs/:attr'];
48
48
  const updatePaths = ['/ngsi-ld/v1/entities/:entity/attrs', '/ngsi-ld/v1/entities/:entity/attrs/:attr'];
49
- const queryPaths = ['/ngsi-ld/v1/entities/:entity'];
49
+ const queryPaths = ['/ngsi-ld/v1/entities/:entity', '/ngsi-ld/v1/entities'];
50
50
 
51
51
  /**
52
52
  * Replacement of NGSI-LD Null placeholders with real null values
@@ -506,6 +506,9 @@ function handleMergePatchNgsiLD(req, res, next) {
506
506
  * @param {Object} res Response that will be sent.
507
507
  */
508
508
  function handleQueryNgsiLD(req, res, next) {
509
+ const returnAsArray = req.query.id;
510
+ req.params.entity = req.params.entity || req.query.id || '';
511
+
509
512
  function getName(element) {
510
513
  return element.name;
511
514
  }
@@ -641,7 +644,7 @@ function handleQueryNgsiLD(req, res, next) {
641
644
  next(error);
642
645
  } else {
643
646
  logger.debug(context, 'Query from [%s] handled successfully.', req.get('host'));
644
- res.status(200).json(result);
647
+ res.status(200).json(returnAsArray ? [result] : result);
645
648
  }
646
649
  }
647
650
 
@@ -793,7 +796,6 @@ function loadUnsupportedEndpointsNGSILD(router) {
793
796
  const unsupportedEndpoint = function (req, res) {
794
797
  return res.status(501).send(new errors.MethodNotSupported(req.method, req.path));
795
798
  };
796
- router.get('/ngsi-ld/v1/entities', unsupportedEndpoint);
797
799
  router.post('/ngsi-ld/v1/entities', unsupportedEndpoint);
798
800
  router.delete('/ngsi-ld/v1/entities/:entity', unsupportedEndpoint);
799
801
  router.delete('/ngsi-ld/v1/entities/:entity/attrs/:attr', unsupportedEndpoint);
@@ -59,7 +59,7 @@ function start(config, callback) {
59
59
  northboundServer.app.use(domainUtils.requestDomain);
60
60
  northboundServer.app.use(bodyParser.json({ limit: config.expressLimit }));
61
61
  northboundServer.app.use(bodyParser.json({ type: 'application/*+json', limit: config.expressLimit }));
62
-
62
+ northboundServer.app.set('trust proxy', true); // populate req.ip
63
63
  if (config.logLevel && config.logLevel === 'DEBUG') {
64
64
  northboundServer.app.use(middlewares.traceRequest);
65
65
  }
@@ -30,7 +30,6 @@ const errors = require('../../errors');
30
30
  const constants = require('../../constants');
31
31
  const intoTrans = require('../common/domain').intoTrans;
32
32
  const revalidator = require('revalidator');
33
- const moment = require('moment');
34
33
  const context = {
35
34
  op: 'IoTAgentNGSI.RestUtils'
36
35
  };
@@ -121,6 +120,11 @@ function checkBody(template) {
121
120
  };
122
121
  }
123
122
 
123
+ function isISOString(val) {
124
+ const d = new Date(val);
125
+ return !Number.isNaN(d.valueOf()) && d.toISOString() === val;
126
+ }
127
+
124
128
  /**
125
129
  * Checks if the timestamp properties of NGSIv2 entities are valid ISO8601 dates.
126
130
  *
@@ -131,7 +135,7 @@ function IsValidTimestampedNgsi2(payload) {
131
135
  function isValidTimestampedNgsi2Entity(entity) {
132
136
  for (const i in entity) {
133
137
  if (entity.hasOwnProperty(i)) {
134
- if (i === constants.TIMESTAMP_ATTRIBUTE && !moment(entity[i].value, moment.ISO_8601).isValid()) {
138
+ if (i === constants.TIMESTAMP_ATTRIBUTE && !isISOString(entity[i].value)) {
135
139
  return false;
136
140
  }
137
141
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "iotagent-node-lib",
3
3
  "license": "AGPL-3.0-only",
4
4
  "description": "IoT Agent library to interface with NGSI Context Broker",
5
- "version": "4.8.0",
5
+ "version": "4.9.0",
6
6
  "homepage": "https://github.com/telefonicaid/iotagent-node-lib",
7
7
  "keywords": [
8
8
  "fiware",
@@ -45,7 +45,7 @@ config.amqp = {
45
45
  };
46
46
 
47
47
  config.iota = {
48
- logLevel: 'DEBUG',
48
+ logLevel: 'FATAL',
49
49
  contextBroker: {
50
50
  host: '192.168.1.1',
51
51
  port: '1026',
@@ -4,10 +4,7 @@
4
4
  "id": "urn:ngsi-ld:MicroLights:FirstMicroLight",
5
5
  "timestamp": {
6
6
  "type": "Property",
7
- "value": {
8
- "@type": "DateTime",
9
- "@value": "1970-01-01T00:00:00.000Z"
10
- }
7
+ "value": "1970-01-01T00:00:00.000Z"
11
8
  },
12
9
  "type": "MicroLights"
13
10
  }
@@ -3,24 +3,15 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "commandAttr_info": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "commandResult",
8
- "@value": " "
9
- }
6
+ "value": " "
10
7
  },
11
8
  "commandAttr_status": {
12
9
  "type": "Property",
13
- "value": {
14
- "@type": "commandStatus",
15
- "@value": "UNKNOWN"
16
- }
10
+ "value": "UNKNOWN"
17
11
  },
18
12
  "hardcodedAttr": {
19
13
  "type": "Property",
20
- "value": {
21
- "@type": "hardcodedType",
22
- "@value": "hardcodedValue"
23
- }
14
+ "value": "hardcodedValue"
24
15
  },
25
16
  "id": "urn:ngsi-ld:TheLightType:TheFirstLight",
26
17
  "type": "TheLightType"
@@ -3,24 +3,15 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "commandAttr_info": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "commandResult",
8
- "@value": " "
9
- }
6
+ "value": " "
10
7
  },
11
8
  "commandAttr_status": {
12
9
  "type": "Property",
13
- "value": {
14
- "@type": "commandStatus",
15
- "@value": "UNKNOWN"
16
- }
10
+ "value": "UNKNOWN"
17
11
  },
18
12
  "hardcodedAttr": {
19
13
  "type": "Property",
20
- "value": {
21
- "@type": "hardcodedType",
22
- "@value": "hardcodedValue"
23
- }
14
+ "value": "hardcodedType"
24
15
  },
25
16
  "id": "urn:ngsi-ld:TheLightType:TheFirstLight",
26
17
  "type": "TheLightType"
@@ -5,45 +5,27 @@
5
5
  "type": "TheLightType",
6
6
  "hardcodedAttr": {
7
7
  "type": "Property",
8
- "value": {
9
- "@type": "hardcodedType",
10
- "@value": "hardcodedValue"
11
- }
8
+ "value": "hardcodedType"
12
9
  },
13
10
  "bootstrapServer": {
14
11
  "type": "Property",
15
- "value": {
16
- "@type": "Address",
17
- "@value": "127.0.0.1"
18
- }
12
+ "value": "127.0.0.1"
19
13
  },
20
14
  "commandAttr_status": {
21
15
  "type": "Property",
22
- "value": {
23
- "@type": "commandStatus",
24
- "@value": "UNKNOWN"
25
- }
16
+ "value": "UNKNOWN"
26
17
  },
27
18
  "commandAttr_info": {
28
19
  "type": "Property",
29
- "value": {
30
- "@type": "commandResult",
31
- "@value": " "
32
- }
20
+ "value": "commandResult",
33
21
  },
34
22
  "wheel1_status": {
35
23
  "type": "Property",
36
- "value": {
37
- "@type": "commandStatus",
38
- "@value": "UNKNOWN"
39
- }
24
+ "value": "commandStatus"
40
25
  },
41
26
  "wheel1_info": {
42
27
  "type": "Property",
43
- "value": {
44
- "@type": "commandResult",
45
- "@value": " "
46
- }
28
+ "value": "commandResult"
47
29
  }
48
30
  }
49
31
  ]
@@ -9,10 +9,7 @@
9
9
  },
10
10
  "bootstrapServer": {
11
11
  "type": "Property",
12
- "value": {
13
- "@type": "Address",
14
- "@value": "127.0.0.1"
15
- }
12
+ "value": "127.0.0.1"
16
13
  }
17
14
  }
18
15
  ]
@@ -3,10 +3,7 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "dimming": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "Percentage",
8
- "@value": "87"
9
- }
6
+ "value": "87"
10
7
  },
11
8
  "id": "urn:ngsi-ld:Light:light1",
12
9
  "state": {
@@ -3,10 +3,7 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "bootstrapServer": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "Address",
8
- "@value": "127.0.0.1"
9
- }
6
+ "value": "127.0.0.1"
10
7
  },
11
8
  "id": "urn:ngsi-ld:SensorMachine:machine1",
12
9
  "status": {
@@ -3,10 +3,7 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "bootstrapServer": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "Address",
8
- "@value": "127.0.0.1"
9
- }
6
+ "value": "Address"
10
7
  },
11
8
  "id": "urn:ngsi-ld:Light:light1",
12
9
  "status": {
@@ -3,10 +3,7 @@
3
3
  "@context": "http://context.json-ld",
4
4
  "bootstrapServer": {
5
5
  "type": "Property",
6
- "value": {
7
- "@type": "Address",
8
- "@value": "127.0.0.1"
9
- }
6
+ "value": "Address"
10
7
  },
11
8
  "id": "urn:ngsi-ld:SensorMachine:Light1",
12
9
  "status": {