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
@@ -0,0 +1,477 @@
1
+ /*
2
+ * Copyright 2024 Telefonica Investigación y Desarrollo, S.A.U
3
+ *
4
+ * This file is part of fiware-iotagent-lib
5
+ *
6
+ * fiware-iotagent-lib is free software: you can redistribute it and/or
7
+ * modify it under the terms of the GNU Affero General Public License as
8
+ * published by the Free Software Foundation, either version 3 of the License,
9
+ * or (at your option) any later version.
10
+ *
11
+ * fiware-iotagent-lib is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
+ * See the GNU Affero General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public
17
+ * License along with fiware-iotagent-lib.
18
+ * If not, see http://www.gnu.org/licenses/.
19
+ *
20
+ * For those usages not covered by the GNU Affero General Public License
21
+ * please contact with::[contacto@tid.es]
22
+ *
23
+ * Modified by: Daniel Calvo - ATOS Research & Innovation
24
+ */
25
+
26
+ // #FIXME1649: parallel tests in mongodb-configGroup-registry-test.js. Remove this file if at the end /iot/services API (now Deprecated) is removed
27
+ /* eslint-disable no-unused-vars */
28
+
29
+ const iotAgentLib = require('../../../lib/fiware-iotagent-lib');
30
+ const _ = require('underscore');
31
+ const utils = require('../../tools/utils');
32
+ const request = utils.request;
33
+ const async = require('async');
34
+ const should = require('should');
35
+ const iotAgentConfig = {
36
+ logLevel: 'FATAL',
37
+ contextBroker: {
38
+ host: '192.168.1.1',
39
+ port: '1026'
40
+ },
41
+ server: {
42
+ name: 'testAgent',
43
+ port: 4041,
44
+ host: 'localhost',
45
+ baseRoot: '/'
46
+ },
47
+ types: {},
48
+ deviceRegistry: {
49
+ type: 'mongodb'
50
+ },
51
+ mongodb: {
52
+ host: 'localhost',
53
+ port: '27017',
54
+ db: 'iotagent'
55
+ },
56
+ service: 'smartgondor',
57
+ subservice: 'gardens',
58
+ providerUrl: 'http://smartgondor.com',
59
+ deviceRegistrationDuration: 'P1M'
60
+ };
61
+ const mongo = require('mongodb').MongoClient;
62
+ const mongoUtils = require('./mongoDBUtils');
63
+ const optionsCreation = {
64
+ url: 'http://localhost:4041/iot/services',
65
+ method: 'POST',
66
+ json: {
67
+ services: [
68
+ {
69
+ resource: '/deviceTest',
70
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
71
+ entity_type: 'Light',
72
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
73
+ cbHost: 'http://unexistentHost:1026',
74
+ commands: [
75
+ {
76
+ name: 'wheel1',
77
+ type: 'Wheel'
78
+ }
79
+ ],
80
+ lazy: [
81
+ {
82
+ name: 'luminescence',
83
+ type: 'Lumens'
84
+ }
85
+ ],
86
+ attributes: [
87
+ {
88
+ name: 'status',
89
+ type: 'Boolean'
90
+ }
91
+ ],
92
+ internal_attributes: [
93
+ {
94
+ customField: 'customValue'
95
+ }
96
+ ]
97
+ }
98
+ ]
99
+ },
100
+ headers: {
101
+ 'fiware-service': 'testservice',
102
+ 'fiware-servicepath': '/testingPath'
103
+ }
104
+ };
105
+ const optionsDelete = {
106
+ url: 'http://localhost:4041/iot/services',
107
+ method: 'DELETE',
108
+ json: {},
109
+ headers: {
110
+ 'fiware-service': 'testservice',
111
+ 'fiware-servicepath': '/testingPath'
112
+ },
113
+ qs: {
114
+ resource: '/deviceTest',
115
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
116
+ }
117
+ };
118
+ const optionsList = {
119
+ url: 'http://localhost:4041/iot/services',
120
+ method: 'GET',
121
+ json: {},
122
+ headers: {
123
+ 'fiware-service': 'testservice',
124
+ 'fiware-servicepath': '/*'
125
+ }
126
+ };
127
+ const optionsUpdate = {
128
+ url: 'http://localhost:4041/iot/services',
129
+ method: 'PUT',
130
+ json: {
131
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
132
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
133
+ cbHost: 'http://anotherUnexistentHost:1026',
134
+ commands: [
135
+ {
136
+ name: 'wheel1',
137
+ type: 'Wheel'
138
+ }
139
+ ],
140
+ lazy: [
141
+ {
142
+ name: 'luminescence',
143
+ type: 'Lumens'
144
+ }
145
+ ],
146
+ attributes: [
147
+ {
148
+ name: 'status',
149
+ type: 'Boolean'
150
+ }
151
+ ],
152
+ static_attributes: [
153
+ {
154
+ name: 'bootstrapServer',
155
+ type: 'Address',
156
+ value: '127.0.0.1'
157
+ }
158
+ ]
159
+ },
160
+ headers: {
161
+ 'fiware-service': 'testservice',
162
+ 'fiware-servicepath': '/testingPath'
163
+ },
164
+ qs: {
165
+ resource: '/deviceTest',
166
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
167
+ }
168
+ };
169
+ const optionsGet = {
170
+ url: 'http://localhost:4041/iot/services',
171
+ method: 'GET',
172
+ json: {},
173
+ headers: {
174
+ 'fiware-service': 'testservice',
175
+ 'fiware-servicepath': '/testingPath'
176
+ }
177
+ };
178
+ let iotAgentDb;
179
+
180
+ describe('MongoDB Service Registry test', function () {
181
+ beforeEach(function (done) {
182
+ mongoUtils.cleanDbs(function () {
183
+ iotAgentLib.activate(iotAgentConfig, function () {
184
+ mongo.connect('mongodb://localhost:27017/iotagent', function (err, db) {
185
+ iotAgentDb = db;
186
+ done();
187
+ });
188
+ });
189
+ });
190
+ });
191
+
192
+ afterEach(function (done) {
193
+ iotAgentLib.deactivate(function () {
194
+ iotAgentDb.close(function (error) {
195
+ mongoUtils.cleanDbs(done);
196
+ });
197
+ });
198
+ });
199
+ describe('When a new device group creation request arrives', function () {
200
+ it('should store it in the DB', function (done) {
201
+ request(optionsCreation, function (error, response, body) {
202
+ iotAgentDb
203
+ .db()
204
+ .collection('groups')
205
+ .find({})
206
+ .toArray(function (err, docs) {
207
+ should.not.exist(err);
208
+ should.exist(docs);
209
+ should.exist(docs.length);
210
+ docs.length.should.equal(1);
211
+ should.exist(docs[0].type);
212
+ should.exist(docs[0].internalAttributes);
213
+ should.exist(docs[0].attributes);
214
+ should.exist(docs[0].apikey);
215
+ docs[0].type.should.equal('Light');
216
+ docs[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
217
+ docs[0].internalAttributes.length.should.equal(1);
218
+ docs[0].internalAttributes[0].customField.should.equal('customValue');
219
+ docs[0].attributes.length.should.equal(1);
220
+ docs[0].attributes[0].name.should.equal('status');
221
+ done();
222
+ });
223
+ });
224
+ });
225
+ it('should store the service information from the headers into the DB', function (done) {
226
+ request(optionsCreation, function (error, response, body) {
227
+ iotAgentDb
228
+ .db()
229
+ .collection('groups')
230
+ .find({})
231
+ .toArray(function (err, docs) {
232
+ should.not.exist(err);
233
+ should.exist(docs[0].service);
234
+ should.exist(docs[0].subservice);
235
+ docs[0].service.should.equal('testservice');
236
+ docs[0].subservice.should.equal('/testingPath');
237
+ done();
238
+ });
239
+ });
240
+ });
241
+ });
242
+
243
+ describe('When a new device group creation request arrives with an existant (apikey, resource) pair', function () {
244
+ it('should return a DUPLICATE_GROUP error', function (done) {
245
+ request(optionsCreation, function (error, response, body) {
246
+ request(optionsCreation, function (error, response, body) {
247
+ response.statusCode.should.equal(409);
248
+ body.name.should.equal('DUPLICATE_GROUP');
249
+ done();
250
+ });
251
+ });
252
+ });
253
+ });
254
+
255
+ describe('When a device group removal request arrives', function () {
256
+ beforeEach(function (done) {
257
+ request(optionsCreation, done);
258
+ });
259
+
260
+ it('should remove it from the database', function (done) {
261
+ request(optionsDelete, function (error, response, body) {
262
+ iotAgentDb
263
+ .db()
264
+ .collection('groups')
265
+ .find({})
266
+ .toArray(function (err, docs) {
267
+ should.not.exist(err);
268
+ should.exist(docs);
269
+ should.exist(docs.length);
270
+ docs.length.should.equal(0);
271
+ done();
272
+ });
273
+ });
274
+ });
275
+
276
+ it('should return a 204 OK statusCode', function (done) {
277
+ request(optionsDelete, function (error, response, body) {
278
+ response.statusCode.should.equal(204);
279
+ done();
280
+ });
281
+ });
282
+ });
283
+
284
+ describe('When a device group update request arrives', function () {
285
+ beforeEach(function (done) {
286
+ request(optionsCreation, done);
287
+ });
288
+
289
+ it('should update the values in the database', function (done) {
290
+ request(optionsUpdate, function (error, response, body) {
291
+ iotAgentDb
292
+ .db()
293
+ .collection('groups')
294
+ .find({})
295
+ .toArray(function (err, docs) {
296
+ should.not.exist(err);
297
+ should.exist(docs);
298
+ should.exist(docs[0].cbHost);
299
+ docs[0].cbHost.should.equal('http://anotherUnexistentHost:1026');
300
+ should.exist(docs[0].staticAttributes);
301
+ docs[0].staticAttributes.length.should.equal(1);
302
+ done();
303
+ });
304
+ });
305
+ });
306
+ });
307
+
308
+ describe('When a multiple device group creation arrives', function () {
309
+ const optionsMultipleCreation = _.clone(optionsCreation);
310
+
311
+ beforeEach(function (done) {
312
+ optionsMultipleCreation.json = utils.readExampleFile(
313
+ './test/unit/examples/groupProvisioningRequests/multipleGroupsCreation.json'
314
+ );
315
+
316
+ done();
317
+ });
318
+
319
+ it('should create the values in the database', function (done) {
320
+ request(optionsMultipleCreation, function (error, response, body) {
321
+ iotAgentDb
322
+ .db()
323
+ .collection('groups')
324
+ .find({})
325
+ .toArray(function (err, docs) {
326
+ should.not.exist(err);
327
+ should.exist(docs);
328
+ docs.length.should.equal(2);
329
+ done();
330
+ });
331
+ });
332
+ });
333
+ });
334
+
335
+ describe('When a device group listing request arrives', function () {
336
+ beforeEach(function (done) {
337
+ const optionsCreation1 = _.clone(optionsCreation);
338
+ const optionsCreation2 = _.clone(optionsCreation);
339
+ const optionsCreation3 = _.clone(optionsCreation);
340
+
341
+ optionsCreation2.json = { services: [] };
342
+ optionsCreation3.json = { services: [] };
343
+
344
+ optionsCreation2.json.services[0] = _.clone(optionsCreation.json.services[0]);
345
+ optionsCreation3.json.services[0] = _.clone(optionsCreation.json.services[0]);
346
+
347
+ optionsCreation2.json.services[0].apikey = 'qwertyuiop';
348
+ optionsCreation3.json.services[0].apikey = 'lkjhgfds';
349
+
350
+ async.series(
351
+ [
352
+ async.apply(request, optionsCreation1),
353
+ async.apply(request, optionsCreation2),
354
+ async.apply(request, optionsCreation3)
355
+ ],
356
+ done
357
+ );
358
+ });
359
+
360
+ it('should return all the configured device groups from the database', function (done) {
361
+ request(optionsList, function (error, response, body) {
362
+ body.count.should.equal(3);
363
+ done();
364
+ });
365
+ });
366
+ });
367
+
368
+ describe('When a device group listing arrives with a limit', function () {
369
+ const optionsConstrained = {
370
+ url: 'http://localhost:4041/iot/services',
371
+ method: 'GET',
372
+ qs: {
373
+ limit: 3,
374
+ offset: 2
375
+ },
376
+ json: {},
377
+ headers: {
378
+ 'fiware-service': 'testservice',
379
+ 'fiware-servicepath': '/*'
380
+ }
381
+ };
382
+
383
+ beforeEach(function (done) {
384
+ const optionsCreationList = [];
385
+ const creationFns = [];
386
+
387
+ for (let i = 0; i < 10; i++) {
388
+ optionsCreationList[i] = _.clone(optionsCreation);
389
+ optionsCreationList[i].json = { services: [] };
390
+ optionsCreationList[i].json.services[0] = _.clone(optionsCreation.json.services[0]);
391
+ optionsCreationList[i].json.services[0].apikey = 'qwertyuiop' + i;
392
+ creationFns.push(async.apply(request, optionsCreationList[i]));
393
+ }
394
+
395
+ async.series(creationFns, done);
396
+ });
397
+
398
+ it('should return the appropriate count of services', function (done) {
399
+ request(optionsConstrained, function (error, response, body) {
400
+ body.count.should.equal(10);
401
+ done();
402
+ });
403
+ });
404
+ });
405
+
406
+ describe('When a device info request arrives', function () {
407
+ beforeEach(function (done) {
408
+ async.series([async.apply(request, optionsCreation)], done);
409
+ });
410
+
411
+ it('should return all the configured device groups from the database', function (done) {
412
+ request(optionsGet, function (error, response, body) {
413
+ should.exist(body);
414
+ should.exist(body.count);
415
+ body.count.should.equal(1);
416
+ should.exist(body.services);
417
+ should.exist(body.services.length);
418
+ body.services.length.should.equal(1);
419
+ body.services[0].service.should.equal('testservice');
420
+ done();
421
+ });
422
+ });
423
+ });
424
+
425
+ describe('When a device info request arrives and multiple groups have been created', function () {
426
+ beforeEach(function (done) {
427
+ const optionsCreationList = [];
428
+ const creationFns = [];
429
+
430
+ for (let i = 0; i < 10; i++) {
431
+ optionsCreationList[i] = _.clone(optionsCreation);
432
+ optionsCreationList[i].json = { services: [] };
433
+ optionsCreationList[i].json.services[0] = _.clone(optionsCreation.json.services[0]);
434
+ optionsCreationList[i].json.services[0].apikey = 'qwertyuiop' + i;
435
+ creationFns.push(async.apply(request, optionsCreationList[i]));
436
+ }
437
+
438
+ async.series(creationFns, done);
439
+ });
440
+
441
+ it('should return all the configured device groups from the database', function (done) {
442
+ request(optionsGet, function (error, response, body) {
443
+ should.exist(body);
444
+ should.exist(body.count);
445
+ body.count.should.equal(10);
446
+ should.exist(body.services);
447
+ should.exist(body.services.length);
448
+ body.services.length.should.equal(10);
449
+ done();
450
+ });
451
+ });
452
+ });
453
+
454
+ describe('When the device info request with name and type', function () {
455
+ beforeEach(function (done) {
456
+ async.series([async.apply(request, optionsCreation)], done);
457
+ });
458
+
459
+ afterEach(function (done) {
460
+ iotAgentLib.clearRegistry(done);
461
+ });
462
+
463
+ it('should return the name and type of device', function (done) {
464
+ request(optionsGet, function (error, response, body) {
465
+ should.exist(body);
466
+ should.exist(body.count);
467
+ body.count.should.equal(1);
468
+ should.exist(body.services);
469
+ should.exist(body.services.length);
470
+ body.services.length.should.equal(1);
471
+ should.exist(body.services[0].entity_type);
472
+ body.services[0].entity_type.should.equal('Light');
473
+ done();
474
+ });
475
+ });
476
+ });
477
+ });
@@ -1,6 +1,8 @@
1
1
  [
2
2
  {
3
3
  "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:WeatherStation:ws1",
5
+ "type": "WeatherStation",
4
6
  "pressure": {
5
7
  "type": "Property",
6
8
  "value": 1040
@@ -9,10 +11,8 @@
9
11
  "type": "Property",
10
12
  "value": {
11
13
  "@type": "Summary",
12
- "@value": "Humidity NaN and pressure 1040"
14
+ "@value": "Humidity NaN and pressure 20800"
13
15
  }
14
- },
15
- "id": "urn:ngsi-ld:WeatherStation:ws1",
16
- "type": "WeatherStation"
16
+ }
17
17
  }
18
18
  ]
@@ -1,25 +1,25 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "humidity": {
5
- "type": "Property",
6
- "value": {
7
- "@type": "Percentage",
8
- "@value": "12"
9
- }
10
- },
11
- "id": "urn:ngsi-ld:WeatherStation:ws1",
12
- "pressure": {
13
- "type": "Property",
14
- "value": 1040
15
- },
16
- "type": "WeatherStation",
17
- "weather": {
18
- "type": "Property",
19
- "value": {
20
- "@type": "Summary",
21
- "@value": "Humidity 6 and pressure 1040"
22
- }
23
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:WeatherStation:ws1",
5
+ "type": "WeatherStation",
6
+ "pressure": {
7
+ "type": "Property",
8
+ "value": 1040
9
+ },
10
+ "humidity": {
11
+ "type": "Property",
12
+ "value": {
13
+ "@type": "Percentage",
14
+ "@value": "12"
15
+ }
16
+ },
17
+ "weather": {
18
+ "type": "Property",
19
+ "value": {
20
+ "@type": "Summary",
21
+ "@value": "Humidity 6 and pressure 20800"
22
+ }
24
23
  }
24
+ }
25
25
  ]
@@ -1,6 +1,8 @@
1
1
  [
2
2
  {
3
3
  "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:WeatherStation:ws1",
5
+ "type": "WeatherStation",
4
6
  "pressure": {
5
7
  "type": "Property",
6
8
  "value": 1040
@@ -9,10 +11,8 @@
9
11
  "type": "Property",
10
12
  "value": {
11
13
  "@type": "Summary",
12
- "@value": "Humidity NaN and pressure 1040"
14
+ "@value": "Humidity NaN and pressure 20800"
13
15
  }
14
- },
15
- "id": "urn:ngsi-ld:WeatherStation:ws1",
16
- "type": "WeatherStation"
16
+ }
17
17
  }
18
18
  ]
@@ -1,18 +1,17 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:GPS:gps1",
5
- "type": "GPS",
6
- "location": {
7
- "type": "GeoProperty",
8
- "value": {
9
- "coordinates": [
10
- 13,
11
- 52
12
- ],
13
- "type": "Point"
14
- },
15
- "observedAt": "1970-01-01T00:00:00.001Z"
16
- }
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:GPS:gps1",
5
+ "type": "GPS",
6
+ "location": {
7
+ "type": "GeoProperty",
8
+ "value": {
9
+ "coordinates": [
10
+ 13,
11
+ 52
12
+ ],
13
+ "type": "Point"
14
+ }
17
15
  }
16
+ }
18
17
  ]
@@ -1,26 +1,26 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:WeatherStation:ws4",
5
- "pressure": {
6
- "type": "Property",
7
- "value": {
8
- "@type": "Hgmm",
9
- "@value": "52"
10
- }
11
- },
12
- "type": "WeatherStation"
13
- },
14
- {
15
- "@context": "http://context.json-ld",
16
- "humidity": {
17
- "type": "Property",
18
- "value": {
19
- "@type": "Percentage",
20
- "@value": "12"
21
- }
22
- },
23
- "id": "urn:ngsi-ld:Higrometer:Higro2000",
24
- "type": "Higrometer"
2
+ {
3
+ "@context": "http://context.json-ld",
4
+ "id": "urn:ngsi-ld:WeatherStation:ws4",
5
+ "type": "WeatherStation",
6
+ "pressure": {
7
+ "type": "Property",
8
+ "value": {
9
+ "@type": "Hgmm",
10
+ "@value": "52"
11
+ }
25
12
  }
13
+ },
14
+ {
15
+ "@context": "http://context.json-ld",
16
+ "id": "urn:ngsi-ld:Higrometer:Higro2000",
17
+ "type": "Higrometer",
18
+ "humidity": {
19
+ "type": "Property",
20
+ "value": {
21
+ "@type": "Percentage",
22
+ "@value": "12"
23
+ }
24
+ }
25
+ }
26
26
  ]
@@ -1,9 +1,4 @@
1
1
  [
2
- {
3
- "@context": "http://context.json-ld",
4
- "id": "urn:ngsi-ld:GPS:gps1",
5
- "type": "GPS"
6
- },
7
2
  {
8
3
  "@context": "http://context.json-ld",
9
4
  "explicit": {