iotagent-node-lib 4.4.0 → 4.6.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 (100) hide show
  1. package/README.md +67 -272
  2. package/config.js +2 -1
  3. package/doc/README.md +1 -1
  4. package/doc/admin.md +19 -22
  5. package/doc/api.md +621 -155
  6. package/doc/deprecated.md +4 -0
  7. package/doc/devel/architecture.md +5 -135
  8. package/doc/devel/development.md +224 -12
  9. package/doc/getting-started.md +114 -53
  10. package/doc/requirements.txt +1 -1
  11. package/doc/roadmap.md +5 -5
  12. package/docker/Mosquitto/Dockerfile +2 -2
  13. package/docker/Mosquitto/README.md +14 -11
  14. package/lib/commonConfig.js +7 -1
  15. package/lib/constants.js +3 -0
  16. package/lib/fiware-iotagent-lib.js +12 -15
  17. package/lib/jexlTranformsMap.js +3 -1
  18. package/lib/model/dbConn.js +1 -4
  19. package/lib/services/common/alarmManagement.js +3 -0
  20. package/lib/services/devices/deviceRegistryMemory.js +1 -1
  21. package/lib/services/devices/deviceRegistryMongoDB.js +2 -2
  22. package/lib/services/devices/deviceService.js +4 -3
  23. package/lib/services/devices/devices-NGSI-LD.js +5 -5
  24. package/lib/services/devices/devices-NGSI-mixed.js +3 -3
  25. package/lib/services/devices/devices-NGSI-v2.js +5 -5
  26. package/lib/services/groups/groupService.js +1 -1
  27. package/lib/services/ngsi/entities-NGSI-LD.js +321 -571
  28. package/lib/services/ngsi/entities-NGSI-v2.js +348 -281
  29. package/lib/services/ngsi/ngsiService.js +3 -1
  30. package/lib/services/ngsi/subscription-NGSI-LD.js +2 -2
  31. package/lib/services/ngsi/subscription-NGSI-v2.js +2 -2
  32. package/lib/services/northBound/deviceGroupAdministrationServer.js +42 -6
  33. package/lib/services/northBound/deviceProvisioningServer.js +5 -5
  34. package/lib/services/northBound/northboundServer.js +4 -2
  35. package/lib/services/stats/statsRegistry.js +128 -101
  36. package/lib/templates/createDevice.json +0 -24
  37. package/lib/templates/createDeviceLax.json +0 -23
  38. package/lib/templates/deviceGroup.json +1 -25
  39. package/lib/templates/updateDevice.json +0 -24
  40. package/lib/templates/updateDeviceLax.json +0 -23
  41. package/package.json +2 -2
  42. package/scripts/legacy_expression_tool/README.md +0 -1
  43. package/test/functional/README.md +75 -47
  44. package/test/functional/functional-tests-runner.js +9 -4
  45. package/test/functional/functional-tests.js +4 -4
  46. package/test/functional/testCases.js +1251 -257
  47. package/test/functional/testUtils.js +53 -20
  48. package/test/unit/examples/deviceProvisioningRequests/provisionFullDevice.json +1 -13
  49. package/test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithApikey.json +4 -0
  50. package/test/unit/examples/groupProvisioningRequests/multipleConfigGroupsCreation.json +44 -0
  51. package/test/unit/examples/groupProvisioningRequests/provisionDuplicateConfigGroup.json +35 -0
  52. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroup.json +36 -0
  53. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroupAlternate.json +36 -0
  54. package/test/unit/general/deviceService-test.js +102 -0
  55. package/test/unit/general/statistics-service_test.js +1 -74
  56. package/test/unit/mongodb/mongodb-configGroup-registry-test.js +452 -0
  57. package/test/unit/mongodb/mongodb-connectionoptions-test.js +2 -3
  58. package/test/unit/mongodb/mongodb-group-registry-test.js +34 -33
  59. package/test/unit/mongodb/mongodb-service-registry-test.js +477 -0
  60. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +4 -4
  61. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json +22 -22
  62. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +4 -4
  63. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json +14 -15
  64. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin1.json +23 -23
  65. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin15.json +0 -5
  66. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin4.json +11 -16
  67. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin5.json +23 -28
  68. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin6.json +8 -13
  69. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin7.json +0 -5
  70. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin8.json +24 -29
  71. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +12 -17
  72. package/test/unit/ngsi-ld/examples/contextRequests/updateContextStaticLinkedAttributes.json +12 -10
  73. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -102
  74. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +4 -5
  75. package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +5 -5
  76. package/test/unit/ngsi-ld/provisioning/listProvisionedDevices-test.js +0 -4
  77. package/test/unit/ngsiv2/general/deviceService-test.js +94 -1
  78. package/test/unit/ngsiv2/general/iotam-autoregistration-test.js +195 -0
  79. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +259 -0
  80. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +1189 -0
  81. package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +6 -6
  82. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +0 -4
  83. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +35 -0
  84. package/test/unit/statsRegistry/openmetrics-test.js +167 -0
  85. package/lib/templates/queryContext.json +0 -25
  86. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +0 -35
  87. package/test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json +0 -17
  88. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +0 -31
  89. package/test/unit/general/statistics-persistence_test.js +0 -121
  90. package/test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json +0 -17
  91. package/test/unit/ngsi-ld/examples/contextRequests/updateContextProcessTimestamp.json +0 -12
  92. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  93. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json +0 -21
  94. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -17
  95. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -23
  96. package/test/unit/ngsi-ld/plugins/timestamp-processing-plugin_test.js +0 -132
  97. package/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +0 -8
  98. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  99. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -19
  100. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -24
@@ -1,19 +1,14 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:WeatherStation:ws5",
5
- "type": "WeatherStation"
6
- },
7
- {
8
- "@context": "http://context.json-ld",
9
- "id": "urn:ngsi-ld:Higrometer:Higro2000",
10
- "pressure": {
11
- "type": "Property",
12
- "value": {
13
- "@type": "Hgmm",
14
- "@value": "16"
15
- }
16
- },
17
- "type": "Higrometer"
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:Higrometer:Higro2000",
5
+ "type": "Higrometer",
6
+ "pressure": {
7
+ "type": "Property",
8
+ "value": {
9
+ "@type": "Hgmm",
10
+ "@value": "16"
11
+ }
18
12
  }
13
+ }
19
14
  ]
@@ -1,31 +1,26 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:WeatherStation:ws6",
5
- "type": "WeatherStation"
6
- },
7
- {
8
- "@context": "http://context.json-ld",
9
- "id": "urn:ngsi-ld:Higrometer:Higro2000",
10
- "type": "Higrometer",
11
- "pressure": {
12
- "type": "Property",
13
- "value": {
14
- "@type": "Hgmm",
15
- "@value": "16"
16
- }
17
- }
18
- },
19
- {
20
- "@context": "http://context.json-ld",
21
- "id": "urn:ngsi-ld:Higrometer:Higro2002",
22
- "type": "Higrometer",
23
- "pressure": {
24
- "type": "Property",
25
- "value": {
26
- "@type": "Hgmm",
27
- "@value": "17"
28
- }
29
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:Higrometer:Higro2002",
5
+ "type": "Higrometer",
6
+ "pressure": {
7
+ "type": "Property",
8
+ "value": {
9
+ "@type": "Hgmm",
10
+ "@value": "17"
11
+ }
30
12
  }
13
+ },
14
+ {
15
+ "@context": "http://context.json-ld",
16
+ "id": "urn:ngsi-ld:Higrometer:Higro2000",
17
+ "type": "Higrometer",
18
+ "pressure": {
19
+ "type": "Property",
20
+ "value": {
21
+ "@type": "Hgmm",
22
+ "@value": "16"
23
+ }
24
+ }
25
+ }
31
26
  ]
@@ -1,16 +1,11 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:Sensor:Sensor",
5
- "type": "Sensor"
6
- },
7
- {
8
- "@context": "http://context.json-ld",
9
- "id": "urn:ngsi-ld:WM:SO1",
10
- "type": "WM",
11
- "vol": {
12
- "type": "Property",
13
- "value": 38
14
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:WM:SO1",
5
+ "type": "WM",
6
+ "vol": {
7
+ "type": "Property",
8
+ "value": 38
15
9
  }
10
+ }
16
11
  ]
@@ -1,9 +1,4 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:Sensor:Sensor",
5
- "type": "Sensor"
6
- },
7
2
  {
8
3
  "@context": "http://context.json-ld",
9
4
  "id": "urn:ngsi-ld:WM:SO1",
@@ -1,32 +1,27 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:WeatherStation:ws7",
5
- "type": "WeatherStation"
6
- },
7
- {
8
- "@context": "http://context.json-ld",
9
- "id": "urn:ngsi-ld:Higrometer:Higro2000",
10
- "type": "Higrometer",
11
- "pressure": {
12
- "type": "Property",
13
- "value": {
14
- "@type": "Hgmm",
15
- "@value": "16"
16
- }
17
- }
18
- },
19
- {
20
- "@context": "http://context.json-ld",
21
- "id": "urn:ngsi-ld:Higrometer:Higro2002",
22
- "type": "Higrometer",
23
- "pressure": {
24
- "type": "Property",
25
- "value": {
26
- "@type": "Hgmm",
27
- "@value": "17"
28
- },
29
- "unitCode": "Hgmm"
30
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:Higrometer:Higro2002",
5
+ "type": "Higrometer",
6
+ "pressure": {
7
+ "type": "Property",
8
+ "value": {
9
+ "@type": "Hgmm",
10
+ "@value": "17"
11
+ },
12
+ "unitCode": "Hgmm"
31
13
  }
14
+ },
15
+ {
16
+ "@context": "http://context.json-ld",
17
+ "id": "urn:ngsi-ld:Higrometer:Higro2000",
18
+ "type": "Higrometer",
19
+ "pressure": {
20
+ "type": "Property",
21
+ "value": {
22
+ "@type": "Hgmm",
23
+ "@value": "16"
24
+ }
25
+ }
26
+ }
32
27
  ]
@@ -1,20 +1,15 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:WeatherStation:ws4",
5
- "type": "WeatherStation"
6
- },
7
- {
8
- "@context": "http://context.json-ld",
9
- "id": "urn:ngsi-ld:Higrometer:Higro2000",
10
- "type": "Higrometer",
11
- "humidity": {
12
- "type": "Property",
13
- "value": {
14
- "@type": "Percentage",
15
- "@value": "12"
16
- },
17
- "observedAt": "2023-03-21T16:54:11.464Z"
18
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:Higrometer:Higro2000",
5
+ "type": "Higrometer",
6
+ "humidity": {
7
+ "type": "Property",
8
+ "value": {
9
+ "@type": "Percentage",
10
+ "@value": "12"
11
+ },
12
+ "observedAt": "2024-06-25T16:04:13.914Z"
19
13
  }
14
+ }
20
15
  ]
@@ -1,14 +1,8 @@
1
1
  [
2
2
  {
3
3
  "@context": "http://context.json-ld",
4
- "luminosity": {
5
- "type": "Property",
6
- "value": 87,
7
- "providedBy": {
8
- "type": "Relationship",
9
- "object": "urn:ngsi-ld:Lamp:lamp1"
10
- }
11
- },
4
+ "id": "urn:ngsi-ld:Lamp:lamp1",
5
+ "type": "Lamp",
12
6
  "controlledAsset": {
13
7
  "type": "Relationship",
14
8
  "object": "urn:ngsi-ld:Building:001"
@@ -21,8 +15,15 @@
21
15
  "value": "bell"
22
16
  }
23
17
  },
24
- "id": "urn:ngsi-ld:Lamp:lamp1",
25
- "type": "Lamp"
18
+ "luminosity": {
19
+ "type": "Property",
20
+ "value": 87,
21
+ "unitCode": "CAL",
22
+ "providedBy": {
23
+ "type": "Relationship",
24
+ "object": "urn:ngsi-ld:Lamp:lamp1"
25
+ }
26
+ }
26
27
  },
27
28
  {
28
29
  "@context": "http://context.json-ld",
@@ -31,6 +32,7 @@
31
32
  "luminosity": {
32
33
  "type": "Property",
33
34
  "value": 87,
35
+ "unitCode": "CAL",
34
36
  "providedBy": {
35
37
  "type": "Relationship",
36
38
  "object": "urn:ngsi-ld:Lamp:lamp1"
@@ -306,40 +306,6 @@ describe('NGSI-LD: JEXL', function () {
306
306
  });
307
307
  });
308
308
 
309
- describe('When an update comes for expressions with syntax errors', function () {
310
- // Case: Update for an attribute with bad expression
311
- const values = [
312
- {
313
- name: 'p',
314
- type: 'centigrades',
315
- value: '52'
316
- }
317
- ];
318
-
319
- beforeEach(function () {
320
- nock.cleanAll();
321
-
322
- contextBrokerMock = nock('http://192.168.1.1:1026')
323
- .matchHeader('fiware-service', 'smartgondor')
324
- .matchHeader('fiware-servicepath', 'gardens')
325
- .post(
326
- '/ngsi-ld/v1/entityOperations/upsert/?options=update',
327
- utils.readExampleFile(
328
- './test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin30.json'
329
- )
330
- )
331
- .reply(204);
332
- });
333
-
334
- it('should ignore the expression before sending the values', function (done) {
335
- iotAgentLib.update('light1', 'LightError', '', values, function (error) {
336
- should.not.exist(error);
337
- contextBrokerMock.done();
338
- done();
339
- });
340
- });
341
- });
342
-
343
309
  describe('When there are expression attributes that are just calculated (not sent by the device)', function () {
344
310
  // Case: Expression which results is sent as a new attribute
345
311
  const values = [
@@ -557,41 +523,6 @@ describe('NGSI-LD: JEXL', function () {
557
523
  });
558
524
  });
559
525
 
560
- describe('When an update comes for attributes without expressions and NULL type', function () {
561
- // Case: Update for a Null attribute without expression
562
-
563
- const values = [
564
- {
565
- name: 'a',
566
- type: 'None',
567
- value: null
568
- }
569
- ];
570
-
571
- beforeEach(function () {
572
- nock.cleanAll();
573
-
574
- contextBrokerMock = nock('http://192.168.1.1:1026')
575
- .matchHeader('fiware-service', 'smartgondor')
576
- .matchHeader('fiware-servicepath', 'gardens')
577
- .post(
578
- '/ngsi-ld/v1/entityOperations/upsert/?options=update',
579
- utils.readExampleFile(
580
- './test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin5.json'
581
- )
582
- )
583
- .reply(204);
584
- });
585
-
586
- it('should apply the expression before sending the values', function (done) {
587
- iotAgentLib.update('light1', 'Light', '', values, function (error) {
588
- should.not.exist(error);
589
- contextBrokerMock.done();
590
- done();
591
- });
592
- });
593
- });
594
-
595
526
  describe('When an update comes for attributes without expressions and Boolean type', function () {
596
527
  // Case: Update for a Boolean attribute without expression
597
528
 
@@ -696,39 +627,6 @@ describe('NGSI-LD: JEXL', function () {
696
627
  });
697
628
  });
698
629
 
699
- describe('When there are expressions including other attributes and they are not updated', function () {
700
- const values = [
701
- {
702
- name: 'x',
703
- type: 'Number',
704
- value: 0.44
705
- }
706
- ];
707
-
708
- beforeEach(function () {
709
- nock.cleanAll();
710
-
711
- contextBrokerMock = nock('http://192.168.1.1:1026')
712
- .matchHeader('fiware-service', 'smartgondor')
713
- .matchHeader('fiware-servicepath', 'gardens')
714
- .post(
715
- '/ngsi-ld/v1/entityOperations/upsert/?options=update',
716
- utils.readExampleFile(
717
- './test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin12a.json'
718
- )
719
- )
720
- .reply(204);
721
- });
722
-
723
- it('should apply the expression before sending the values', function (done) {
724
- iotAgentLib.update('light1', 'Light', '', values, function (error) {
725
- should.not.exist(error);
726
- contextBrokerMock.done();
727
- done();
728
- });
729
- });
730
- });
731
-
732
630
  describe('When there are expressions including other attributes and they are updated', function () {
733
631
  const values = [
734
632
  {
@@ -696,17 +696,16 @@ describe('NGSI-LD - Multi-entity plugin is executed before timestamp process plu
696
696
  './test/unit/ngsi-ld/examples' +
697
697
  '/contextRequests/updateContextMultientityTimestampPlugin2.json'
698
698
  );
699
-
700
699
  // Note that TimeInstant fields are not included in the json used by this mock as they are dynamic
701
700
  // fields. The following code just checks that TimeInstant fields are present.
702
- if (!body[1].humidity.observedAt) {
701
+ if (!body[0].humidity.observedAt) {
703
702
  return false;
704
703
  }
705
704
 
706
- const timeInstantAtt = body[1].humidity.observedAt;
705
+ const timeInstantAtt = body[0].humidity.observedAt;
707
706
  if (moment(timeInstantAtt, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid) {
708
- delete body[1].humidity.observedAt;
709
- delete expectedBody[1].humidity.observedAt;
707
+ delete body[0].humidity.observedAt;
708
+ delete expectedBody[0].humidity.observedAt;
710
709
  return JSON.stringify(body) === JSON.stringify(expectedBody);
711
710
  }
712
711
  return false;
@@ -186,14 +186,14 @@ describe('NGSI-LD - IoT Agent Device Update Registration', function () {
186
186
  });
187
187
 
188
188
  it('should register as ContextProvider of its lazy attributes', function (done) {
189
- iotAgentLib.updateRegister(deviceUpdated, false, function (error) {
189
+ iotAgentLib.updateRegister(deviceUpdated, device1, false, function (error) {
190
190
  should.not.exist(error);
191
191
  contextBrokerMock.done();
192
192
  done();
193
193
  });
194
194
  });
195
195
  it('should store the new values in the registry', function (done) {
196
- iotAgentLib.updateRegister(deviceUpdated, false, function (error, data) {
196
+ iotAgentLib.updateRegister(deviceUpdated, device1, false, function (error, data) {
197
197
  iotAgentLib.getDevice(deviceUpdated.id, null, 'smartgondor', 'gardens', function (error, deviceResult) {
198
198
  should.not.exist(error);
199
199
  should.exist(deviceResult);
@@ -236,7 +236,7 @@ describe('NGSI-LD - IoT Agent Device Update Registration', function () {
236
236
  // });
237
237
  // });
238
238
  it('should store the new values in the registry', function (done) {
239
- iotAgentLib.updateRegister(deviceCommandUpdated, false, function (error, data) {
239
+ iotAgentLib.updateRegister(deviceCommandUpdated, device1, false, function (error, data) {
240
240
  iotAgentLib.getDevice(
241
241
  deviceCommandUpdated.id,
242
242
  null,
@@ -257,7 +257,7 @@ describe('NGSI-LD - IoT Agent Device Update Registration', function () {
257
257
 
258
258
  describe('When a update action is executed in a non registered device', function () {
259
259
  it('should return a DEVICE_NOT_FOUND error', function (done) {
260
- iotAgentLib.updateRegister(unknownDevice, false, function (error) {
260
+ iotAgentLib.updateRegister(unknownDevice, device1, false, function (error) {
261
261
  should.exist(error);
262
262
  error.name.should.equal('DEVICE_NOT_FOUND');
263
263
  done();
@@ -273,7 +273,7 @@ describe('NGSI-LD - IoT Agent Device Update Registration', function () {
273
273
  });
274
274
 
275
275
  it('should return a REGISTRATION_ERROR error in the update action', function (done) {
276
- iotAgentLib.updateRegister(deviceUpdated, false, function (error) {
276
+ iotAgentLib.updateRegister(deviceUpdated, device1, false, function (error) {
277
277
  should.exist(error);
278
278
  //error.name.should.equal('UNREGISTRATION_ERROR');
279
279
  done();
@@ -184,11 +184,9 @@ describe('NGSI-LD - Device provisioning API: List provisioned devices', function
184
184
  should.exist(body.devices[2].attributes[0].entity_name);
185
185
  should.exist(body.devices[2].attributes[0].entity_type);
186
186
  should.exist(body.devices[2].attributes[1].expression);
187
- should.exist(body.devices[2].attributes[2].reverse);
188
187
  body.devices[2].attributes[0].entity_name.should.equal('Higro2000');
189
188
  body.devices[2].attributes[0].entity_type.should.equal('Higrometer');
190
189
  body.devices[2].attributes[1].expression.should.equal('${@humidity * 20}');
191
- body.devices[2].attributes[2].reverse.length.should.equal(2);
192
190
  done();
193
191
  });
194
192
  });
@@ -245,11 +243,9 @@ describe('NGSI-LD - Device provisioning API: List provisioned devices', function
245
243
  should.exist(body.attributes[0].entity_name);
246
244
  should.exist(body.attributes[0].entity_type);
247
245
  should.exist(body.attributes[1].expression);
248
- should.exist(body.attributes[2].reverse);
249
246
  body.attributes[0].entity_name.should.equal('Higro2000');
250
247
  body.attributes[0].entity_type.should.equal('Higrometer');
251
248
  body.attributes[1].expression.should.equal('${@humidity * 20}');
252
- body.attributes[2].reverse.length.should.equal(2);
253
249
  done();
254
250
  });
255
251
  });
@@ -156,6 +156,34 @@ const groupCreation = {
156
156
  'fiware-servicepath': '/testingPath'
157
157
  }
158
158
  };
159
+ const configGroupCreation = {
160
+ url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/groups',
161
+ method: 'POST',
162
+ json: {
163
+ groups: [
164
+ {
165
+ resource: '',
166
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
167
+ entity_type: 'TheLightType',
168
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
169
+ cbHost: 'http://192.168.1.1:1026',
170
+ commands: [],
171
+ lazy: [],
172
+ attributes: [
173
+ {
174
+ name: 'status',
175
+ type: 'Boolean'
176
+ }
177
+ ],
178
+ static_attributes: []
179
+ }
180
+ ]
181
+ },
182
+ headers: {
183
+ 'fiware-service': 'testservice',
184
+ 'fiware-servicepath': '/testingPath'
185
+ }
186
+ };
159
187
  const deviceCreation = {
160
188
  url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
161
189
  method: 'POST',
@@ -182,7 +210,7 @@ describe('NGSI-v2 - Device Service: utils', function () {
182
210
  nock.cleanAll();
183
211
  async.series([iotAgentLib.clearAll, iotAgentLib.deactivate], done);
184
212
  });
185
-
213
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
186
214
  describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
187
215
  beforeEach(function (done) {
188
216
  // This mock does not check the payload since the aim of the test is not to verify
@@ -212,7 +240,39 @@ describe('NGSI-v2 - Device Service: utils', function () {
212
240
  });
213
241
  });
214
242
  });
243
+ describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
244
+ beforeEach(function (done) {
245
+ // This mock does not check the payload since the aim of the test is not to verify
246
+ // device provisioning functionality. Appropriate verification is done in tests under
247
+ // provisioning folder
248
+ contextBrokerMock = nock('http://192.168.1.1:1026')
249
+ .matchHeader('fiware-service', 'testservice')
250
+ .matchHeader('fiware-servicepath', '/testingPath')
251
+ .post('/v2/entities?options=upsert')
252
+ .reply(204);
253
+
254
+ async.series(
255
+ [
256
+ utils.request.bind(utils.request, configGroupCreation),
257
+ utils.request.bind(utils.request, deviceCreation)
258
+ ],
259
+ function (error, results) {
260
+ done();
261
+ }
262
+ );
263
+ });
264
+
265
+ it('should return the existing device', function (done) {
266
+ iotAgentLib.retrieveDevice('Light1', '801230BJKL23Y9090DSFL123HJK09H324HV8732', function (error, device) {
267
+ should.not.exist(error);
268
+ should.exist(device);
215
269
 
270
+ device.id.should.equal('Light1');
271
+ done();
272
+ });
273
+ });
274
+ });
275
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
216
276
  describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
217
277
  beforeEach(function (done) {
218
278
  // This mock does not check the payload since the aim of the test is not to verify
@@ -246,6 +306,39 @@ describe('NGSI-v2 - Device Service: utils', function () {
246
306
  });
247
307
  });
248
308
 
309
+ describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
310
+ beforeEach(function (done) {
311
+ // This mock does not check the payload since the aim of the test is not to verify
312
+ // device provisioning functionality. Appropriate verification is done in tests under
313
+ // provisioning folder
314
+ contextBrokerMock = nock('http://192.168.1.1:1026')
315
+ .matchHeader('fiware-service', 'testservice')
316
+ .matchHeader('fiware-servicepath', '/testingPath')
317
+ .post('/v2/entities?options=upsert')
318
+ .reply(204);
319
+
320
+ async.series([utils.request.bind(utils.request, configGroupCreation)], function (error, results) {
321
+ done();
322
+ });
323
+ });
324
+
325
+ it('should register the device and return it', function (done) {
326
+ iotAgentLib.retrieveDevice(
327
+ 'UNEXISTENT_DEV',
328
+ '801230BJKL23Y9090DSFL123HJK09H324HV8732',
329
+ function (error, device) {
330
+ should.not.exist(error);
331
+ should.exist(device);
332
+
333
+ device.id.should.equal('UNEXISTENT_DEV');
334
+ should.exist(device.protocol);
335
+ device.protocol.should.equal('MQTT_UL');
336
+ done();
337
+ }
338
+ );
339
+ });
340
+ });
341
+
249
342
  describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function () {
250
343
  it('should raise an error', function (done) {
251
344
  iotAgentLib.retrieveDevice(