iotagent-node-lib 4.2.0 → 4.4.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 (31) hide show
  1. package/doc/api.md +178 -69
  2. package/docker/Mosquitto/Dockerfile +1 -1
  3. package/lib/commonConfig.js +18 -0
  4. package/lib/errors.js +48 -20
  5. package/lib/services/commands/commandRegistryMemory.js +12 -2
  6. package/lib/services/commands/commandRegistryMongoDB.js +26 -15
  7. package/lib/services/devices/deviceRegistryMemory.js +1 -1
  8. package/lib/services/devices/deviceRegistryMongoDB.js +7 -12
  9. package/lib/services/devices/deviceService.js +4 -3
  10. package/lib/services/devices/devices-NGSI-LD.js +3 -3
  11. package/lib/services/devices/devices-NGSI-v2.js +10 -4
  12. package/lib/services/groups/groupRegistryMemory.js +1 -1
  13. package/lib/services/groups/groupRegistryMongoDB.js +1 -1
  14. package/lib/services/groups/groupService.js +9 -3
  15. package/lib/services/ngsi/entities-NGSI-LD.js +15 -7
  16. package/lib/services/ngsi/entities-NGSI-v2.js +86 -54
  17. package/lib/services/ngsi/ngsiService.js +3 -3
  18. package/lib/services/ngsi/subscription-NGSI-LD.js +2 -0
  19. package/lib/services/ngsi/subscription-NGSI-v2.js +2 -0
  20. package/lib/services/northBound/contextServer-NGSI-LD.js +50 -55
  21. package/lib/services/northBound/contextServer-NGSI-v2.js +1 -1
  22. package/lib/services/northBound/deviceProvisioningServer.js +100 -26
  23. package/lib/services/northBound/restUtils.js +1 -1
  24. package/package.json +2 -2
  25. package/scripts/legacy_expression_tool/requirements.txt +1 -1
  26. package/test/functional/testCases.js +797 -66
  27. package/test/functional/testUtils.js +3 -1
  28. package/test/unit/ngsi-ld/ngsiService/active-devices-test.js +0 -1
  29. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +8 -5
  30. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +34 -2
  31. package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +37 -2
package/doc/api.md CHANGED
@@ -8,6 +8,8 @@
8
8
  - [IoT Agent information model](#iot-agent-information-model)
9
9
  - [Config groups](#config-groups)
10
10
  - [Devices](#devices)
11
+ - [Uniqueness of groups and devices](#uniqueness-of-groups-and-devices)
12
+ - [Special measures and attributes names](#special-measures-and-attributes-names)
11
13
  - [Entity attributes](#entity-attributes)
12
14
  - [Multientity support)](#multientity-support)
13
15
  - [Metadata support](#metadata-support)
@@ -53,6 +55,8 @@
53
55
  - [Get device details `GET /iot/devices/:deviceId`](#get-device-details-get-iotdevicesdeviceid)
54
56
  - [Modify device `PUT /iot/devices/:deviceId`](#modify-device-put-iotdevicesdeviceid)
55
57
  - [Remove device `DELETE /iot/devices/:deviceId`](#remove-device-delete-iotdevicesdeviceid)
58
+ - [Batch Operations](#batch-operations)
59
+ - [Remove devices `POST /iot/op/delete`](#remove-devices-post-iotopdelete)
56
60
  - [Miscellaneous API](#miscellaneous-api)
57
61
  - [Log operations](#log-operations)
58
62
  - [Modify Loglevel `PUT /admin/log`](#modify-loglevel-put-adminlog)
@@ -130,9 +134,9 @@ parameters. The specific parameters that can be configured for a given config gr
130
134
  ### Devices
131
135
 
132
136
  A device contains the information that connects a physical device to a particular entity in the Context Broker. Devices
133
- are identified by a `device_id`, and they are associated to an existing config group based in `apiKey` matching or
134
- `type` matching (in the case `apiKey` matching fails). For instance, let's consider a situation in which a config group
135
- has been provisioned with `type=X`/`apiKey=111` and no other config group has been provisioned.
137
+ are identified by a `device_id`, and they are associated to an existing config group based in `apikey` matching. For
138
+ instance, let's consider a situation in which a config group has been provisioned with `type=X`/`apikey=111` and no
139
+ other config group has been provisioned.
136
140
 
137
141
  The IoT Agents offer a provisioning API where devices can be preregistered, so all the information about service and
138
142
  subservice mapping, security information and attribute configuration can be specified in a per device way instead of
@@ -140,7 +144,7 @@ relaying on the config group configuration. The specific parameters that can be
140
144
  described in the [Device datamodel](#device-datamodel) section.
141
145
 
142
146
  If devices are not pre-registered, they will be automatically created when a measure arrives to the IoT Agent - this
143
- process is known as autoprovisioning. The IoT Agent will create an empty device with the group `apiKey` and `type` - the
147
+ process is known as autoprovisioning. The IoT Agent will create an empty device with the group `apikey` and `type` - the
144
148
  associated document created in database doesn't include config group parameters (in particular, `timestamp`,
145
149
  `explicitAttrs`, `active` or `attributes`, `static` and `lazy` attributes and commands). The IoT Agent will also create
146
150
  the entity in the Context Broker if it does not exist yet.
@@ -149,6 +153,23 @@ This behavior allows that autoprovisioned parameters can freely established modi
149
153
  creation using the provisioning API. However, note that if a device (autoprovisioned or not) doesn't have these
150
154
  parameters defined at device level in database, the parameters are inherit from config group parameters.
151
155
 
156
+ ### Uniqueness of groups and devices
157
+
158
+ Group service uniqueness is defined by the combination of: service, subservice and apikey
159
+
160
+ Device uniqueness is defined by the combination of: service, subservice, device_id and apikey. Note that several devices
161
+ with the same device_id are allowed in the same service and subservice as long as their apikeys are different.
162
+
163
+ ## Special measures and attributes names
164
+
165
+ In case of arriving measures with name `id` or `type`, they are automatically transformed to `measure_id` and
166
+ `measure_type` attributes at Context Broker update. The reason behind this is to avoid to collide with the original
167
+ entity ID and type, as mechanism that enable store measure values from parameters called with the same name. It only
168
+ applies to autoprovisioned attributes and is also available at JEXL context with the same name (`measure_id` or
169
+ `measure_type`).
170
+
171
+ In case of provisioning attributes using `id` or `type` as names (please don't do that ;), they are ignored.
172
+
152
173
  ## Entity attributes
153
174
 
154
175
  In the config group/device model there are four list of attributes with different purpose to configure how the
@@ -293,6 +314,43 @@ e.g.:
293
314
  }
294
315
  ```
295
316
 
317
+ Metadata could also has `expression` like attributes in order to expand it:
318
+
319
+ e.g.:
320
+
321
+ ```json
322
+ {
323
+ "entity_type": "Lamp",
324
+ "resource": "/iot/d",
325
+ "protocol": "PDI-IoTA-UltraLight",
326
+ ..etc
327
+ "commands": [
328
+ {"name": "on","type": "command"},
329
+ {"name": "off","type": "command"}
330
+ ],
331
+ "attributes": [
332
+ {"object_id": "s", "name": "state", "type":"Text"},
333
+ {"object_id": "l", "name": "luminosity", "type":"Integer",
334
+ "metadata":{
335
+ "unitCode":{"type": "Text", "value" :"CAL"}
336
+ }
337
+ }
338
+ ],
339
+ "static_attributes": [
340
+ {"name": "category", "type":"Text", "value": ["actuator","sensor"]},
341
+ {"name": "controlledProperty", "type": "Text", "value": ["light"],
342
+ "metadata":{
343
+ "includes":{"type": "Text",
344
+ "value" :["state", "luminosity"],
345
+ "expression": "level / 100"
346
+ },
347
+ "alias":{"type": "Text", "value" :"lamp"}
348
+ }
349
+ },
350
+ ]
351
+ }
352
+ ```
353
+
296
354
  ### NGSI-LD data and metadata considerations
297
355
 
298
356
  When provisioning devices for an NGSI-LD Context Broker, `type` values should typically correspond to one of the
@@ -504,8 +562,8 @@ expression. In all cases the following data is available to all expressions:
504
562
  - `subservice`: device subservice
505
563
  - `staticAttributes`: static attributes defined in the device or config group
506
564
 
507
- Additionally, for attribute expressions (`expression`, `entity_name`) and `entityNameExp` measures are avaiable in the
508
- **context** used to evaluate them.
565
+ Additionally, for attribute expressions (`expression`, `entity_name`), `entityNameExp` and metadata expressions
566
+ (`expression`) measures are available in the **context** used to evaluate them.
509
567
 
510
568
  ### Examples of JEXL expressions
511
569
 
@@ -951,31 +1009,40 @@ Will now generate the following NGSI v2 payload:
951
1009
 
952
1010
  ## Timestamp Processing
953
1011
 
954
- The IOTA processes the entity attributes looking for a `TimeInstant` attribute. If one is found, for NGSI v2, then it
955
- adds a `TimeInstant` attribute as metadata for every other attribute in the same request. With NGSI-LD, the Standard
956
- `observedAt` property-of-a-property is used instead.
1012
+ Timestamp processing done by IOTA is as follows:
1013
+
1014
+ - An attribute `TimeInstant` is added to updated entities
1015
+ - In the case of NGSI-v2, a `TimeInstant` metadata is added in each updated attribute. With NGSI-LD, the Standard
1016
+ `observedAt` property-of-a-property is used instead.
1017
+
1018
+ Depending on the `timestamp` configuration and if the measure contains a value named `TimeInstant` with a correct value,
1019
+ the IoTA behaviour is described in the following table:
957
1020
 
958
- If a `TimeInstant` arrives as measure but not follows [ISO_8601](https://en.wikipedia.org/wiki/ISO_8601) then measure
959
- is refused.
1021
+ | `timestamp` conf value | measure contains `TimeInstant` | Behaviour |
1022
+ | ---------------------- | ------------------------------ | ------------------------------------------------------ |
1023
+ | true | Yes | TimeInstant and metadata updated with measure value |
1024
+ | true | No | TimeInstant and metadata updated with server timestamp |
1025
+ | false | Yes | TimeInstant and metadata updated with measure value |
1026
+ | false | No | TimeInstant and metadata updated with server timestamp |
1027
+ | Not defined | Yes | TimeInstant and metadata updated with measure value |
1028
+ | Not defined | No | TimeInstant and metadata updated with server timestamp |
960
1029
 
961
- Depending on the `timestamp` configuration and if the measure contains a
962
- value named `TimeInstant` with a correct value, the IoTA behaviour is described
963
- in the following table:
1030
+ The `timestamp` conf value used is:
964
1031
 
965
- `timestamp` value | measure contains `TimeInstant` | Behaviour
966
- -- | -- | --
967
- true | Yes | TimeInstant and metadata updated with measure value
968
- true | No | TimeInstant and metadata updated with server timestamp
969
- false | Yes | TimeInstant and metadata updated with measure value
970
- false | No | TimeInstant and metadata updated with server timestamp
971
- Not defined | Yes | TimeInstant and metadata updated with measure value
972
- Not defined | No | TimeInstant and metadata updated with server timestamp
1032
+ - The one defined at device level
1033
+ - The one defined at group level (if not defined at device level)
1034
+ - The one defined at [IoTA configuration level](admin.md#timestamp) / `IOTA_TIMESTAMP` env var (if not defined at
1035
+ group level or device level)
973
1036
 
974
- The `timestamp` value used is:
1037
+ Some additional considerations to take into account:
975
1038
 
976
- * The one defined at device level
977
- * The one defined at group level (if not defined at device level)
978
- * The one defined at [IoTA configuration level](admin.md#timestamp) / `IOTA_TIMESTAMP` env var (if not defined at group level or device level)
1039
+ - If there is an attribute which maps a measure to `TimeInstant` attribute (after
1040
+ [expression evaluation](#expression-language-support) if any is defined), then that value will be used as
1041
+ `TimeInstant, overwriting the above rules specified in "Behaviour" column. Note that an expression in the could be
1042
+ used in that mapping.
1043
+ - If the resulting `TimeInstant` not follows [ISO_8601](https://en.wikipedia.org/wiki/ISO_8601) (either from a direct
1044
+ measure of after a mapping, as described in the previous bullet) then it is refused (so a failover to server
1045
+ timestamp will take place).
979
1046
 
980
1047
  ## Overriding global Context Broker host
981
1048
 
@@ -1217,29 +1284,29 @@ A `datasetId` is also maintained for each new attribute defined in the `reverse`
1217
1284
 
1218
1285
  Config group is represented by a JSON object with the following fields:
1219
1286
 
1220
- | Field | Optional | Type | Expression | Definitiom |
1221
- | ------------------------------ | -------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1222
- | `service` | | string | | `FIWARE-Service` header to be used |
1223
- | `subservice` | | string | | Subservice of the devices of this type. |
1224
- | `resource` | | string | | string representing the Southbound resource that will be used to assign a type to a device (e.g.: pathname in the southbound port). |
1225
- | `apikey` | | string | | API Key string. |
1287
+ | Field | Optional | Type | Expression | Definitiom |
1288
+ | ------------------------------ | -------- | -------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1289
+ | `service` | | string | | `FIWARE-Service` header to be used |
1290
+ | `subservice` | | string | | Subservice of the devices of this type. |
1291
+ | `resource` | | string | | string representing the Southbound resource that will be used to assign a type to a device (e.g.: pathname in the southbound port). |
1292
+ | `apikey` | | string | | API Key string. |
1226
1293
  | `timestamp` | ✓ | bool | | Optional flag about whether or not to add the `TimeInstant` attribute to the device entity created, as well as a `TimeInstant` metadata to each attribute, with the current server timestamp or provided `TimeInstant` as measure when follows ISO 8601 format (see [timestamp processing](#timestamp-processing) section for aditional detail). With NGSI-LD, the Standard `observedAt` property-of-a-property is created instead. |
1227
- | `entity_type` | | string | | name of the Entity `type` to assign to the group. |
1228
- | `trust` | ✓ | string | | trust token to use for secured access to the Context Broker for this type of devices (optional; only needed for secured scenarios). |
1229
- | `cbHost` | ✓ | string | | Context Broker connection information. This options can be used to override the global ones for specific types of devices. |
1230
- | `lazy` | ✓ | | | list of common lazy attributes of the device. For each attribute, its `name` and `type` must be provided. |
1231
- | `commands` | ✓ | | | list of common commands attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. |
1232
- | `attributes` | ✓ | | | list of common active attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. |
1233
- | `static_attributes` | ✓ | | | this attributes will be added to all the entities of this group 'as is', additional `metadata` is optional. |
1234
- | `internal_attributes` | ✓ | | | optional section with free format, to allow specific IoT Agents to store information along with the devices in the Device Registry. |
1235
- | `explicitAttrs` | ✓ | string or bool | ✓ | optional field to support selective ignore of measures so that IOTA doesn’t progress. See details in [specific section](#explicitly-defined-attributes-explicitattrs) |
1236
- | `entityNameExp` | ✓ | string | | optional field to allow use expressions to define entity name, instead default `id` and `type` |
1237
- | `ngsiVersion` | ✓ | string | | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. Possible values are: `v2` or `ld`. The default is `v2`. When not running in mixed mode, this field is ignored. |
1238
- | `defaultEntityNameConjunction` | ✓ | string | | optional string value to set default conjunction string used to compose a default `entity_name` when is not provided at device provisioning time. |
1239
- | `autoprovision` | ✓ | bool | ✓? | optional boolean: If `false`, autoprovisioned devices (i.e. devices that are not created with an explicit provision operation but when the first measure arrives) are not allowed in this group. Default (in the case of omitting the field) is `true`. |
1240
- | `payloadType` | ✓ | string | | optional string value used to switch between **IoTAgent**, **NGSI-v2** and **NGSI-LD** measure payloads types. Possible values are: `iotagent`, `ngsiv2` or `ngsild`. The default is `iotagent`. |
1241
- | `transport` | ✓ | `string` | | Transport protocol used by the group of devices to send updates, for the IoT Agents with multiple transport protocols. |
1242
- | `endpoint` | ✓ | `string` | | Endpoint where the group of device is going to receive commands, if any. |
1294
+ | `entity_type` | | string | | name of the Entity `type` to assign to the group. |
1295
+ | `trust` | ✓ | string | | trust token to use for secured access to the Context Broker for this type of devices (optional; only needed for secured scenarios). |
1296
+ | `cbHost` | ✓ | string | | Context Broker connection information. This options can be used to override the global ones for specific types of devices. |
1297
+ | `lazy` | ✓ | | | list of common lazy attributes of the device. For each attribute, its `name` and `type` must be provided. |
1298
+ | `commands` | ✓ | | | list of common commands attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. |
1299
+ | `attributes` | ✓ | | | list of common active attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. |
1300
+ | `static_attributes` | ✓ | | | this attributes will be added to all the entities of this group 'as is', additional `metadata` is optional. |
1301
+ | `internal_attributes` | ✓ | | | optional section with free format, to allow specific IoT Agents to store information along with the devices in the Device Registry. |
1302
+ | `explicitAttrs` | ✓ | string or bool | ✓ | optional field to support selective ignore of measures so that IOTA doesn’t progress. See details in [specific section](#explicitly-defined-attributes-explicitattrs) |
1303
+ | `entityNameExp` | ✓ | string | | optional field to allow use expressions to define entity name, instead default name, based on the device ID and the entity type (i.e. `<device_id>:<entity_type>`) |
1304
+ | `ngsiVersion` | ✓ | string | | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. Possible values are: `v2` or `ld`. The default is `v2`. When not running in mixed mode, this field is ignored. |
1305
+ | `defaultEntityNameConjunction` | ✓ | string | | optional string value to set default conjunction string used to compose a default `entity_name` when is not provided at device provisioning time. |
1306
+ | `autoprovision` | ✓ | bool | ✓? | optional boolean: If `false`, autoprovisioned devices (i.e. devices that are not created with an explicit provision operation but when the first measure arrives) are not allowed in this group. Default (in the case of omitting the field) is `true`. |
1307
+ | `payloadType` | ✓ | string | | optional string value used to switch between **IoTAgent**, **NGSI-v2** and **NGSI-LD** measure payloads types. Possible values are: `iotagent`, `ngsiv2` or `ngsild`. The default is `iotagent`. |
1308
+ | `transport` | ✓ | `string` | | Transport protocol used by the group of devices to send updates, for the IoT Agents with multiple transport protocols. |
1309
+ | `endpoint` | ✓ | `string` | | Endpoint where the group of device is going to receive commands, if any. |
1243
1310
 
1244
1311
  ### Config group operations
1245
1312
 
@@ -1439,27 +1506,27 @@ _**Response code**_
1439
1506
  The table below shows the information held in the Device resource. The table also contains the correspondence between
1440
1507
  the API resource fields and the same fields in the database model.
1441
1508
 
1442
- | Field | Optional | Type | Expression | Definitiom |
1443
- | --------------------- | -------- | --------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1444
- | `device_id` | | `string` | | Device ID that will be used to identify the device. |
1445
- | `service` | | `string` | | Name of the service the device belongs to (will be used in the fiware-service header). |
1446
- | `service_path` | | `string` | | Name of the subservice the device belongs to (used in the fiware-servicepath header). |
1447
- | `entity_name` | | `string` | | Name of the entity representing the device in the Context Broker |
1448
- | `entity_type` | | `string` | | Type of the entity in the Context Broker |
1449
- | `timezone` | ✓ | `string` | | Timezone of the device if that has any |
1509
+ | Field | Optional | Type | Expression | Definitiom |
1510
+ | --------------------- | -------- | --------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1511
+ | `device_id` | | `string` | | Device ID that will be used to identify the device. |
1512
+ | `service` | | `string` | | Name of the service the device belongs to (will be used in the fiware-service header). |
1513
+ | `service_path` | | `string` | | Name of the subservice the device belongs to (used in the fiware-servicepath header). |
1514
+ | `entity_name` | | `string` | | Name of the entity representing the device in the Context Broker |
1515
+ | `entity_type` | | `string` | | Type of the entity in the Context Broker |
1516
+ | `timezone` | ✓ | `string` | | Timezone of the device if that has any |
1450
1517
  | `timestamp` | ✓ | `string` | | Flag about whether or not to add the `TimeInstant` attribute to the device entity created, as well as a `TimeInstant` metadata to each attribute, with the current server timestamp or provided `TimeInstant` as measure when follows ISO 8601 format (see [timestamp processing](#timestamp-processing) section for aditional detail). With NGSI-LD, the Standard `observedAt` property-of-a-property is created instead. |
1451
- | `apikey` | ✓ | `string` | | Apikey key string to use instead of group apikey |
1452
- | `endpoint` | ✓ | `string` | | Endpoint where the device is going to receive commands, if any. |
1453
- | `protocol` | ✓ | `string` | | Pame of the device protocol, for its use with an IoT Manager |
1454
- | `transport` | ✓ | `string` | | Transport protocol used by the device to send updates, for the IoT Agents with multiple transport protocols. |
1455
- | `attributes` | ✓ | `array` | | List of attributes that will be stored in the Context Broker. |
1456
- | `commands` | ✓ | `array` | | List of commands that will be stored in the Context Broker. |
1457
- | `lazy` | ✓ | `array` | | List of lazy attributes that will be stored in the Context Broker. |
1458
- | `static_attributes` | ✓ | `array` | | List of static attributes that will be stored in the Context Broker. |
1459
- | `internal_attributes` | ✓ | `array` | | List of internal attributes with free format for specific IoT Agent configuration. |
1460
- | `explicitAttrs` | ✓ | `boolean` | ✓ | Field to support selective ignore of measures so that IOTA doesn’t progress. See details in [specific section](#explicitly-defined-attributes-explicitattrs) |
1461
- | `ngsiVersion` | ✓ | `string` | | string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. The default is `v2`. When not running in mixed mode, this field is ignored. |
1462
- | `payloadType` | ✓ | `string` | | optional string value used to switch between **IoTAgent**, **NGSI-v2** and **NGSI-LD** measure payloads types. Possible values are: `iotagent`, `ngsiv2` or `ngsild`. The default is `iotagent`. |
1518
+ | `apikey` | ✓ | `string` | | Apikey key string to use instead of group apikey |
1519
+ | `endpoint` | ✓ | `string` | | Endpoint where the device is going to receive commands, if any. |
1520
+ | `protocol` | ✓ | `string` | | Pame of the device protocol, for its use with an IoT Manager |
1521
+ | `transport` | ✓ | `string` | | Transport protocol used by the device to send updates, for the IoT Agents with multiple transport protocols. |
1522
+ | `attributes` | ✓ | `array` | | List of attributes that will be stored in the Context Broker. |
1523
+ | `commands` | ✓ | `array` | | List of commands that will be stored in the Context Broker. |
1524
+ | `lazy` | ✓ | `array` | | List of lazy attributes that will be stored in the Context Broker. |
1525
+ | `static_attributes` | ✓ | `array` | | List of static attributes that will be stored in the Context Broker. |
1526
+ | `internal_attributes` | ✓ | `array` | | List of internal attributes with free format for specific IoT Agent configuration. |
1527
+ | `explicitAttrs` | ✓ | `boolean` | ✓ | Field to support selective ignore of measures so that IOTA doesn’t progress. See details in [specific section](#explicitly-defined-attributes-explicitattrs) |
1528
+ | `ngsiVersion` | ✓ | `string` | | string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. The default is `v2`. When not running in mixed mode, this field is ignored. |
1529
+ | `payloadType` | ✓ | `string` | | optional string value used to switch between **IoTAgent**, **NGSI-v2** and **NGSI-LD** measure payloads types. Possible values are: `iotagent`, `ngsiv2` or `ngsild`. The default is `iotagent`. |
1463
1530
 
1464
1531
  ### Device operations
1465
1532
 
@@ -1710,10 +1777,52 @@ _**Request headers**_
1710
1777
 
1711
1778
  _**Response code**_
1712
1779
 
1713
- - `200` `OK` if successful.
1780
+ - `204` `OK` if successful.
1714
1781
  - `404` `NOT FOUND` if the device was not found in the database.
1715
1782
  - `500` `SERVER ERROR` if there was any error not contemplated above.
1716
1783
 
1784
+ ### Batch Operations
1785
+
1786
+ #### Remove devices `POST /iot/op/delete`
1787
+
1788
+ Remove a set of devices from the device registry. The devices is identified by the Device ID and apikey in payload body.
1789
+
1790
+ _**Request headers**_
1791
+
1792
+ | Header | Optional | Description | Example |
1793
+ | -------------------- | -------- | ---------------------------------------------------------------------------------------------- | ---------- |
1794
+ | `Fiware-Service` | ✓ | Tenant or service. See subsection [Multi tenancy](#multi-tenancy) for more information. | `acme` |
1795
+ | `Fiware-ServicePath` | ✓ | Service path or subservice. See subsection [Service Path](#service-path) for more information. | `/project` |
1796
+
1797
+ _**Request body**_
1798
+
1799
+ The request body contains an Array of objects which the values which identifies the devices, deviceId and apikey. For
1800
+ more information, see the [Device datamodel](#device-datamodel) section.
1801
+
1802
+ Example:
1803
+
1804
+ ```json
1805
+ {
1806
+ "devices": [
1807
+ {
1808
+ "deviceId": "myDevice1",
1809
+ "apikey": "apikey1"
1810
+ },
1811
+ {
1812
+ "deviceId": "myDevice2",
1813
+ "apikey": "apikey2"
1814
+ }
1815
+ ]
1816
+ }
1817
+ ```
1818
+
1819
+ _**Response code**_
1820
+
1821
+ - `204` `OK` if successful.
1822
+ - `404` `NOT FOUND` if one or several devices were not found in the database. Note that although a 404 error is
1823
+ returned the existing devices are deleted.
1824
+ - `500` `SERVER ERROR` if there was any error not considered above.
1825
+
1717
1826
  ## Miscellaneous API
1718
1827
 
1719
1828
  ### Log operations
@@ -1,4 +1,4 @@
1
- ARG IMAGE_TAG=12.4-slim
1
+ ARG IMAGE_TAG=12.5-slim
2
2
  FROM debian:${IMAGE_TAG}
3
3
 
4
4
  ARG CLEAN_DEV_TOOLS
@@ -485,6 +485,23 @@ function getConfig() {
485
485
  return config;
486
486
  }
487
487
 
488
+ function getConfigForTypeInformation() {
489
+ // Just return relevant configuration flags
490
+ // avoid to include server, authentication, mongodb, orion and iotamanger info
491
+ let conf = {
492
+ timestamp: config.timestamp,
493
+ defaultResource: config.defaultResource,
494
+ explicitAttrs: config.explicitAttrs,
495
+ pollingExpiration: config.pollingExpiration,
496
+ pollingDaemonFrequency: config.pollingDaemonFrequency,
497
+ multiCore: config.multiCore,
498
+ relaxTemplateValidation: config.relaxTemplateValidation,
499
+ defaultEntityNameConjunction: config.defaultEntityNameConjunction,
500
+ defaultType: config.defaultType
501
+ };
502
+ return conf;
503
+ }
504
+
488
505
  function setRegistry(newRegistry) {
489
506
  registry = newRegistry;
490
507
  }
@@ -541,6 +558,7 @@ function getSecurityService() {
541
558
 
542
559
  exports.setConfig = setConfig;
543
560
  exports.getConfig = getConfig;
561
+ exports.getConfigForTypeInformation = getConfigForTypeInformation;
544
562
  exports.setRegistry = setRegistry;
545
563
  exports.getRegistry = getRegistry;
546
564
  exports.setGroupRegistry = setGroupRegistry;
package/lib/errors.js CHANGED
@@ -36,9 +36,15 @@ class UnregistrationError {
36
36
  }
37
37
  }
38
38
  class EntityGenericError {
39
- constructor(id, type, details, code) {
39
+ constructor(id, type, typeInformation, details, code) {
40
40
  this.name = 'ENTITY_GENERIC_ERROR';
41
- this.message = 'Error accesing entity data for device: ' + id + ' of type: ' + type;
41
+ this.message =
42
+ 'Error accesing entity data for device: ' +
43
+ id +
44
+ ' of type: ' +
45
+ type +
46
+ ' and ' +
47
+ JSON.stringify(typeInformation);
42
48
  this.details = details || {};
43
49
  this.code = code || 200;
44
50
  }
@@ -77,36 +83,47 @@ class UnsupportedContentType {
77
83
  }
78
84
  }
79
85
  class TypeNotFound {
80
- constructor(id, type) {
86
+ constructor(id, type, typeInformation) {
81
87
  this.name = 'TYPE_NOT_FOUND';
82
- this.message = 'Type : ' + type + ' not found for device with id: ' + id;
88
+ this.message =
89
+ 'Type : ' + type + ' not found for device with id: ' + id + ' with: ' + JSON.stringify(typeInformation);
83
90
  this.code = 500;
84
91
  }
85
92
  }
86
93
  class MissingAttributes {
87
- constructor(msg) {
94
+ constructor(msg, device) {
88
95
  this.name = 'MISSING_ATTRIBUTES';
89
- this.message = 'The request was not well formed:' + msg;
96
+ this.message = 'The request was not well formed:' + msg + ' with: ' + JSON.stringify(device);
90
97
  }
91
98
  }
92
99
  class DeviceNotFound {
93
- constructor(id) {
100
+ constructor(id, typeInformation) {
94
101
  this.name = 'DEVICE_NOT_FOUND';
95
- this.message = 'No device was found with id:' + id;
102
+ this.message = 'No device was found with id:' + id + ' and ' + JSON.stringify(typeInformation);
96
103
  this.code = 404;
97
104
  }
98
105
  }
99
106
  class DuplicateDeviceId {
100
- constructor(id) {
107
+ constructor(device) {
101
108
  this.name = 'DUPLICATE_DEVICE_ID';
102
- this.message = 'A device with the same pair (Service, DeviceId) was found:' + id;
109
+ this.message =
110
+ 'A device with the same info (DeviceId, ApiKey, Service, Subservice) was found:' +
111
+ device.id +
112
+ ' and ' +
113
+ JSON.stringify(device);
103
114
  this.code = 409;
104
115
  }
105
116
  }
106
117
  class DuplicateGroup {
107
- constructor(res, key) {
118
+ constructor(group) {
108
119
  this.name = 'DUPLICATE_GROUP';
109
- this.message = 'A device configuration already exists for resource ' + res + ' and API Key ' + key;
120
+ this.message =
121
+ 'A device configuration already exists for resource ' +
122
+ group.resource +
123
+ ' and API Key ' +
124
+ group.apikey +
125
+ ' and ' +
126
+ JSON.stringify(group);
110
127
  this.code = 409;
111
128
  }
112
129
  }
@@ -170,9 +187,13 @@ class WrongSyntax {
170
187
  }
171
188
  }
172
189
  class CommandNotFound {
173
- constructor(name) {
190
+ constructor(name, typeInformation) {
174
191
  this.name = 'COMMAND_NOT_FOUND';
175
- this.message = "Couldn't update the command because no command with the name [" + name + '] was found.';
192
+ this.message =
193
+ "Couldn't update the command because no command with the name [" +
194
+ name +
195
+ '] was found with ' +
196
+ JSON.stringify(typeInformation);
176
197
  this.code = 400;
177
198
  }
178
199
  }
@@ -201,9 +222,10 @@ class DeviceGroupNotFound {
201
222
  }
202
223
  }
203
224
  class GroupNotFound {
204
- constructor(service, subservice) {
225
+ constructor(service, subservice, type) {
205
226
  this.name = 'GROUP_NOT_FOUND';
206
- this.message = 'Group not found for service [' + service + '] and subservice [' + subservice + ']';
227
+ this.message =
228
+ 'Group not found for service [' + service + '] subservice [' + subservice + '] and type [' + type + ']';
207
229
  this.code = 404;
208
230
  }
209
231
  }
@@ -229,16 +251,22 @@ class BadAnswer {
229
251
  }
230
252
  }
231
253
  class BadTimestamp {
232
- constructor(payload, entityName) {
254
+ constructor(payload, entityName, typeInformation) {
233
255
  this.name = 'BAD_TIMESTAMP';
234
- this.message = 'Invalid ISO8601 timestamp [' + payload + '] in [' + entityName + ']';
256
+ this.message =
257
+ 'Invalid ISO8601 timestamp [' +
258
+ payload +
259
+ '] in [' +
260
+ entityName +
261
+ '] with: ' +
262
+ JSON.stringify(typeInformation);
235
263
  this.code = 400;
236
264
  }
237
265
  }
238
266
  class BadGeocoordinates {
239
- constructor(payload) {
267
+ constructor(payload, device) {
240
268
  this.name = 'BAD_GEOCOORDINATES';
241
- this.message = 'Invalid rfc7946 coordinates [' + payload + ']';
269
+ this.message = 'Invalid rfc7946 coordinates [' + payload + '] in ' + JSON.stringify(device);
242
270
  this.code = 400;
243
271
  }
244
272
  }
@@ -75,7 +75,12 @@ function updateCommand(service, subservice, deviceId, command, callback) {
75
75
 
76
76
  callback(null, foundCommand);
77
77
  } else {
78
- callback(new errors.CommandNotFound(command.name));
78
+ const deviceInfo = {
79
+ service,
80
+ subservice,
81
+ deviceId
82
+ };
83
+ callback(new errors.CommandNotFound(command.name, deviceInfo));
79
84
  }
80
85
  }
81
86
 
@@ -144,7 +149,12 @@ function remove(service, subservice, deviceId, name, callback) {
144
149
  delete registeredCommands[foundCommand._id];
145
150
  callback(null, foundCommand);
146
151
  } else {
147
- callback(new errors.CommandNotFound(name));
152
+ const deviceInfo = {
153
+ service,
154
+ subservice,
155
+ deviceId
156
+ };
157
+ callback(new errors.CommandNotFound(name, deviceInfo));
148
158
  }
149
159
  }
150
160