iotagent-node-lib 4.9.0 → 4.11.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 (49) hide show
  1. package/.github/workflows/ci.yml +6 -8
  2. package/CHANGES_NEXT_RELEASE +0 -1
  3. package/Changelog +14 -0
  4. package/config.js +2 -1
  5. package/doc/admin.md +17 -20
  6. package/doc/api.md +87 -50
  7. package/doc/deprecated.md +18 -0
  8. package/doc/devel/northboundinteractions.md +213 -113
  9. package/lib/commonConfig.js +12 -1
  10. package/lib/jexlTranformsMap.js +15 -0
  11. package/lib/model/Device.js +3 -1
  12. package/lib/model/Group.js +2 -1
  13. package/lib/model/dbConn.js +57 -58
  14. package/lib/services/common/iotManagerService.js +2 -1
  15. package/lib/services/devices/deviceRegistryMongoDB.js +5 -1
  16. package/lib/services/devices/deviceService.js +17 -1
  17. package/lib/services/devices/devices-NGSI-LD.js +3 -2
  18. package/lib/services/devices/devices-NGSI-mixed.js +16 -0
  19. package/lib/services/devices/devices-NGSI-v2.js +122 -8
  20. package/lib/services/devices/registrationUtils.js +97 -30
  21. package/lib/services/groups/groupRegistryMongoDB.js +2 -1
  22. package/lib/services/ngsi/subscription-NGSI-LD.js +2 -2
  23. package/lib/services/ngsi/subscription-NGSI-mixed.js +3 -3
  24. package/lib/services/ngsi/subscription-NGSI-v2.js +20 -6
  25. package/lib/services/ngsi/subscriptionService.js +2 -2
  26. package/lib/services/northBound/contextServer-NGSI-v2.js +4 -2
  27. package/lib/services/northBound/deviceProvisioningServer.js +6 -3
  28. package/lib/templates/updateDevice.json +12 -0
  29. package/lib/templates/updateDeviceLax.json +4 -0
  30. package/package.json +2 -2
  31. package/test/unit/expressions/jexlExpression-test.js +30 -0
  32. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +2 -2
  33. package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +1 -1
  34. package/test/unit/ngsi-ld/general/contextBrokerOAuthSecurityAccess-test.js +2 -2
  35. package/test/unit/ngsi-ld/general/https-support-test.js +1 -1
  36. package/test/unit/ngsi-ld/ngsiService/subscriptions-test.js +6 -6
  37. package/test/unit/ngsiv2/examples/contextAvailabilityRequests/subscribeIoTAgentCommands.json +24 -0
  38. package/test/unit/ngsiv2/examples/contextAvailabilityRequests/subscribeIoTAgentCommands2.json +24 -0
  39. package/test/unit/ngsiv2/examples/contextAvailabilityRequests/subscribeIoTAgentCommands3.json +24 -0
  40. package/test/unit/ngsiv2/examples/contextAvailabilityRequests/subscribeIoTAgentCommands4.json +24 -0
  41. package/test/unit/ngsiv2/examples/contextRequests/updateEntity.json +5 -0
  42. package/test/unit/ngsiv2/examples/contextRequests/updateEntity2.json +5 -0
  43. package/test/unit/ngsiv2/examples/contextRequests/updateEntity2b.json +7 -0
  44. package/test/unit/ngsiv2/examples/contextRequests/updateEntity3.json +5 -0
  45. package/test/unit/ngsiv2/examples/subscriptionRequests/simpleSubscriptionRequest.json +4 -2
  46. package/test/unit/ngsiv2/examples/subscriptionRequests/simpleSubscriptionRequest2.json +4 -2
  47. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +2 -2
  48. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  49. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +245 -2
@@ -14,10 +14,10 @@ jobs:
14
14
  steps:
15
15
  - name: Git checkout
16
16
  uses: actions/checkout@v2
17
- - name: Use Node.js 16.x
17
+ - name: Use Node.js 24.x
18
18
  uses: actions/setup-node@v1
19
19
  with:
20
- node-version: 16.x
20
+ node-version: 24.x
21
21
  - name: Run Remark Markdown Linter
22
22
  run: |
23
23
  npm install
@@ -31,10 +31,10 @@ jobs:
31
31
  steps:
32
32
  - name: Git checkout
33
33
  uses: actions/checkout@v2
34
- - name: Use Node.js 16.x
34
+ - name: Use Node.js 24.x
35
35
  uses: actions/setup-node@v1
36
36
  with:
37
- node-version: 16.x
37
+ node-version: 24.x
38
38
  - name: Run EsLint Node.js Linter
39
39
  run: |
40
40
  npm install
@@ -51,8 +51,6 @@ jobs:
51
51
  strategy:
52
52
  matrix:
53
53
  node-version:
54
- - 16.x
55
- - 18.x
56
54
  - 20.x
57
55
  - 22.x
58
56
  - 24.x
@@ -80,10 +78,10 @@ jobs:
80
78
  steps:
81
79
  - name: Git checkout
82
80
  uses: actions/checkout@v2
83
- - name: 'Test Coverage with Node.js 16.x'
81
+ - name: 'Test Coverage with Node.js 24.x'
84
82
  uses: actions/setup-node@v1
85
83
  with:
86
- node-version: 16.x
84
+ node-version: 24.x
87
85
  - run: |
88
86
  npm install
89
87
  npm run test:coverage
@@ -1 +0,0 @@
1
-
package/Changelog CHANGED
@@ -1,3 +1,17 @@
1
+ 4.11.0 (Oct 23th, 2025)
2
+
3
+ - Add: IOTA_MONGO_URI env var
4
+ - Add: locale string number jexl function (#1737)
5
+ - Deprecated: IOTA_MONGO_ different from IOTA_MONGO_URI (use IOTA_MONGO_URI instead)
6
+ - Fix: broken notification command mode (it was not working without providing targetEntityId and targetEntityType in the notification, which belongs to another command mode: advancedNotification)
7
+ - Fix: use normalized in attrsFormat for commands subscriptions (#1743)
8
+
9
+ 4.10.0 (Oct 6th, 2025)
10
+
11
+ - Add: command modes (new field cmdMode): legacy, notification and advancedNotification (#1732)
12
+ - Fix: update device with useCBflowControl
13
+ - Set Nodejs 20 as minimum version in packages.json (effectively removing Nodev16 and Nodev18 from supported versions)
14
+
1
15
  4.9.0 (Aug 22nd, 2025)
2
16
 
3
17
  - Add: support NGSI-LD QueryEntities endpoint for lazy attributes (#1722)
package/config.js CHANGED
@@ -79,7 +79,8 @@ var config = {
79
79
  defaultType: 'Thing',
80
80
  expressLimit: '1Mb',
81
81
  useCBflowControl: false,
82
- storeLastMeasure: false
82
+ storeLastMeasure: false,
83
+ cmdMode: 'legacy'
83
84
  };
84
85
 
85
86
  module.exports = config;
package/doc/admin.md CHANGED
@@ -248,15 +248,8 @@ the `mongob` section (as described bellow). E.g.:
248
248
 
249
249
  #### `mongodb`
250
250
 
251
- It configures the MongoDB driver for those repositories with 'mongodb' type. If the `host` parameter is a list of
252
- comma-separated IPs, they will be considered to be part of a Replica Set. In that case, the optional property
253
- `replicaSet` should contain the Replica Set name. If the database requires authentication, username (`user`), password
254
- (`password`) and authSource (`authSource`) can be set. If the database requires TLS/SSL connection but any validation of
255
- the certificate chain is not mandatory, all you need is to set the ssl (`ssl`) option as `true` to connect the database.
256
- If you need to add more complex option(s) such as `retryWrites=true` or `w=majority` when connection database, extraArgs
257
- (`extraArgs`) can be used to perform it. For The MongoBD driver will retry the connection at startup time `retries`
258
- times, waiting `retryTime` seconds between attempts, if those attributes are present (default values are 5 and 5
259
- respectively). E.g.:
251
+ It configures the MongoDB driver for those repositories with 'mongodb' type, using the `uri` parameter (which format is
252
+ available in [this reference](http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html)).
260
253
 
261
254
  ```javascript
262
255
  {
@@ -452,6 +445,19 @@ If this flag is activated, when iotAgent invokes Context Broker will use
452
445
  [flowControl option](https://github.com/telefonicaid/fiware-orion/blob/master/doc/manuals/admin/perf_tuning.md#updates-flow-control-mechanism).
453
446
  This flag is overwritten by `useCBflowControl` flag in group or device. This flag is disabled by default.
454
447
 
448
+ #### `cmdMode`
449
+
450
+ Set command mode for the IoTAgent instance (it can be overriden by the `cmdMode` at group or device level). Possible
451
+ values are:
452
+
453
+ - `legacy` (used as default if this setting is not defined): IoTAgent commands will use Context Broker registers
454
+ mechanims.
455
+ - `notification`: IoTAgent commands will use subscriptions to be notified for Context Broker commands.
456
+ - `advancedNotification`: IoTAgent commands will use subscriptions to be notified for Context Broker commands (but in
457
+ a different way as in `notification` mode)
458
+
459
+ Have a look to [this document](devel/northboundinteractions.md) for more detail on how this modes work.
460
+
455
461
  ### Configuration using environment variables
456
462
 
457
463
  Some of the configuration parameters can be overriden with environment variables, to ease the use of those parameters
@@ -494,17 +500,7 @@ overrides.
494
500
  | IOTA_IOTAM_AGENTPATH | `iotManager.agentPath` |
495
501
  | IOTA_IOTAM_PROTOCOL | `iotManager.protocol` |
496
502
  | IOTA_IOTAM_DESCRIPTION | `iotManager.description` |
497
- | IOTA_MONGO_HOST | `mongodb.host` |
498
- | IOTA_MONGO_PORT | `mongodb.port` |
499
- | IOTA_MONGO_DB | `mongodb.db` |
500
- | IOTA_MONGO_REPLICASET | `mongodb.replicaSet` |
501
- | IOTA_MONGO_USER | `mongodb.user` |
502
- | IOTA_MONGO_PASSWORD | `mongodb.password` |
503
- | IOTA_MONGO_AUTH_SOURCE | `mongodb.authSource` |
504
- | IOTA_MONGO_RETRIES | `mongodb.retries` |
505
- | IOTA_MONGO_RETRY_TIME | `mongodb.retryTime` |
506
- | IOTA_MONGO_SSL | `mongodb.ssl` |
507
- | IOTA_MONGO_EXTRAARGS | `mongodb.extraArgs` |
503
+ | IOTA_MONGO_URI | `mongodb.uri` |
508
504
  | IOTA_POLLING_EXPIRATION | `pollingExpiration` |
509
505
  | IOTA_POLLING_DAEMON_FREQ | `pollingDaemonFrequency` |
510
506
  | IOTA_MULTI_CORE | `multiCore` |
@@ -517,6 +513,7 @@ overrides.
517
513
  | IOTA_EXPRESS_LIMIT | `expressLimit` |
518
514
  | IOTA_STORE_LAST_MEASURE | `storeLastMeasure` |
519
515
  | IOTA_CB_FLOW_CONTROL | `useCBflowControl` |
516
+ | IOTA_CMD_MODE | `cmdMode` |
520
517
 
521
518
  Note:
522
519
 
package/doc/api.md CHANGED
@@ -12,6 +12,7 @@
12
12
  - [Special measures and attributes names](#special-measures-and-attributes-names)
13
13
  - [Device to NGSI Mapping](#device-to-ngsi-mapping)
14
14
  - [Device autoprovision and entity creation](#device-autoprovision-and-entity-creation)
15
+ - [Entity creation when `cmdMode` is `notification`](#entity-creation-when-cmdmode-is-notification)
15
16
  - [Entity Name expression support](#entity-name-expression-support)
16
17
  - [Multientity support](#multientity-support)
17
18
  - [Metadata support](#metadata-support)
@@ -257,9 +258,9 @@ Additionally for commands (which are attributes of type `command`) the following
257
258
  particular IOTAs documentation for allowed values of this field in each case.
258
259
  - **contentType**: `content-type` header used when send command by HTTP transport (ignored in other kinds of
259
260
  transports)
260
- - **headers**: extra customer headers used when send command by HTTP transport (ignored in other kinds of
261
- transports)
262
- Check full detail of these fields in [comand-transformations](https://github.com/telefonicaid/iotagent-json/blob/master/docs/usermanual.md#commands-transformations)
261
+ - **headers**: extra customer headers used when send command by HTTP transport (ignored in other kinds of transports)
262
+ Check full detail of these fields in
263
+ [comand-transformations](https://github.com/telefonicaid/iotagent-json/blob/master/docs/usermanual.md#commands-transformations)
263
264
 
264
265
  Note that, when information coming from devices, this means measures, are not defined neither in the group, nor in the
265
266
  device, the IoT agent will store that information into the destination entity using the same attribute name than the
@@ -276,6 +277,36 @@ If for any reason you need the entity at CB before the first measure of the corr
276
277
  IOTAgent, you can create it in advance using the Context Broker
277
278
  [NGSI v2 API](https://github.com/telefonicaid/fiware-orion/blob/master/doc/manuals/orion-api.md).
278
279
 
280
+ ## Entity creation when `cmdMode` is `notification`
281
+
282
+ Even when an entity should not be created (see [above section](#device-autoprovision-and-entity-creation)), when the
283
+ device uses `cmdMode` set to `notification` an entity is created. In particular:
284
+
285
+ - An entity is created at device provision time
286
+ - That entity is created with an attribute corresponding to each commands. The value of that attribute at creation
287
+ time is `null` (specifying in some way that the command has not been triggered yet). Note that if the attribute
288
+ doesn't have any command, the entity is not created (even if `cmdMode` is `notification`).
289
+
290
+ For instance, if device has commands `ping` and `switch` the entity corresponding to that device will be created at
291
+ provising time with the following attributes:
292
+
293
+ ```
294
+ ...
295
+ {
296
+ "ping": {
297
+ "type": "command",
298
+ "value": null
299
+ },
300
+ "switch": {
301
+ "type": "command",
302
+ "value": null
303
+ },
304
+ }
305
+ ```
306
+
307
+ **NOTE:** `command` is the usual type for attributes associated to commands, but the one used at provisioning time
308
+ (`"command": [ ...]` field) will be actually used.
309
+
279
310
  ## Entity Name expression support
280
311
 
281
312
  By default, the entity name used to persist the device measures in the Context Broker can be defined in the device
@@ -682,52 +713,53 @@ to incorporate new transformations from the IoT Agent configuration file in a fa
682
713
 
683
714
  Current common transformation set:
684
715
 
685
- | JEXL Transformation | Equivalent JavaScript Function |
686
- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
687
- | jsonparse: (str) | `JSON.parse(str);` |
688
- | jsonstringify: (obj) | `JSON.stringify(obj);` |
689
- | indexOf: (val, char) | `String(val).indexOf(char);` |
690
- | length: (val) | `String(val).length;` |
691
- | trim: (val) | `String(val).trim();` |
692
- | substr: (val, int1, int2) | `String(val).substr(int1, int2);` |
693
- | addreduce: (arr) | <code>arr.reduce((i, v) &vert; i + v));</code> |
694
- | lengtharray: (arr) | `arr.length;` |
695
- | typeof: (val) | `typeof val;` |
696
- | isarray: (arr) | `Array.isArray(arr);` |
697
- | isnan: (val) | `isNaN(val);` |
698
- | parseint: (val) | `parseInt(val);` |
699
- | parsefloat: (val) | `parseFloat(val);` |
700
- | toisodate: (val) | `new Date(val).toISOString();` |
701
- | timeoffset:(isostr) | `new Date(isostr).getTimezoneOffset();` |
702
- | tostring: (val) | `val.toString();` |
703
- | urlencode: (val) | `encodeURI(val);` |
704
- | urldecode: (val) | `decodeURI(val);` |
705
- | replacestr: (str, from, to) | `str.replace(from, to);` |
706
- | replaceregexp: (str, reg, to) | `str.replace(new RegExp(reg), to);` |
707
- | replaceallstr: (str, from, to) | `str.replaceAll(from, to);` |
708
- | replaceallregexp: (str, reg, to) | `str.replaceAll(new RegExp(reg,"g"), to);` |
709
- | split: (str, ch) | `str.split(ch);` |
710
- | joinarrtostr: (arr, ch) | `arr.join(ch);` |
711
- | concatarr: (arr, arr2) | `arr.concat(arr2);` |
712
- | mapper: (val, values, choices) | <code>choices[values.findIndex((target) &vert; target == val)]);</code> |
713
- | thmapper: (val, values, choices) | <code>choices[values.reduce((acc,curr,i,arr) &vert; (acc==0)&vert;&vert;acc?acc:val<=curr?acc=i:acc=null,null)];</code> |
714
- | bitwisemask: (i,mask,op,shf) | <code>(op==="&"?parseInt(i)&mask: op==="&vert;"?parseInt(i)&vert;mask: op==="^"?parseInt(i)^mask:i)>>shf;</code> |
715
- | slice: (arr, init, end) | `arr.slice(init,end);` |
716
- | addset: (arr, x) | <code>{ return Array.from((new Set(arr)).add(x)) }</code> |
717
- | removeset: (arr, x) | <code>{ let s = new Set(arr); s.delete(x); return Array.from(s) }</code> |
718
- | touppercase: (val) | `String(val).toUpperCase()` |
719
- | tolowercase: (val) | `String(val).toLowerCase()` |
720
- | round: (val) | `Math.round(val)` |
721
- | floor: (val) | `Math.floor(val)` |
722
- | ceil: (val) | `Math.ceil(val)` |
723
- | tofixed: (val, decimals) | `Number.parseFloat(val).toFixed(decimals)` |
724
- | gettime: (d) | `new Date(d).getTime()` |
725
- | toisostring: (d) | `new Date(d).toISOString()` |
726
- | localestring: (d, timezone, options) | `new Date(d).toLocaleString(timezone, options)` |
727
- | now: () | `Date.now()` |
728
- | hextostring: (val) | `new TextDecoder().decode(new Uint8Array(val.match(/.{1,2}/g).map(byte => parseInt(byte, 16))))` |
729
- | valuePicker: (val,pick) | <code>valuePicker: (val,pick) => Object.entries(val).filter(([_, v]) => v === pick).map(([k, _]) => k)</code> |
730
- | valuePickerMulti: (val,pick) | <code>valuePickerMulti: (val,pick) => Object.entries(val).filter(([_, v]) => pick.includes(v)).map(([k, _]) => k)</code> |
716
+ | JEXL Transformation | Equivalent JavaScript Function |
717
+ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
718
+ | jsonparse: (str) | `JSON.parse(str);` |
719
+ | jsonstringify: (obj) | `JSON.stringify(obj);` |
720
+ | indexOf: (val, char) | `String(val).indexOf(char);` |
721
+ | length: (val) | `String(val).length;` |
722
+ | trim: (val) | `String(val).trim();` |
723
+ | substr: (val, int1, int2) | `String(val).substr(int1, int2);` |
724
+ | addreduce: (arr) | <code>arr.reduce((i, v) &vert; i + v));</code> |
725
+ | lengtharray: (arr) | `arr.length;` |
726
+ | typeof: (val) | `typeof val;` |
727
+ | isarray: (arr) | `Array.isArray(arr);` |
728
+ | isnan: (val) | `isNaN(val);` |
729
+ | parseint: (val) | `parseInt(val);` |
730
+ | parsefloat: (val) | `parseFloat(val);` |
731
+ | toisodate: (val) | `new Date(val).toISOString();` |
732
+ | timeoffset:(isostr) | `new Date(isostr).getTimezoneOffset();` |
733
+ | tostring: (val) | `val.toString();` |
734
+ | urlencode: (val) | `encodeURI(val);` |
735
+ | urldecode: (val) | `decodeURI(val);` |
736
+ | replacestr: (str, from, to) | `str.replace(from, to);` |
737
+ | replaceregexp: (str, reg, to) | `str.replace(new RegExp(reg), to);` |
738
+ | replaceallstr: (str, from, to) | `str.replaceAll(from, to);` |
739
+ | replaceallregexp: (str, reg, to) | `str.replaceAll(new RegExp(reg,"g"), to);` |
740
+ | split: (str, ch) | `str.split(ch);` |
741
+ | joinarrtostr: (arr, ch) | `arr.join(ch);` |
742
+ | concatarr: (arr, arr2) | `arr.concat(arr2);` |
743
+ | mapper: (val, values, choices) | <code>choices[values.findIndex((target) &vert; target == val)]);</code> |
744
+ | thmapper: (val, values, choices) | <code>choices[values.reduce((acc,curr,i,arr) &vert; (acc==0)&vert;&vert;acc?acc:val<=curr?acc=i:acc=null,null)];</code> |
745
+ | bitwisemask: (i,mask,op,shf) | <code>(op==="&"?parseInt(i)&mask: op==="&vert;"?parseInt(i)&vert;mask: op==="^"?parseInt(i)^mask:i)>>shf;</code> |
746
+ | slice: (arr, init, end) | `arr.slice(init,end);` |
747
+ | addset: (arr, x) | <code>{ return Array.from((new Set(arr)).add(x)) }</code> |
748
+ | removeset: (arr, x) | <code>{ let s = new Set(arr); s.delete(x); return Array.from(s) }</code> |
749
+ | touppercase: (val) | `String(val).toUpperCase()` |
750
+ | tolowercase: (val) | `String(val).toLowerCase()` |
751
+ | round: (val) | `Math.round(val)` |
752
+ | floor: (val) | `Math.floor(val)` |
753
+ | ceil: (val) | `Math.ceil(val)` |
754
+ | tofixed: (val, decimals) | `Number.parseFloat(val).toFixed(decimals)` |
755
+ | gettime: (d) | `new Date(d).getTime()` |
756
+ | toisostring: (d) | `new Date(d).toISOString()` |
757
+ | localestring: (d, timezone, options) | `new Date(d).toLocaleString(timezone, options)` |
758
+ | localestringnumber: (n, locale, options) | `n.toLocaleStringNumber(locale, options)` |
759
+ | now: () | `Date.now()` |
760
+ | hextostring: (val) | `new TextDecoder().decode(new Uint8Array(val.match(/.{1,2}/g).map(byte => parseInt(byte, 16))))` |
761
+ | valuePicker: (val,pick) | <code>valuePicker: (val,pick) => Object.entries(val).filter(([_, v]) => v === pick).map(([k, _]) => k)</code> |
762
+ | valuePickerMulti: (val,pick) | <code>valuePickerMulti: (val,pick) => Object.entries(val).filter(([_, v]) => pick.includes(v)).map(([k, _]) => k)</code> |
731
763
 
732
764
  You have available this [JEXL interactive playground][99] with all the transformations already loaded, in which you can
733
765
  test all the functions described above.
@@ -1323,6 +1355,9 @@ as `command` in the [config group](#config-group-datamodel) or in the [device pr
1323
1355
  attributes are created using `command` as attribute type. Also, you can define the protocol you want the commands to be
1324
1356
  sent (HTTP/MQTT) with the `transport` parameter at the provisioning process.
1325
1357
 
1358
+ **NOTE**: in `advancedNotification` mode the command is not triggered updating an attribute, but creating a command
1359
+ execution entity. However, this mode has not been implemented yet so details are to be clarified.
1360
+
1326
1361
  For a given device provisioned with a `ping` command defined, any update on this attribute "ping" at the NGSI entity in
1327
1362
  the Context Broker will send a command to your device. For instance, to send the `ping` command with value
1328
1363
  `Ping request` you could use the following operation in the Context Broker API:
@@ -1784,6 +1819,7 @@ Config group is represented by a JSON object with the following fields:
1784
1819
  | `endpoint` | ✓ | `string` | | Endpoint where the group of device is going to receive commands, if any. |
1785
1820
  | `storeLastMeasure` | ✓ | `boolean` | | Store in device last measure received. See more info [in this section](admin.md#storelastmeasure). False by default |
1786
1821
  | `useCBflowControl` | ✓ | `boolean` | | Use Context Broker flow control. See more info [in this section](admin.md#useCBflowControl). False by default |
1822
+ | `cmdMode` | ✓ | `string` | | Command mode that will use iotagent with CB: **legacy**, **notification** and **advancedNotification**. **Legacy** is based on registers. **notification** based on simplified schema of subscriptions. **Legacy** by default. More information on how the different modes work can be found in [the northbound interactions documents](devel/northboundinteractions.md). |
1787
1823
 
1788
1824
  ### Config group operations
1789
1825
 
@@ -2007,6 +2043,7 @@ the API resource fields and the same fields in the database model.
2007
2043
  | `storeLastMeasure` | ✓ | `boolean` | | Store in device last measure received. Useful just for debugging purpose. See more info [in this section](admin.md#storelastmeasure). False by default. |
2008
2044
  | `lastMeasure` | ✓ | `object` | | last measure stored on device when `storeLastMeasure` is enabled. See more info [in this section](admin.md#storelastmeasure). This field can be cleared using `{}` in a device update request. In that case, `lastMeasure` is removed from device (until a next measure is received and `lastMesuare` gets created again). |
2009
2045
  | `useCBflowControl` | ✓ | `boolean` | | Use Context Broker flow control. See more info [in this section](admin.md#useCBflowControl). False by default. |
2046
+ | `cmdMode` | ✓ | `string` | | Command mode that will use iotagent with CB: **legacy**, **notification** and **advancedNotification**. **Legacy** is based on registers. **notification** based on simplified schema of subscriptions. **Legacy** by default. More information on how the different modes work can be found in [the northbound interactions documents](devel/northboundinteractions.md). |
2010
2047
 
2011
2048
  ### Device operations
2012
2049
 
@@ -2463,4 +2500,4 @@ updateEntityRequestsError 5
2463
2500
  [18]:
2464
2501
  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
2502
  [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=%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
2503
+ 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%20localestringnumber%3A%20(n%2C%20locale%2C%20options)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20safeOperation%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%20(fn)%20%3D%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20(...args)%20%3D%3E%20%7B%0A%20%20%20%20%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%20%20%20%20%20return%20fn(...args)%3B%0A%20%20%20%20%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%20%20%20%20%20return%20null%3B%0A%20%20%20%20%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%20%7D%3B%0A%20%20%20%20%20%20%20%20return%20safeOperation((n%2C%20locale%2C%20options)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20n%20!%3D%3D%20'number'%20%7C%7C%20isNaN(n))%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20n.toLocaleString(locale%2C%20options)%3B%0A%20%20%20%20%20%20%20%20%7D)(n%2C%20locale%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
package/doc/deprecated.md CHANGED
@@ -12,12 +12,16 @@ longer. In particular:
12
12
 
13
13
  A list of deprecated features and the version in which they were deprecated follows:
14
14
 
15
+ - Config `mongodb.*` different from `mongodb.uri` (and associated env vars `IOTA_MONGO_*` except `IOTA_MONGO_URI`) in 4.11.0
15
16
  - Support to NGSI v1 (finally removed in 2.18.0)
16
17
  - Support to Node.js v4 in iotagent-node-lib 2.8.1 (finally removed in 2.9.0)
17
18
  - Support to Node.js v6 in iotagent-node-lib 2.9.0 (finally removed in 2.10.0)
18
19
  - Support to Node.js v8 in iotagent-node-lib 2.12.0 (finally removed in 2.13.0)
19
20
  - Support to Node.js v10 in iotagent-node-lib 2.15.0 (finally removed in 2.16.0)
20
21
  - Support to Node.js v12 in iotagent-node-lib 2.24.0 (finally removed in 2.25.0)
22
+ - Support to Node.js v14 in iotagent-node-lib 3.0.0 (finally removed in 3.1.0)
23
+ - Support to Node.js v16 in iotagent-node-lib 4.9.0 (finally removed in 4.10.0)
24
+ - Support to Node.js v18 in iotagent-node-lib 4.9.0 (finally removed in 4.10.0)
21
25
  - Support to NGSI-LD v1.3 in iotagent-node-lib 2.25.0 (finally removed in 2.26.0)
22
26
  - Support groups (provision) statically defined by configuration
23
27
  - Support to in-memory registry (i.e.`deviceRegistry.type=memory`)
@@ -55,9 +59,23 @@ The following table provides information about the last iotagent-node-lib versio
55
59
  | Support to Node.js v8 | 2.12.0 | April 7th, 2020 |
56
60
  | Support to Node.js v10 | 2.15.0 | February 18th, 2021 |
57
61
  | Support to Node.js v12 | 2.24.0 | September 2nd, 2022 |
62
+ | Support to Node.js v14 | 3.0.0 | March 30th, 2023 |
63
+ | Support to Node.js v16 | 4.9.0 | August 22nd, 2025 |
64
+ | Support to Node.js v18 | 4.9.0 | August 22nd, 2025 |
58
65
  | Support to NGSI-LD 1.3 | 2.25.0 | January 24th, 2023 |
59
66
  | eventType configuration | 2.26.0 | March 15th, 2023 |
60
67
  | Support to Legacy Expressions | 3.1.0 | April 25th, 2023 |
61
68
  | bidirectional plugin | 3.3.0 | August 24th, 2023 |
62
69
  | appendMode configuration (`IOTA_APPEND_MODE` env var) | 3.3.0 | August 24th, 2023 |
63
70
  | push-mode stats | 4.5.0 | June 11th, 2024 |
71
+ | config `mongodb.host` (env var `IOTA_MONGO_HOST`) | Not yet | Not yet |
72
+ | config `mongodb.port` (env var `IOTA_MONGO_PORT`) | Not yet | Not yet |
73
+ | config `mongodb.db` (env var `IOTA_MONGO_DB`) | Not yet | Not yet |
74
+ | config `mongodb.replicaSet` (env var `IOTA_MONGO_REPLICASET`) | Not yet | Not yet |
75
+ | config `mongodb.user` (env var `IOTA_MONGO_USER`) | Not yet | Not yet |
76
+ | config `mongodb.password` (env var `IOTA_MONGO_PASSWORD`) | Not yet | Not yet |
77
+ | config `mongodb.authSource` (env var `IOTA_MONGO_AUTH_SOURCE`) | Not yet | Not yet |
78
+ | config `mongodb.retries` (env var `IOTA_MONGO_RETRIES`) | Not yet | Not yet |
79
+ | config `mongodb.retryTime` (env var `IOTA_MONGO_RETRY_TIME`) | Not yet | Not yet |
80
+ | config `mongodb.ssl` (env var `IOTA_MONGO_SSL`) | Not yet | Not yet |
81
+ | config `mongodb.extraArgs` (env var `IOTA_MONGO_EXTRAARGS`) | Not yet | Not yet |