iotagent-node-lib 4.3.0 → 4.5.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.
- package/config.js +2 -1
- package/doc/admin.md +16 -7
- package/doc/api.md +230 -45
- package/doc/requirements.txt +1 -1
- package/docker/Mosquitto/Dockerfile +1 -1
- package/lib/commonConfig.js +25 -1
- package/lib/errors.js +4 -1
- package/lib/services/devices/deviceRegistryMemory.js +1 -1
- package/lib/services/devices/deviceRegistryMongoDB.js +3 -10
- package/lib/services/devices/deviceService.js +5 -3
- package/lib/services/devices/devices-NGSI-LD.js +5 -5
- package/lib/services/devices/devices-NGSI-mixed.js +3 -3
- package/lib/services/devices/devices-NGSI-v2.js +5 -5
- package/lib/services/ngsi/entities-NGSI-LD.js +1 -1
- package/lib/services/ngsi/entities-NGSI-v2.js +324 -268
- package/lib/services/ngsi/ngsiService.js +2 -2
- package/lib/services/ngsi/subscription-NGSI-LD.js +2 -2
- package/lib/services/ngsi/subscription-NGSI-v2.js +2 -2
- package/lib/services/northBound/deviceProvisioningServer.js +5 -4
- package/lib/services/northBound/northboundServer.js +2 -2
- package/package.json +2 -2
- package/scripts/legacy_expression_tool/requirements.txt +1 -1
- package/test/functional/README.md +60 -37
- package/test/functional/testCases.js +2206 -722
- package/test/functional/testUtils.js +53 -20
- package/test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithApikey.json +4 -0
- package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +5 -5
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +34 -2
- package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +6 -6
- package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +35 -0
package/config.js
CHANGED
package/doc/admin.md
CHANGED
|
@@ -260,13 +260,13 @@ the `mongob` section (as described bellow). E.g.:
|
|
|
260
260
|
|
|
261
261
|
It configures the MongoDB driver for those repositories with 'mongodb' type. If the `host` parameter is a list of
|
|
262
262
|
comma-separated IPs, they will be considered to be part of a Replica Set. In that case, the optional property
|
|
263
|
-
`replicaSet` should contain the Replica Set name. If the database requires authentication, username (`user`),
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
263
|
+
`replicaSet` should contain the Replica Set name. If the database requires authentication, username (`user`), password
|
|
264
|
+
(`password`) and authSource (`authSource`) can be set. If the database requires TLS/SSL connection but any validation of
|
|
265
|
+
the certificate chain is not mandatory, all you need is to set the ssl (`ssl`) option as `true` to connect the database.
|
|
266
|
+
If you need to add more complex option(s) such as `retryWrites=true` or `w=majority` when connection database, extraArgs
|
|
267
|
+
(`extraArgs`) can be used to perform it. For The MongoBD driver will retry the connection at startup time `retries`
|
|
268
|
+
times, waiting `retryTime` seconds between attempts, if those attributes are present (default values are 5 and 5
|
|
269
|
+
respectively). E.g.:
|
|
270
270
|
|
|
271
271
|
```javascript
|
|
272
272
|
{
|
|
@@ -421,6 +421,14 @@ characters (such as semi-colons) which are
|
|
|
421
421
|
specification. When provisioning devices, it is necessary that the developer provides valid `objectId`-`name` mappings
|
|
422
422
|
whenever relaxed mode is used, to prevent the consumption of forbidden characters.
|
|
423
423
|
|
|
424
|
+
#### `expressLimit`
|
|
425
|
+
|
|
426
|
+
IotAgents, as all Express applications that use the body-parser middleware, have a default limit to the request body
|
|
427
|
+
size that the application will handle. This default limit for ioiotagnets are 1Mb. So, if your IotAgent receives a
|
|
428
|
+
request with a body that exceeds this limit, the application will throw a “Error: Request entity too large”.
|
|
429
|
+
|
|
430
|
+
The 1Mb default can be changed setting the `expressLimit` configuration parameter (or equivalente `IOTA_EXPRESS_LIMIT` environment variable).
|
|
431
|
+
|
|
424
432
|
### Configuration using environment variables
|
|
425
433
|
|
|
426
434
|
Some of the configuration parameters can be overriden with environment variables, to ease the use of those parameters
|
|
@@ -482,6 +490,7 @@ overrides.
|
|
|
482
490
|
| IOTA_EXPLICIT_ATTRS | `explicitAttrs` |
|
|
483
491
|
| IOTA_DEFAULT_ENTITY_NAME_CONJUNCTION | `defaultEntityNameConjunction` |
|
|
484
492
|
| IOTA_RELAX_TEMPLATE_VALIDATION | `relaxTemplateValidation` |
|
|
493
|
+
| IOTA_EXPRESS_LIMIT | `expressLimit` |
|
|
485
494
|
|
|
486
495
|
Note:
|
|
487
496
|
|
package/doc/api.md
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
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)
|
|
11
12
|
- [Special measures and attributes names](#special-measures-and-attributes-names)
|
|
12
13
|
- [Entity attributes](#entity-attributes)
|
|
13
|
-
- [Multientity support
|
|
14
|
+
- [Multientity support](#multientity-support)
|
|
14
15
|
- [Metadata support](#metadata-support)
|
|
15
16
|
- [NGSI LD data and metadata considerations](#ngsi-ld-data-and-metadata-considerations)
|
|
16
17
|
- [Advice on Attribute definitions](#advice-on-attribute-definitions)
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
- [Measurement transformation order](#measurement-transformation-order)
|
|
32
33
|
- [Multientity measurement transformation support (`object_id`)](#multientity-measurement-transformation-support-object_id)
|
|
33
34
|
- [Timestamp Processing](#timestamp-processing)
|
|
35
|
+
- [Multimeasure support](#multimeasure-support)
|
|
34
36
|
- [Overriding global Context Broker host](#overriding-global-context-broker-host)
|
|
35
37
|
- [Multitenancy, FIWARE Service and FIWARE ServicePath](#multitenancy-fiware-service-and-fiware-servicepath)
|
|
36
38
|
- [Secured access to the Context Broker](#secured-access-to-the-context-broker)
|
|
@@ -133,9 +135,9 @@ parameters. The specific parameters that can be configured for a given config gr
|
|
|
133
135
|
### Devices
|
|
134
136
|
|
|
135
137
|
A device contains the information that connects a physical device to a particular entity in the Context Broker. Devices
|
|
136
|
-
are identified by a `device_id`, and they are associated to an existing config group based in `
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
are identified by a `device_id`, and they are associated to an existing config group based in `apikey` matching. For
|
|
139
|
+
instance, let's consider a situation in which a config group has been provisioned with `type=X`/`apikey=111` and no
|
|
140
|
+
other config group has been provisioned.
|
|
139
141
|
|
|
140
142
|
The IoT Agents offer a provisioning API where devices can be preregistered, so all the information about service and
|
|
141
143
|
subservice mapping, security information and attribute configuration can be specified in a per device way instead of
|
|
@@ -143,7 +145,7 @@ relaying on the config group configuration. The specific parameters that can be
|
|
|
143
145
|
described in the [Device datamodel](#device-datamodel) section.
|
|
144
146
|
|
|
145
147
|
If devices are not pre-registered, they will be automatically created when a measure arrives to the IoT Agent - this
|
|
146
|
-
process is known as autoprovisioning. The IoT Agent will create an empty device with the group `
|
|
148
|
+
process is known as autoprovisioning. The IoT Agent will create an empty device with the group `apikey` and `type` - the
|
|
147
149
|
associated document created in database doesn't include config group parameters (in particular, `timestamp`,
|
|
148
150
|
`explicitAttrs`, `active` or `attributes`, `static` and `lazy` attributes and commands). The IoT Agent will also create
|
|
149
151
|
the entity in the Context Broker if it does not exist yet.
|
|
@@ -152,6 +154,13 @@ This behavior allows that autoprovisioned parameters can freely established modi
|
|
|
152
154
|
creation using the provisioning API. However, note that if a device (autoprovisioned or not) doesn't have these
|
|
153
155
|
parameters defined at device level in database, the parameters are inherit from config group parameters.
|
|
154
156
|
|
|
157
|
+
### Uniqueness of groups and devices
|
|
158
|
+
|
|
159
|
+
Group service uniqueness is defined by the combination of: service, subservice and apikey
|
|
160
|
+
|
|
161
|
+
Device uniqueness is defined by the combination of: service, subservice, device_id and apikey. Note that several devices
|
|
162
|
+
with the same device_id are allowed in the same service and subservice as long as their apikeys are different.
|
|
163
|
+
|
|
155
164
|
## Special measures and attributes names
|
|
156
165
|
|
|
157
166
|
In case of arriving measures with name `id` or `type`, they are automatically transformed to `measure_id` and
|
|
@@ -278,32 +287,76 @@ e.g.:
|
|
|
278
287
|
|
|
279
288
|
```json
|
|
280
289
|
{
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
{"name": "
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
290
|
+
"entity_type": "Lamp",
|
|
291
|
+
"resource": "/iot/d",
|
|
292
|
+
"protocol": "PDI-IoTA-UltraLight",
|
|
293
|
+
"commands": [
|
|
294
|
+
{ "name": "on", "type": "command" },
|
|
295
|
+
{ "name": "off", "type": "command" }
|
|
296
|
+
],
|
|
297
|
+
"attributes": [
|
|
298
|
+
{ "object_id": "s", "name": "state", "type": "Text" },
|
|
299
|
+
{
|
|
300
|
+
"object_id": "l",
|
|
301
|
+
"name": "luminosity",
|
|
302
|
+
"type": "Integer",
|
|
303
|
+
"metadata": {
|
|
304
|
+
"unitCode": { "type": "Text", "value": "CAL" }
|
|
305
|
+
}
|
|
295
306
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
"
|
|
301
|
-
|
|
302
|
-
|
|
307
|
+
],
|
|
308
|
+
"static_attributes": [
|
|
309
|
+
{ "name": "category", "type": "Text", "value": ["actuator", "sensor"] },
|
|
310
|
+
{
|
|
311
|
+
"name": "controlledProperty",
|
|
312
|
+
"type": "Text",
|
|
313
|
+
"value": ["light"],
|
|
314
|
+
"metadata": {
|
|
315
|
+
"includes": { "type": "Text", "value": ["state", "luminosity"] },
|
|
316
|
+
"alias": { "type": "Text", "value": "lamp" }
|
|
303
317
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Metadata could also has `expression` like attributes in order to expand it:
|
|
324
|
+
|
|
325
|
+
e.g.:
|
|
326
|
+
|
|
327
|
+
```json
|
|
328
|
+
{
|
|
329
|
+
"entity_type": "Lamp",
|
|
330
|
+
"resource": "/iot/d",
|
|
331
|
+
"protocol": "PDI-IoTA-UltraLight",
|
|
332
|
+
"commands": [
|
|
333
|
+
{ "name": "on", "type": "command" },
|
|
334
|
+
{ "name": "off", "type": "command" }
|
|
335
|
+
],
|
|
336
|
+
"attributes": [
|
|
337
|
+
{ "object_id": "s", "name": "state", "type": "Text" },
|
|
338
|
+
{
|
|
339
|
+
"object_id": "l",
|
|
340
|
+
"name": "luminosity",
|
|
341
|
+
"type": "Integer",
|
|
342
|
+
"metadata": {
|
|
343
|
+
"unitCode": { "type": "Text", "value": "CAL" }
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
],
|
|
347
|
+
"static_attributes": [
|
|
348
|
+
{ "name": "category", "type": "Text", "value": ["actuator", "sensor"] },
|
|
349
|
+
{
|
|
350
|
+
"name": "controlledProperty",
|
|
351
|
+
"type": "Text",
|
|
352
|
+
"value": ["light"],
|
|
353
|
+
"metadata": {
|
|
354
|
+
"includes": { "type": "Text", "value": ["state", "luminosity"], "expression": "level / 100" },
|
|
355
|
+
"alias": { "type": "Text", "value": "lamp" }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
]
|
|
359
|
+
}
|
|
307
360
|
```
|
|
308
361
|
|
|
309
362
|
### NGSI-LD data and metadata considerations
|
|
@@ -413,6 +466,8 @@ mappings of the provision. If `explicitAttrs` is provided both at device and con
|
|
|
413
466
|
precedence. Additionally `explicitAttrs` can be used to define which measures (identified by their attribute names, not
|
|
414
467
|
by their object_id) defined in JSON/JEXL array will be propagated to NGSI interface.
|
|
415
468
|
|
|
469
|
+
Note that when `explicitAttrs` is an array or a JEXL expression resulting in to Array, if this array is empty then `TimeInstant` is not propaged to CB.
|
|
470
|
+
|
|
416
471
|
The different possibilities are summarized below:
|
|
417
472
|
|
|
418
473
|
Case 1 (default):
|
|
@@ -517,8 +572,8 @@ expression. In all cases the following data is available to all expressions:
|
|
|
517
572
|
- `subservice`: device subservice
|
|
518
573
|
- `staticAttributes`: static attributes defined in the device or config group
|
|
519
574
|
|
|
520
|
-
Additionally, for attribute expressions (`expression`, `entity_name`)
|
|
521
|
-
**context** used to evaluate them.
|
|
575
|
+
Additionally, for attribute expressions (`expression`, `entity_name`), `entityNameExp` and metadata expressions
|
|
576
|
+
(`expression`) measures are available in the **context** used to evaluate them.
|
|
522
577
|
|
|
523
578
|
### Examples of JEXL expressions
|
|
524
579
|
|
|
@@ -964,32 +1019,162 @@ Will now generate the following NGSI v2 payload:
|
|
|
964
1019
|
|
|
965
1020
|
## Timestamp Processing
|
|
966
1021
|
|
|
967
|
-
|
|
968
|
-
adds a `TimeInstant` attribute as metadata for every other attribute in the same request. With NGSI-LD, the Standard
|
|
969
|
-
`observedAt` property-of-a-property is used instead.
|
|
1022
|
+
Timestamp processing done by IOTA is as follows:
|
|
970
1023
|
|
|
971
|
-
|
|
972
|
-
|
|
1024
|
+
- An attribute `TimeInstant` is added to updated entities
|
|
1025
|
+
- In the case of NGSI-v2, a `TimeInstant` metadata is added in each updated attribute. With NGSI-LD, the Standard
|
|
1026
|
+
`observedAt` property-of-a-property is used instead.
|
|
973
1027
|
|
|
974
1028
|
Depending on the `timestamp` configuration and if the measure contains a value named `TimeInstant` with a correct value,
|
|
975
1029
|
the IoTA behaviour is described in the following table:
|
|
976
1030
|
|
|
977
|
-
| `timestamp` value | measure contains `TimeInstant` | Behaviour |
|
|
978
|
-
|
|
|
979
|
-
| true
|
|
980
|
-
| true
|
|
981
|
-
| false
|
|
982
|
-
| false
|
|
983
|
-
| Not defined
|
|
984
|
-
| Not defined
|
|
1031
|
+
| `timestamp` conf value | measure contains `TimeInstant` | Behaviour |
|
|
1032
|
+
| ---------------------- | ------------------------------ | ------------------------------------------------------ |
|
|
1033
|
+
| true | Yes | TimeInstant and metadata updated with measure value |
|
|
1034
|
+
| true | No | TimeInstant and metadata updated with server timestamp |
|
|
1035
|
+
| false | Yes | TimeInstant and metadata updated with measure value |
|
|
1036
|
+
| false | No | TimeInstant and metadata updated with server timestamp |
|
|
1037
|
+
| Not defined | Yes | TimeInstant and metadata updated with measure value |
|
|
1038
|
+
| Not defined | No | TimeInstant and metadata updated with server timestamp |
|
|
985
1039
|
|
|
986
|
-
The `timestamp` value used is:
|
|
1040
|
+
The `timestamp` conf value used is:
|
|
987
1041
|
|
|
988
1042
|
- The one defined at device level
|
|
989
1043
|
- The one defined at group level (if not defined at device level)
|
|
990
1044
|
- The one defined at [IoTA configuration level](admin.md#timestamp) / `IOTA_TIMESTAMP` env var (if not defined at
|
|
991
1045
|
group level or device level)
|
|
992
1046
|
|
|
1047
|
+
Some additional considerations to take into account:
|
|
1048
|
+
|
|
1049
|
+
- If there is an attribute which maps a measure to `TimeInstant` attribute (after
|
|
1050
|
+
[expression evaluation](#expression-language-support) if any is defined), then that value will be used as
|
|
1051
|
+
`TimeInstant, overwriting the above rules specified in "Behaviour" column. Note that an expression in the could be
|
|
1052
|
+
used in that mapping.
|
|
1053
|
+
- If the resulting `TimeInstant` not follows [ISO_8601](https://en.wikipedia.org/wiki/ISO_8601) (either from a direct
|
|
1054
|
+
measure of after a mapping, as described in the previous bullet) then it is refused (so a failover to server
|
|
1055
|
+
timestamp will take place).
|
|
1056
|
+
|
|
1057
|
+
## Multimeasure support
|
|
1058
|
+
|
|
1059
|
+
A device could receive several measures at the same time.
|
|
1060
|
+
|
|
1061
|
+
For example:
|
|
1062
|
+
|
|
1063
|
+
```json
|
|
1064
|
+
[
|
|
1065
|
+
{
|
|
1066
|
+
"vol": 0
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
"vol": 1
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
"vol": 2
|
|
1073
|
+
}
|
|
1074
|
+
]
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
In this case a batch update (`POST /v2/op/update`) to CB will be generated with the following NGSI v2 payload:
|
|
1078
|
+
|
|
1079
|
+
```json
|
|
1080
|
+
{
|
|
1081
|
+
"actionType": "append",
|
|
1082
|
+
"entities": [
|
|
1083
|
+
{
|
|
1084
|
+
"id": "ws",
|
|
1085
|
+
"type": "WeatherStation",
|
|
1086
|
+
"vol": {
|
|
1087
|
+
"type": "Number",
|
|
1088
|
+
"value": 0
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"id": "ws",
|
|
1093
|
+
"type": "WeatherStation",
|
|
1094
|
+
"vol": {
|
|
1095
|
+
"type": "Number",
|
|
1096
|
+
"value": 1
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
"id": "ws",
|
|
1101
|
+
"type": "WeatherStation",
|
|
1102
|
+
"vol": {
|
|
1103
|
+
"type": "Number",
|
|
1104
|
+
"value": 1
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
]
|
|
1108
|
+
}
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
Moreover if a multimeasure contains TimeInstant attribute, then CB update is sorted by attribute TimeInstant:
|
|
1112
|
+
|
|
1113
|
+
For example:
|
|
1114
|
+
|
|
1115
|
+
```json
|
|
1116
|
+
[
|
|
1117
|
+
{
|
|
1118
|
+
"vol": 0,
|
|
1119
|
+
"TimeInstant": "2024-04-10T10:15:00Z"
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
"vol": 1,
|
|
1123
|
+
"TimeInstant": "2024-04-10T10:10:00Z"
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
"vol": 2,
|
|
1127
|
+
"TimeInstant": "2024-04-10T10:05:00Z"
|
|
1128
|
+
}
|
|
1129
|
+
]
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
In this case a batch update (`POST /v2/op/update`) to CB will be generated with the following NGSI v2 payload:
|
|
1133
|
+
|
|
1134
|
+
```json
|
|
1135
|
+
{
|
|
1136
|
+
"actionType": "append",
|
|
1137
|
+
"entities": [
|
|
1138
|
+
{
|
|
1139
|
+
"id": "ws",
|
|
1140
|
+
"type": "WeatherStation",
|
|
1141
|
+
"vol": {
|
|
1142
|
+
"type": "Number",
|
|
1143
|
+
"value": 2
|
|
1144
|
+
},
|
|
1145
|
+
"TimeInstant": {
|
|
1146
|
+
"type": "DateTime",
|
|
1147
|
+
"value": "2024-04-10T10:05:00Z"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
"id": "ws",
|
|
1152
|
+
"type": "WeatherStation",
|
|
1153
|
+
"vol": {
|
|
1154
|
+
"type": "Number",
|
|
1155
|
+
"value": 1
|
|
1156
|
+
},
|
|
1157
|
+
"TimeInstant": {
|
|
1158
|
+
"type": "DateTime",
|
|
1159
|
+
"value": "2024-04-10T10:10:00Z"
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
"id": "ws",
|
|
1164
|
+
"type": "WeatherStation",
|
|
1165
|
+
"vol": {
|
|
1166
|
+
"type": "Number",
|
|
1167
|
+
"value": 0
|
|
1168
|
+
},
|
|
1169
|
+
"TimeInstant": {
|
|
1170
|
+
"type": "DateTime",
|
|
1171
|
+
"value": "2024-04-10T10:15:00Z"
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
]
|
|
1175
|
+
}
|
|
1176
|
+
```
|
|
1177
|
+
|
|
993
1178
|
## Overriding global Context Broker host
|
|
994
1179
|
|
|
995
1180
|
**cbHost**: Context Broker host URL. This option can be used to override the global CB configuration for specific types
|
package/doc/requirements.txt
CHANGED
package/lib/commonConfig.js
CHANGED
|
@@ -156,7 +156,8 @@ function processEnvironmentVariables() {
|
|
|
156
156
|
'IOTA_FALLBACK_TENANT',
|
|
157
157
|
'IOTA_FALLBACK_PATH',
|
|
158
158
|
'IOTA_LD_SUPPORT_NULL',
|
|
159
|
-
'IOTA_LD_SUPPORT_DATASET_ID'
|
|
159
|
+
'IOTA_LD_SUPPORT_DATASET_ID',
|
|
160
|
+
'IOTA_EXPRESS_LIMIT'
|
|
160
161
|
];
|
|
161
162
|
const iotamVariables = [
|
|
162
163
|
'IOTA_IOTAM_URL',
|
|
@@ -468,6 +469,11 @@ function processEnvironmentVariables() {
|
|
|
468
469
|
? config.defaultEntityNameConjunction
|
|
469
470
|
: ':';
|
|
470
471
|
}
|
|
472
|
+
if (process.env.IOTA_EXPRESS_LIMIT) {
|
|
473
|
+
config.expressLimit = process.env.IOTA_EXPRESS_LIMIT;
|
|
474
|
+
} else {
|
|
475
|
+
config.expressLimit = config.expressLimit ? config.expressLimit : '1mb';
|
|
476
|
+
}
|
|
471
477
|
}
|
|
472
478
|
|
|
473
479
|
function setConfig(newConfig) {
|
|
@@ -485,6 +491,23 @@ function getConfig() {
|
|
|
485
491
|
return config;
|
|
486
492
|
}
|
|
487
493
|
|
|
494
|
+
function getConfigForTypeInformation() {
|
|
495
|
+
// Just return relevant configuration flags
|
|
496
|
+
// avoid to include server, authentication, mongodb, orion and iotamanger info
|
|
497
|
+
let conf = {
|
|
498
|
+
timestamp: config.timestamp,
|
|
499
|
+
defaultResource: config.defaultResource,
|
|
500
|
+
explicitAttrs: config.explicitAttrs,
|
|
501
|
+
pollingExpiration: config.pollingExpiration,
|
|
502
|
+
pollingDaemonFrequency: config.pollingDaemonFrequency,
|
|
503
|
+
multiCore: config.multiCore,
|
|
504
|
+
relaxTemplateValidation: config.relaxTemplateValidation,
|
|
505
|
+
defaultEntityNameConjunction: config.defaultEntityNameConjunction,
|
|
506
|
+
defaultType: config.defaultType
|
|
507
|
+
};
|
|
508
|
+
return conf;
|
|
509
|
+
}
|
|
510
|
+
|
|
488
511
|
function setRegistry(newRegistry) {
|
|
489
512
|
registry = newRegistry;
|
|
490
513
|
}
|
|
@@ -541,6 +564,7 @@ function getSecurityService() {
|
|
|
541
564
|
|
|
542
565
|
exports.setConfig = setConfig;
|
|
543
566
|
exports.getConfig = getConfig;
|
|
567
|
+
exports.getConfigForTypeInformation = getConfigForTypeInformation;
|
|
544
568
|
exports.setRegistry = setRegistry;
|
|
545
569
|
exports.getRegistry = getRegistry;
|
|
546
570
|
exports.setGroupRegistry = setGroupRegistry;
|
package/lib/errors.js
CHANGED
|
@@ -107,7 +107,10 @@ class DuplicateDeviceId {
|
|
|
107
107
|
constructor(device) {
|
|
108
108
|
this.name = 'DUPLICATE_DEVICE_ID';
|
|
109
109
|
this.message =
|
|
110
|
-
'A device with the same
|
|
110
|
+
'A device with the same info (DeviceId, ApiKey, Service, Subservice) was found:' +
|
|
111
|
+
device.id +
|
|
112
|
+
' and ' +
|
|
113
|
+
JSON.stringify(device);
|
|
111
114
|
this.code = 409;
|
|
112
115
|
}
|
|
113
116
|
}
|
|
@@ -176,7 +176,7 @@ function getByName(name, service, subservice, callback) {
|
|
|
176
176
|
getByNameAndType(name, null, service, subservice, callback);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
function update(device, callback) {
|
|
179
|
+
function update(previousDevice, device, callback) {
|
|
180
180
|
registeredDevices[device.service][device.id] = deepClone(device);
|
|
181
181
|
callback(null, device);
|
|
182
182
|
}
|
|
@@ -243,14 +243,7 @@ function getDeviceById(id, apikey, service, subservice, callback) {
|
|
|
243
243
|
function getDevice(id, apikey, service, subservice, callback) {
|
|
244
244
|
getDeviceById(id, apikey, service, subservice, function (error, data) {
|
|
245
245
|
if (error) {
|
|
246
|
-
|
|
247
|
-
getDeviceById(id, null, service, subservice, function (error, data) {
|
|
248
|
-
if (error) {
|
|
249
|
-
callback(error);
|
|
250
|
-
} else {
|
|
251
|
-
callback(null, data);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
246
|
+
callback(error);
|
|
254
247
|
} else {
|
|
255
248
|
callback(null, data);
|
|
256
249
|
}
|
|
@@ -297,9 +290,9 @@ function getByName(name, service, servicepath, callback) {
|
|
|
297
290
|
*
|
|
298
291
|
* @param {Object} device Device object with the new values to write.
|
|
299
292
|
*/
|
|
300
|
-
function update(device, callback) {
|
|
293
|
+
function update(previousDevice, device, callback) {
|
|
301
294
|
logger.debug(context, 'Storing updated values for device [%s]:\n%s', device.id, JSON.stringify(device, null, 4));
|
|
302
|
-
getDevice(device.id,
|
|
295
|
+
getDevice(device.id, previousDevice.apikey, device.service, device.subservice, function (error, data) {
|
|
303
296
|
if (error) {
|
|
304
297
|
callback(error);
|
|
305
298
|
} else {
|
|
@@ -444,8 +444,8 @@ function unregisterDevice(id, apikey, service, subservice, callback) {
|
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
function updateRegisterDevice(deviceObj, entityInfoUpdated, callback) {
|
|
448
|
-
deviceHandler.updateRegisterDevice(deviceObj, entityInfoUpdated, callback);
|
|
447
|
+
function updateRegisterDevice(deviceObj, previousDevice, entityInfoUpdated, callback) {
|
|
448
|
+
deviceHandler.updateRegisterDevice(deviceObj, previousDevice, entityInfoUpdated, callback);
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
/**
|
|
@@ -518,7 +518,8 @@ function getDevice(deviceId, apikey, service, subservice, callback) {
|
|
|
518
518
|
* @param {String} device JSON object contain the device to update.
|
|
519
519
|
*/
|
|
520
520
|
function updateDevice(device, callback) {
|
|
521
|
-
|
|
521
|
+
logger.debug(context, 'updateDevice %j', device);
|
|
522
|
+
config.getRegistry().update(device, device, callback);
|
|
522
523
|
}
|
|
523
524
|
|
|
524
525
|
/**
|
|
@@ -615,6 +616,7 @@ function findOrCreate(deviceId, apikey, group, callback) {
|
|
|
615
616
|
} else if (error.name === 'DEVICE_NOT_FOUND') {
|
|
616
617
|
const newDevice = {
|
|
617
618
|
id: deviceId,
|
|
619
|
+
apikey: apikey,
|
|
618
620
|
service: group.service,
|
|
619
621
|
subservice: group.subservice,
|
|
620
622
|
type: group.type
|
|
@@ -182,7 +182,7 @@ function updateEntityNgsiLD(deviceData, updatedDevice, callback) {
|
|
|
182
182
|
*
|
|
183
183
|
* @param {Object} deviceObj Object with all the device information (mandatory).
|
|
184
184
|
*/
|
|
185
|
-
function updateRegisterDeviceNgsiLD(deviceObj, entityInfoUpdated, callback) {
|
|
185
|
+
function updateRegisterDeviceNgsiLD(deviceObj, previousDevice, entityInfoUpdated, callback) {
|
|
186
186
|
if (!deviceObj.id || !deviceObj.type) {
|
|
187
187
|
callback(new errors.MissingAttributes('Id or device missing', deviceObj));
|
|
188
188
|
return;
|
|
@@ -280,7 +280,7 @@ function updateRegisterDeviceNgsiLD(deviceObj, entityInfoUpdated, callback) {
|
|
|
280
280
|
apply(
|
|
281
281
|
config.getRegistry().get,
|
|
282
282
|
deviceObj.id,
|
|
283
|
-
|
|
283
|
+
previousDevice.apikey,
|
|
284
284
|
deviceObj.service,
|
|
285
285
|
deviceObj.subservice
|
|
286
286
|
),
|
|
@@ -289,7 +289,7 @@ function updateRegisterDeviceNgsiLD(deviceObj, entityInfoUpdated, callback) {
|
|
|
289
289
|
apply(combineWithNewDevice, deviceObj),
|
|
290
290
|
apply(registrationUtils.sendRegistrations, false),
|
|
291
291
|
apply(registrationUtils.processContextRegistration, deviceObj),
|
|
292
|
-
config.getRegistry().update
|
|
292
|
+
apply(config.getRegistry().update, previousDevice)
|
|
293
293
|
],
|
|
294
294
|
callback
|
|
295
295
|
);
|
|
@@ -299,7 +299,7 @@ function updateRegisterDeviceNgsiLD(deviceObj, entityInfoUpdated, callback) {
|
|
|
299
299
|
apply(
|
|
300
300
|
config.getRegistry().get,
|
|
301
301
|
deviceObj.id,
|
|
302
|
-
|
|
302
|
+
previousDevice.apikey,
|
|
303
303
|
deviceObj.service,
|
|
304
304
|
deviceObj.subservice
|
|
305
305
|
),
|
|
@@ -308,7 +308,7 @@ function updateRegisterDeviceNgsiLD(deviceObj, entityInfoUpdated, callback) {
|
|
|
308
308
|
apply(combineWithNewDevice, deviceObj),
|
|
309
309
|
apply(registrationUtils.sendRegistrations, false),
|
|
310
310
|
apply(registrationUtils.processContextRegistration, deviceObj),
|
|
311
|
-
config.getRegistry().update
|
|
311
|
+
apply(config.getRegistry().update, previousDevice)
|
|
312
312
|
],
|
|
313
313
|
callback
|
|
314
314
|
);
|
|
@@ -38,11 +38,11 @@ const deviceHandlerV2 = require('./devices-NGSI-v2');
|
|
|
38
38
|
*
|
|
39
39
|
* @param {Object} deviceObj Object with all the device information (mandatory).
|
|
40
40
|
*/
|
|
41
|
-
function updateRegisterDeviceNgsiMixed(deviceObj, entityInfoUpdated, callback) {
|
|
41
|
+
function updateRegisterDeviceNgsiMixed(deviceObj, previousDevice, entityInfoUpdated, callback) {
|
|
42
42
|
if (config.checkNgsiLD(deviceObj)) {
|
|
43
|
-
deviceHandlerLD.updateRegisterDevice(deviceObj, entityInfoUpdated, callback);
|
|
43
|
+
deviceHandlerLD.updateRegisterDevice(deviceObj, previousDevice, entityInfoUpdated, callback);
|
|
44
44
|
} else {
|
|
45
|
-
deviceHandlerV2.updateRegisterDevice(deviceObj, entityInfoUpdated, callback);
|
|
45
|
+
deviceHandlerV2.updateRegisterDevice(deviceObj, previousDevice, entityInfoUpdated, callback);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -247,7 +247,7 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) {
|
|
|
247
247
|
*
|
|
248
248
|
* @param {Object} deviceObj Object with all the device information (mandatory).
|
|
249
249
|
*/
|
|
250
|
-
function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
250
|
+
function updateRegisterDeviceNgsi2(deviceObj, previousDevice, entityInfoUpdated, callback) {
|
|
251
251
|
if (!deviceObj.id || !deviceObj.type) {
|
|
252
252
|
callback(new errors.MissingAttributes('Id or device missing', deviceObj));
|
|
253
253
|
return;
|
|
@@ -352,7 +352,7 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
|
352
352
|
apply(
|
|
353
353
|
config.getRegistry().get,
|
|
354
354
|
deviceObj.id,
|
|
355
|
-
|
|
355
|
+
previousDevice.apikey, // it could be updated
|
|
356
356
|
deviceObj.service,
|
|
357
357
|
deviceObj.subservice
|
|
358
358
|
),
|
|
@@ -361,7 +361,7 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
|
361
361
|
apply(combineWithNewDevice, deviceObj),
|
|
362
362
|
apply(registrationUtils.sendRegistrations, false),
|
|
363
363
|
apply(registrationUtils.processContextRegistration, deviceObj),
|
|
364
|
-
config.getRegistry().update
|
|
364
|
+
apply(config.getRegistry().update, previousDevice)
|
|
365
365
|
],
|
|
366
366
|
callback
|
|
367
367
|
);
|
|
@@ -371,7 +371,7 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
|
371
371
|
apply(
|
|
372
372
|
config.getRegistry().get,
|
|
373
373
|
deviceObj.id,
|
|
374
|
-
|
|
374
|
+
previousDevice.apikey,
|
|
375
375
|
deviceObj.service,
|
|
376
376
|
deviceObj.subservice
|
|
377
377
|
),
|
|
@@ -380,7 +380,7 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
|
380
380
|
apply(combineWithNewDevice, deviceObj),
|
|
381
381
|
apply(registrationUtils.sendRegistrations, false),
|
|
382
382
|
apply(registrationUtils.processContextRegistration, deviceObj),
|
|
383
|
-
config.getRegistry().update
|
|
383
|
+
apply(config.getRegistry().update, previousDevice)
|
|
384
384
|
],
|
|
385
385
|
callback
|
|
386
386
|
);
|