iotagent-node-lib 4.0.1 → 4.2.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.
@@ -45,7 +45,7 @@ jobs:
45
45
  runs-on: ubuntu-latest
46
46
  services:
47
47
  mongodb:
48
- image: mongo:4.2
48
+ image: mongo:6.0
49
49
  ports:
50
50
  - 27017:27017
51
51
  strategy:
@@ -72,7 +72,7 @@ jobs:
72
72
  needs: unit-test
73
73
  services:
74
74
  mongodb:
75
- image: mongo:4.2
75
+ image: mongo:6.0
76
76
  ports:
77
77
  - 27017:27017
78
78
  steps:
package/.readthedocs.yml CHANGED
@@ -3,7 +3,11 @@ version: 2
3
3
  mkdocs:
4
4
  configuration: mkdocs.yml
5
5
 
6
+ build:
7
+ os: ubuntu-22.04
8
+ tools:
9
+ python: "3.8"
10
+
6
11
  python:
7
- version: 3.8
8
12
  install:
9
13
  - requirements: doc/requirements.txt
File without changes
package/doc/api.md CHANGED
@@ -450,7 +450,7 @@ propagated to NGSI interface (note that in this case the value of `explicitAttrs
450
450
  that looks likes a JSON). This is necessary when same attribute names are used within multiple entities. Only static
451
451
  attributes included in that array will be propagated to NGSI interface.
452
452
 
453
- Note that in the previous case show above, when selecting the object_id (with `{object_id:'active_id'}`), the attribute
453
+ Note that in the previous case show above, when selecting the object_id (with `{object_id:'active_id'}`), the attribute
454
454
  must be defined. In other words, it would not work if the attribute with the corresponding `object_id`, is not defined.
455
455
 
456
456
  Case 5:
@@ -955,6 +955,28 @@ The IOTA processes the entity attributes looking for a `TimeInstant` attribute.
955
955
  adds a `TimeInstant` attribute as metadata for every other attribute in the same request. With NGSI-LD, the Standard
956
956
  `observedAt` property-of-a-property is used instead.
957
957
 
958
+ If a `TimeInstant` arrives as measure but not follows [ISO_8601](https://en.wikipedia.org/wiki/ISO_8601) then measure
959
+ is refused.
960
+
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:
964
+
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
973
+
974
+ The `timestamp` value used is:
975
+
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)
979
+
958
980
  ## Overriding global Context Broker host
959
981
 
960
982
  **cbHost**: Context Broker host URL. This option can be used to override the global CB configuration for specific types
@@ -963,8 +985,7 @@ of devices.
963
985
  ## Multitenancy, FIWARE Service and FIWARE ServicePath
964
986
 
965
987
  Every operation in the API require the `fiware-service` and `fiware-servicepath` to be defined; the operations are
966
- performed in the scope of those headers. For the list case, the special wildcard servicepath can be specified, `/*`. In
967
- this case, the operation applies to all the subservices of the service given by the `fiware-service` header.
988
+ performed in the scope of those headers.
968
989
 
969
990
  ## Secured access to the Context Broker
970
991
 
@@ -1202,7 +1223,7 @@ Config group is represented by a JSON object with the following fields:
1202
1223
  | `subservice` | | string | | Subservice of the devices of this type. |
1203
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). |
1204
1225
  | `apikey` | | string | | API Key string. |
1205
- | `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 timestamp. With NGSI-LD, the Standard `observedAt` property-of-a-property is created instead. |
1226
+ | `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. |
1206
1227
  | `entity_type` | | string | | name of the Entity `type` to assign to the group. |
1207
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). |
1208
1229
  | `cbHost` | ✓ | string | | Context Broker connection information. This options can be used to override the global ones for specific types of devices. |
@@ -1217,6 +1238,8 @@ Config group is represented by a JSON object with the following fields:
1217
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. |
1218
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`. |
1219
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. |
1220
1243
 
1221
1244
  ### Config group operations
1222
1245
 
@@ -1224,9 +1247,8 @@ The following actions are available under the config group endpoint:
1224
1247
 
1225
1248
  #### Retrieve config groups `GET /iot/services`
1226
1249
 
1227
- List all the config groups for the given `fiware-service` and `fiware-servicepath`. If the `fiware-servicepath` header
1228
- has the wildcard expression, `/*`, all the config groups for that `fiware-service` are returned. The config groups that
1229
- match the `fiware-servicepath` are returned in any other case.
1250
+ List all the config groups for the given `fiware-service` and `fiware-servicepath`. The config groups that match the
1251
+ `fiware-servicepath` are returned in any other case.
1230
1252
 
1231
1253
  _**Request headers**_
1232
1254
 
@@ -1425,7 +1447,7 @@ the API resource fields and the same fields in the database model.
1425
1447
  | `entity_name` | | `string` | | Name of the entity representing the device in the Context Broker |
1426
1448
  | `entity_type` | | `string` | | Type of the entity in the Context Broker |
1427
1449
  | `timezone` | ✓ | `string` | | Timezone of the device if that has any |
1428
- | `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 timestamp. With NGSI-LD, the Standard `observedAt` property-of-a-property is created instead. |
1450
+ | `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. |
1429
1451
  | `apikey` | ✓ | `string` | | Apikey key string to use instead of group apikey |
1430
1452
  | `endpoint` | ✓ | `string` | | Endpoint where the device is going to receive commands, if any. |
1431
1453
  | `protocol` | ✓ | `string` | | Pame of the device protocol, for its use with an IoT Manager |
@@ -1,4 +1,4 @@
1
- mkdocs==1.2.3
1
+ mkdocs==1.2.4
2
2
  Pygments==2.15.0
3
3
  Markdown==3.3.4
4
- jinja2==3.0.0
4
+ jinja2==3.1.3
@@ -1,4 +1,4 @@
1
- ARG IMAGE_TAG=12.1-slim
1
+ ARG IMAGE_TAG=12.4-slim
2
2
  FROM debian:${IMAGE_TAG}
3
3
 
4
4
  ARG CLEAN_DEV_TOOLS
@@ -3,6 +3,6 @@ version: '3'
3
3
  services:
4
4
 
5
5
  mongo:
6
- image: mongo:4.4
6
+ image: mongo:6.0.12
7
7
  ports:
8
8
  - "27017:27017"
package/lib/constants.js CHANGED
@@ -61,6 +61,7 @@ module.exports = {
61
61
  NGSI_LD_TENANT_HEADER: 'NGSILD-Tenant',
62
62
  NGSI_LD_PATH_HEADER: 'NGSILD-Path',
63
63
  NGSI_LD_NULL: 'urn:ngsi-ld:null',
64
+ MEASURE: 'measure_',
64
65
  //FIXME: check Keystone support this in lowercase, then change
65
66
  AUTH_HEADER: 'X-Auth-Token',
66
67
  X_FORWARDED_FOR_HEADER: 'x-forwarded-for',
@@ -83,7 +84,7 @@ module.exports = {
83
84
  MONGO_ALARM: 'MONGO-ALARM',
84
85
  ORION_ALARM: 'ORION-ALARM',
85
86
  IOTAM_ALARM: 'IOTAM-ALARM',
86
-
87
+
87
88
  ATTRIBUTE_DEFAULT,
88
89
  DATETIME_DEFAULT,
89
90
 
@@ -308,6 +308,7 @@ exports.getDeviceByName = deviceService.getDeviceByName;
308
308
  exports.getDeviceByNameAndType = deviceService.getDeviceByNameAndType;
309
309
  exports.getDevicesByAttribute = deviceService.getDevicesByAttribute;
310
310
  exports.mergeDeviceWithConfiguration = deviceService.mergeDeviceWithConfiguration;
311
+ exports.findOrCreate = deviceService.findOrCreate;
311
312
  exports.retrieveDevice = deviceService.retrieveDevice;
312
313
  exports.getConfiguration = groupConfig.get;
313
314
  exports.getConfigurationSilently = groupConfig.getSilently;
@@ -45,6 +45,8 @@ const Group = new Schema({
45
45
  url: String,
46
46
  resource: String,
47
47
  apikey: String,
48
+ endpoint: String,
49
+ transport: String,
48
50
  type: String,
49
51
  service: { type: String, lowercase: true },
50
52
  subservice: String,
@@ -61,7 +61,9 @@ function register(callback) {
61
61
  defaultEntityNameConjunction: service.defaultEntityNameConjunction,
62
62
  ngsiVersion: service.ngsiVersion,
63
63
  entityNameExp: service.entityNameExp,
64
- payloadType: service.payloadType
64
+ payloadType: service.payloadType,
65
+ endpoint: service.endpoint,
66
+ transport: service.transport
65
67
  };
66
68
  }
67
69
 
@@ -309,6 +309,7 @@ function update(device, callback) {
309
309
  data.internalAttributes = device.internalAttributes;
310
310
  data.commands = device.commands;
311
311
  data.endpoint = device.endpoint;
312
+ data.transport = device.transport;
312
313
  data.polling = device.polling;
313
314
  data.name = device.name;
314
315
  data.type = device.type;
@@ -352,7 +352,7 @@ function registerDevice(deviceObj, callback) {
352
352
  deviceObj.subservice = deviceData.subservice;
353
353
  deviceObj.type = deviceData.type;
354
354
  deviceObj.staticAttributes = deviceObj.staticAttributes ? deviceObj.staticAttributes : [];
355
- deviceObj.commands = deviceObj.commands ? deviceObj.commands : [];
355
+ deviceObj.commands = deviceData.commands ? deviceData.commands : [];
356
356
  deviceObj.lazy = deviceObj.lazy ? deviceObj.lazy : [];
357
357
  if ('apikey' in deviceData && deviceData.apikey !== undefined) {
358
358
  deviceObj.apikey = deviceData.apikey;
@@ -677,7 +677,7 @@ function retrieveDevice(deviceId, apiKey, callback) {
677
677
  } else {
678
678
  async.waterfall(
679
679
  [
680
- apply(groupService.get, config.getConfig().defaultResource || '', apiKey),
680
+ apply(groupService.getSilently, config.getConfig().defaultResource || '', apiKey),
681
681
  apply(findOrCreate, deviceId, apiKey),
682
682
  apply(
683
683
  mergeDeviceWithConfiguration,
@@ -704,5 +704,6 @@ exports.unregister = intoTrans(context, unregisterDevice);
704
704
  exports.clearRegistry = intoTrans(context, checkRegistry)(clearRegistry);
705
705
  exports.retrieveDevice = intoTrans(context, checkRegistry)(retrieveDevice);
706
706
  exports.mergeDeviceWithConfiguration = mergeDeviceWithConfiguration;
707
+ exports.findOrCreate = findOrCreate;
707
708
  exports.findConfigurationGroup = findConfigurationGroup;
708
709
  exports.init = init;
@@ -273,7 +273,12 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
273
273
  if ('payloadType' in newDevice && newDevice.payloadType !== undefined) {
274
274
  oldDevice.payloadType = newDevice.payloadType;
275
275
  }
276
- oldDevice.endpoint = newDevice.endpoint || oldDevice.endpoint;
276
+ if ('endpoint' in newDevice && newDevice.endpoint !== undefined) {
277
+ oldDevice.endpoint = newDevice.endpoint;
278
+ }
279
+ if ('transport' in newDevice && newDevice.transport !== undefined) {
280
+ oldDevice.transport = newDevice.transport;
281
+ }
277
282
 
278
283
  callback(null, oldDevice);
279
284
  } else {
@@ -61,7 +61,7 @@ function createGroup(group, callback) {
61
61
 
62
62
  logger.debug(
63
63
  context,
64
- 'Storing device group for service [%s] and subservice [%s]',
64
+ 'Storing device group id %s for service [%s] and subservice [%s]',
65
65
  storeGroup._id,
66
66
  storeGroup.service,
67
67
  storeGroup.subservice
@@ -144,6 +144,7 @@ function find(service, subservice, callback) {
144
144
  }
145
145
 
146
146
  if (result.length > 0) {
147
+ logger.debug(context, 'groups found %j', result);
147
148
  return callback(null, {
148
149
  count: result.length,
149
150
  services: result
@@ -169,7 +170,7 @@ function findBy(fields) {
169
170
  /* eslint-disable-next-line prefer-rest-params */
170
171
  const callback = arguments[i];
171
172
 
172
- logger.debug(context, 'Looking for device params %j', fields);
173
+ logger.debug(context, 'Looking for group with params %j', fields);
173
174
 
174
175
  for (const p in registeredGroups) {
175
176
  if (registeredGroups.hasOwnProperty(p)) {
@@ -189,6 +190,7 @@ function findBy(fields) {
189
190
  }
190
191
 
191
192
  if (result) {
193
+ logger.debug(context, 'group found %j', result);
192
194
  callback(null, result);
193
195
  } else {
194
196
  callback(new errors.DeviceGroupNotFound('n/a', 'n/a'));
@@ -211,6 +213,7 @@ function getSingleGroup(resource, apikey, callback) {
211
213
  }
212
214
 
213
215
  if (result) {
216
+ logger.debug(context, 'single group found %j', result);
214
217
  callback(null, result);
215
218
  } else {
216
219
  callback(new errors.DeviceGroupNotFound(resource, apikey));
@@ -228,6 +231,7 @@ function getSingleGroupType(type, callback) {
228
231
  }
229
232
 
230
233
  if (result) {
234
+ logger.debug(context, 'single group type found %j', result);
231
235
  callback(null, result);
232
236
  } else {
233
237
  callback(new errors.DeviceGroupNotFound(type));
@@ -243,7 +247,7 @@ function update(id, body, callback) {
243
247
  groupToModify[i] = body[i];
244
248
  }
245
249
  }
246
-
250
+ logger.debug(context, 'groupd to update %j', groupToModify);
247
251
  callback(null, groupToModify);
248
252
  } else {
249
253
  callback(new errors.DeviceGroupNotFound(id));
@@ -262,8 +266,8 @@ exports.list = intoTrans(context, listGroups);
262
266
  exports.init = intoTrans(context, init);
263
267
  exports.find = intoTrans(context, find);
264
268
  exports.findBy = intoTrans(context, findBy);
265
- exports.findType = intoTrans(context, findBy(['service', 'subservice', 'type']));
266
- exports.findTypeSilently = intoTrans(context, findBy(['service', 'subservice', 'type']));
269
+ exports.findType = intoTrans(context, findBy(['service', 'subservice', 'type', 'apikey']));
270
+ exports.findTypeSilently = intoTrans(context, findBy(['service', 'subservice', 'type', 'apikey']));
267
271
  exports.findSilently = intoTrans(context, findBy(['service', 'subservice']));
268
272
  exports.get = intoTrans(context, getSingleGroup);
269
273
  exports.getSilently = intoTrans(context, getSingleGroup);
@@ -41,6 +41,8 @@ const attributeList = [
41
41
  'resource',
42
42
  'apikey',
43
43
  'type',
44
+ 'endpoint',
45
+ 'transport',
44
46
  'service',
45
47
  'subservice',
46
48
  'description',
@@ -282,6 +282,12 @@ function sendUpdateValueNgsi2(entityName, measures, typeInformation, token, call
282
282
  callback(new errors.TypeNotFound(null, entityName));
283
283
  return;
284
284
  }
285
+ //Rename all measures with matches with id and type to measure_id and measure_type
286
+ for (let measure of measures) {
287
+ if (measure.name === 'id' || measure.name === 'type') {
288
+ measure.name = constants.MEASURE + measure.name;
289
+ }
290
+ }
285
291
 
286
292
  //Make a copy of measures in an plain object: plainMeasures
287
293
  plainMeasures = reduceAttrToPlainObject(measures);
@@ -541,7 +547,6 @@ function sendUpdateValueNgsi2(entityName, measures, typeInformation, token, call
541
547
  //extract attributes
542
548
  let isEmpty = true;
543
549
  for (let attr of entities[ename][etype]) {
544
- //Handling id/type measures, skip, hit & explicit (condition)
545
550
  if (
546
551
  attr.name !== 'id' &&
547
552
  attr.name !== 'type' &&
@@ -32,6 +32,10 @@
32
32
  "description": "Protocol the device is using to communicate with the platform",
33
33
  "type": "string"
34
34
  },
35
+ "endpoint": {
36
+ "description": "Endpoint for the commands targeting this device",
37
+ "type": "string"
38
+ },
35
39
  "transport": {
36
40
  "description": "Transport protocol used by the platform to communicate with the device",
37
41
  "type": "string"
@@ -32,6 +32,10 @@
32
32
  "description": "Protocol the device is using to communicate with the platform",
33
33
  "type": "string"
34
34
  },
35
+ "endpoint": {
36
+ "description": "Endpoint for the commands targeting this device",
37
+ "type": "string"
38
+ },
35
39
  "transport": {
36
40
  "description": "Transport protocol used by the platform to communicate with the device",
37
41
  "type": "string"
@@ -20,6 +20,14 @@
20
20
  "type": "string",
21
21
  "required": true
22
22
  },
23
+ "endpoint": {
24
+ "description": "Endpoint for the commands targeting this group",
25
+ "type": "string"
26
+ },
27
+ "transport": {
28
+ "description": "Transport protocol used by the platform to communicate with the device",
29
+ "type": "string"
30
+ },
23
31
  "token": {
24
32
  "description": "token",
25
33
  "type": "string"
@@ -33,6 +33,10 @@
33
33
  "description": "Endpoint for the commands targeting this device",
34
34
  "type": "string"
35
35
  },
36
+ "transport": {
37
+ "description": "Transport protocol used by the platform to communicate with the device",
38
+ "type": "string"
39
+ },
36
40
  "lazy": {
37
41
  "description": "list of lazy attributes of the devices",
38
42
  "type": "array",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "iotagent-node-lib",
3
3
  "license": "AGPL-3.0-only",
4
4
  "description": "IoT Agent library to interface with NGSI Context Broker",
5
- "version": "4.0.1",
5
+ "version": "4.2.0",
6
6
  "homepage": "https://github.com/telefonicaid/iotagent-node-lib",
7
7
  "keywords": [
8
8
  "fiware",
@@ -30,10 +30,10 @@ test cases are automatically generated. Each test case is defined as an object w
30
30
  - `json`: The JSON object that defines the group
31
31
  - `headers`: The headers to send to the provisioning API. This should contain the `fiware-service` and
32
32
  `fiware-servicepath` headers.
33
- - `skip`: optional. If set to `true`, the test case (`describe`) will be skipped. This is useful to skip test
34
- cases that are not supported by the agent. It can also have a string value `"lib"`. This will skip the test case
35
- only if the is executed in the IoTA Node lib repo. This is useful to skip test cases that are not supported by
36
- the lib (I.E: all tests related to the transport).
33
+ - `skip`: optional. Allow to skip test cases (at `describe` level). It allows diferent values: `false` (default, meaning that the test is not skipped in any circustance),
34
+ `true` (meaning the test is always skipped), `"lib"` (meaning the test has to be skipped when running it in IoTA Node lib repo) and
35
+ `"json"` (meaning the test has to be skipped when running it in IOTA JSON repo). The latter alternatives are useful to skip test cases that are not supported by
36
+ the lib (I.E: all tests related to the transport) or by the IOTA. Combinations (e.g `"lib,json"`) and negation (e.g. `"!lib"`) are also supported.
37
37
  - `should`: The array of test cases to execute. Each test case is defined as an object with the following elements:
38
38
  - `transport`: The transport to use to send the measure. This can be `HTTP` or `MQTT`. It uses `HTTP` by default
39
39
  or if the `transport` element is not defined. See the "Advanced features" section for more information.
@@ -88,7 +88,7 @@ describe('FUNCTIONAL TESTS AUTO', function () {
88
88
 
89
89
  testCase.should.forEach((should) => {
90
90
  it(should.shouldName, async function () {
91
- if (testCase.skip && testUtils.checkSkip(testCase.skip, 'lib')) {
91
+ if (should.skip && testUtils.checkSkip(should.skip, 'lib')) {
92
92
  this.skip();
93
93
  }
94
94
  // Skip the test if the transport is specified (IoTA Lib does not support any transport)
@@ -1476,6 +1476,65 @@ const testCases = [
1476
1476
  }
1477
1477
  ]
1478
1478
  },
1479
+ // 0200 - COMMANDS TESTS
1480
+ {
1481
+ describeName: '0200 - Simple group with commands',
1482
+ provision: {
1483
+ url: 'http://localhost:' + config.iota.server.port + '/iot/services',
1484
+ method: 'POST',
1485
+ json: {
1486
+ services: [
1487
+ {
1488
+ resource: '/iot/json',
1489
+ apikey: globalEnv.apikey,
1490
+ entity_type: globalEnv.entity_type,
1491
+ commands: [
1492
+ {
1493
+ name: 'cmd1',
1494
+ type: 'command'
1495
+ }
1496
+ ],
1497
+ endpoint: 'http://myendpoint.com',
1498
+ transport: 'http',
1499
+ lazy: [],
1500
+ attributes: [],
1501
+ static_attributes: []
1502
+ }
1503
+ ]
1504
+ },
1505
+ headers: {
1506
+ 'fiware-service': globalEnv.service,
1507
+ 'fiware-servicepath': globalEnv.servicePath
1508
+ }
1509
+ },
1510
+ should: [
1511
+ {
1512
+ shouldName:
1513
+ 'A - WHEN sending not provisioned object_ids (measures) through http IT should store commands into Context Broker',
1514
+ type: 'single',
1515
+ skip: '!lib', // there is not CB registration mock
1516
+ measure: {
1517
+ url: 'http://localhost:' + config.http.port + '/iot/json',
1518
+ method: 'POST',
1519
+ qs: {
1520
+ i: globalEnv.deviceId,
1521
+ k: globalEnv.apikey
1522
+ },
1523
+ json: {
1524
+ b: 10
1525
+ }
1526
+ },
1527
+ expectation: {
1528
+ id: globalEnv.entity_name,
1529
+ type: globalEnv.entity_type,
1530
+ b: {
1531
+ value: 10,
1532
+ type: 'string'
1533
+ }
1534
+ }
1535
+ }
1536
+ ]
1537
+ },
1479
1538
  // 0300 - STATIC ATTRIBUTES TESTS
1480
1539
  {
1481
1540
  describeName:
@@ -2424,6 +2483,7 @@ const testCases = [
2424
2483
  {
2425
2484
  shouldName: 'C - WHEN sending only b IT should store only [{object_id:b}] attrs into Context Broker',
2426
2485
  type: 'single',
2486
+ skip: '!lib', // FIXME: https://github.com/telefonicaid/iotagent-json/issues/782
2427
2487
  measure: {
2428
2488
  url: 'http://localhost:' + config.http.port + '/iot/json',
2429
2489
  method: 'POST',
@@ -2450,6 +2510,7 @@ const testCases = [
2450
2510
  shouldName:
2451
2511
  'D - WHEN no sending any defined case IT should store [static_a,static_b] attrs into Context Broker',
2452
2512
  type: 'single',
2513
+ skip: '!lib', // FIXME: https://github.com/telefonicaid/iotagent-json/issues/782
2453
2514
  measure: {
2454
2515
  url: 'http://localhost:' + config.http.port + '/iot/json',
2455
2516
  method: 'POST',
@@ -139,6 +139,8 @@ function groupToIoTAConfigType(group, service, subservice) {
139
139
  type.type = group.entity_type;
140
140
  } else if (key === 'static_attributes') {
141
141
  type.staticAttributes = group.static_attributes;
142
+ } else if (key === 'commands') {
143
+ type.commands = group.commands;
142
144
  } else if (key !== 'resource') {
143
145
  type[key] = group[key];
144
146
  }
@@ -932,6 +932,14 @@ describe('NGSI-v2 - Active attributes test', function () {
932
932
  meas: {
933
933
  value: 'measIoTA',
934
934
  type: 'String'
935
+ },
936
+ measure_id: {
937
+ type: 'text',
938
+ value: 'idIoTA'
939
+ },
940
+ measure_type: {
941
+ type: 'text',
942
+ value: 'typeIoTA'
935
943
  }
936
944
  })
937
945
  .reply(204);
@@ -1026,6 +1034,14 @@ describe('NGSI-v2 - Active attributes test', function () {
1026
1034
  meas: {
1027
1035
  value: 'measIoTA',
1028
1036
  type: 'String'
1037
+ },
1038
+ measure_id: {
1039
+ value: 'idIoTA',
1040
+ type: 'text'
1041
+ },
1042
+ measure_type: {
1043
+ value: 'typeIoTA',
1044
+ type: 'text'
1029
1045
  }
1030
1046
  })
1031
1047
  .reply(204);
@@ -61,6 +61,8 @@ const optionsCreation = {
61
61
  entity_type: 'SensorMachine',
62
62
  trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
63
63
  cbHost: 'http://unexistentHost:1026',
64
+ transport: 'HTTP',
65
+ endpoint: 'http://myendpoint.com',
64
66
  commands: [
65
67
  {
66
68
  name: 'wheel1',
@@ -136,6 +138,8 @@ const optionsUpdate = {
136
138
  json: {
137
139
  trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
138
140
  cbHost: 'http://anotherUnexistentHost:1026',
141
+ transport: 'MQTT',
142
+ endpoint: 'http://yourendpoint.com',
139
143
  commands: [
140
144
  {
141
145
  name: 'wheel1',
@@ -217,6 +221,8 @@ describe('NGSI-v2 - Device Group Configuration API', function () {
217
221
  request(optionsList, function (error, response, body) {
218
222
  body.count.should.equal(1);
219
223
  body.services[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
224
+ body.services[0].transport.should.equal('HTTP');
225
+ body.services[0].endpoint.should.equal('http://myendpoint.com');
220
226
  done();
221
227
  });
222
228
  });
@@ -664,6 +670,8 @@ describe('NGSI-v2 - Device Group Configuration API', function () {
664
670
  ) {
665
671
  body.services[i].cbHost.should.equal('http://anotherUnexistentHost:1026');
666
672
  body.services[i].static_attributes.length.should.equal(1);
673
+ body.services[i].endpoint = 'http://yourendpoint.com';
674
+ body.services[i].transport = 'MQTT';
667
675
  found = true;
668
676
  }
669
677
  }