iotagent-node-lib 2.23.0 → 2.24.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/.nyc_output/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +1 -0
- package/.nyc_output/processinfo/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -1
- package/CHANGES_NEXT_RELEASE +0 -2
- package/doc/advanced-topics.md +55 -2
- package/doc/architecture.md +52 -5
- package/doc/expressionLanguage.md +2 -1
- package/doc/usermanual.md +18 -16
- package/lib/errors.js +9 -1
- package/lib/plugins/bidirectionalData.js +104 -6
- package/lib/plugins/expressionPlugin.js +10 -0
- package/lib/plugins/pluginUtils.js +2 -1
- package/lib/request-shim.js +2 -1
- package/lib/services/devices/deviceService.js +34 -20
- package/lib/services/ngsi/entities-NGSI-v2.js +14 -4
- package/lib/services/northBound/contextServer-NGSI-LD.js +96 -20
- package/lib/services/northBound/contextServer-NGSI-v2.js +1 -0
- package/package.json +1 -1
- package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +51 -0
- package/test/unit/mongodb/mongodb-group-registry-test.js +24 -0
- package/test/unit/mongodb/mongodb-registry-test.js +49 -0
- package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json +21 -0
- package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +17 -0
- package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +656 -2
- package/test/unit/ngsi-ld/ngsiService/unsupported-endpoints-test.js +111 -0
- package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +221 -0
- package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +19 -0
- package/test/unit/ngsiv2/lazyAndCommands/command-test.js +106 -0
- package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +115 -0
- package/.nyc_output/6e3d7795-bf8c-4a50-bd2f-f8221f27aeae.json +0 -1
- package/.nyc_output/processinfo/6e3d7795-bf8c-4a50-bd2f-f8221f27aeae.json +0 -1
- package/config +0 -0
- package/docker/Mosquitto/Dockerfile.debian +0 -38
- package/docker/Mosquitto/Dockerfile.debian~ +0 -23
- package/lib/plugins/multiEntity.js_avg2 +0 -343
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js_avg2 +0 -1224
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 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::daniel.moranjimenez@telefonica.com
|
|
22
|
+
*
|
|
23
|
+
* Modified by: Jason Fox - FIWARE Foundation
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/* eslint-disable no-unused-vars */
|
|
27
|
+
|
|
28
|
+
const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
|
|
29
|
+
const utils = require('../../../tools/utils');
|
|
30
|
+
const request = utils.request;
|
|
31
|
+
const should = require('should');
|
|
32
|
+
|
|
33
|
+
let contextBrokerMock;
|
|
34
|
+
const iotAgentConfig = {
|
|
35
|
+
contextBroker: {
|
|
36
|
+
host: '192.168.1.1',
|
|
37
|
+
port: '1026',
|
|
38
|
+
ngsiVersion: 'ld',
|
|
39
|
+
jsonLdContext: 'http://context.json-ld'
|
|
40
|
+
},
|
|
41
|
+
server: {
|
|
42
|
+
port: 4041
|
|
43
|
+
},
|
|
44
|
+
types: {},
|
|
45
|
+
service: 'smartgondor',
|
|
46
|
+
subservice: 'gardens',
|
|
47
|
+
providerUrl: 'http://smartgondor.com'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
describe('NGSI-LD - Unsupported Endpoints', function () {
|
|
51
|
+
beforeEach(function (done) {
|
|
52
|
+
iotAgentLib.activate(iotAgentConfig, function () {
|
|
53
|
+
iotAgentLib.clearAll(function () {
|
|
54
|
+
done();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(function (done) {
|
|
60
|
+
iotAgentLib.clearAll(function () {
|
|
61
|
+
iotAgentLib.deactivate(done);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('When accessing an Unsupported Endpoint', function () {
|
|
66
|
+
it('GET /entities should return a valid NSGI-LD error message', function (done) {
|
|
67
|
+
const options = {
|
|
68
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/ngsi-ld/v1/entities',
|
|
69
|
+
method: 'GET'
|
|
70
|
+
};
|
|
71
|
+
request(options, function (error, response, body) {
|
|
72
|
+
response.statusCode.should.equal(501);
|
|
73
|
+
done();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
it('POST /entities should return a valid NSGI-LD error message', function (done) {
|
|
77
|
+
const options = {
|
|
78
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/ngsi-ld/v1/entities',
|
|
79
|
+
method: 'POST',
|
|
80
|
+
json: {}
|
|
81
|
+
};
|
|
82
|
+
request(options, function (error, response, body) {
|
|
83
|
+
response.statusCode.should.equal(501);
|
|
84
|
+
done();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
it('DELETE /entities/<entity-id> should return a valid NSGI-LD error message', function (done) {
|
|
88
|
+
const options = {
|
|
89
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/ngsi-ld/v1/entities/urn:ngsi-ld:entity',
|
|
90
|
+
method: 'DELETE'
|
|
91
|
+
};
|
|
92
|
+
request(options, function (error, response, body) {
|
|
93
|
+
response.statusCode.should.equal(501);
|
|
94
|
+
done();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
it('DELETE /entities/<entity-id>/attrs/<attr-name> should return a valid NSGI-LD error message', function (done) {
|
|
98
|
+
const options = {
|
|
99
|
+
url:
|
|
100
|
+
'http://localhost:' +
|
|
101
|
+
iotAgentConfig.server.port +
|
|
102
|
+
'/ngsi-ld/v1/entities/urn:ngsi-ld:entity/attrs/att',
|
|
103
|
+
method: 'DELETE'
|
|
104
|
+
};
|
|
105
|
+
request(options, function (error, response, body) {
|
|
106
|
+
response.statusCode.should.equal(501);
|
|
107
|
+
done();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -264,6 +264,227 @@ describe('NGSI-LD - Bidirectional data plugin', function () {
|
|
|
264
264
|
});
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
+
describe('When a notification with metadata arrives for a bidirectional attribute', function () {
|
|
268
|
+
const notificationOptions = {
|
|
269
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
|
|
270
|
+
method: 'POST',
|
|
271
|
+
json: utils.readExampleFile(
|
|
272
|
+
'./test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json'
|
|
273
|
+
),
|
|
274
|
+
headers: {
|
|
275
|
+
'fiware-service': 'smartgondor',
|
|
276
|
+
'fiware-servicepath': '/gardens'
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
let executedHandler = false;
|
|
280
|
+
|
|
281
|
+
beforeEach(function () {
|
|
282
|
+
contextBrokerMock
|
|
283
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
284
|
+
.post(
|
|
285
|
+
'/ngsi-ld/v1/subscriptions/',
|
|
286
|
+
utils.readExampleFile(
|
|
287
|
+
'./test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json'
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
.reply(201, null, { Location: '/ngsi-ld/v1/subscriptions/51c0ac9ed714fb3b37d7d5a8' });
|
|
291
|
+
|
|
292
|
+
contextBrokerMock
|
|
293
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
294
|
+
.post(
|
|
295
|
+
'/ngsi-ld/v1/entityOperations/upsert/',
|
|
296
|
+
utils.readExampleFile('./test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json')
|
|
297
|
+
)
|
|
298
|
+
.reply(204);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
afterEach(function () {
|
|
302
|
+
iotAgentLib.setNotificationHandler();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should execute the original handler', function (done) {
|
|
306
|
+
function mockedHandler(device, notification, callback) {
|
|
307
|
+
notification[0].name.should.equal('location');
|
|
308
|
+
notification[0].value.should.equal('12.4, -9.6');
|
|
309
|
+
notification[0].metadata.qos.value.should.equal(1);
|
|
310
|
+
executedHandler = true;
|
|
311
|
+
callback();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
315
|
+
|
|
316
|
+
request(options, function (error, response, body) {
|
|
317
|
+
request(notificationOptions, function (error, response, body) {
|
|
318
|
+
executedHandler.should.equal(true);
|
|
319
|
+
contextBrokerMock.done();
|
|
320
|
+
done();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('should return a 200 OK', function (done) {
|
|
326
|
+
function mockedHandler(device, notification, callback) {
|
|
327
|
+
executedHandler = true;
|
|
328
|
+
callback();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
332
|
+
|
|
333
|
+
request(options, function (error, response, body) {
|
|
334
|
+
request(notificationOptions, function (error, response, body) {
|
|
335
|
+
response.statusCode.should.equal(200);
|
|
336
|
+
contextBrokerMock.done();
|
|
337
|
+
done();
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('should return the transformed values', function (done) {
|
|
343
|
+
let transformedHandler = false;
|
|
344
|
+
|
|
345
|
+
function mockedHandler(device, values, callback) {
|
|
346
|
+
let latitudeFound = false;
|
|
347
|
+
let longitudeFound = false;
|
|
348
|
+
|
|
349
|
+
for (let i = 0; i < values.length; i++) {
|
|
350
|
+
if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') {
|
|
351
|
+
latitudeFound = true;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (values[i].name === 'longitude' && values[i].type === 'string' && values[i].value === '12.4') {
|
|
355
|
+
longitudeFound = true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
transformedHandler = values.length >= 2 && longitudeFound && latitudeFound;
|
|
360
|
+
callback();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
364
|
+
|
|
365
|
+
request(options, function (error, response, body) {
|
|
366
|
+
request(notificationOptions, function (error, response, body) {
|
|
367
|
+
contextBrokerMock.done();
|
|
368
|
+
transformedHandler.should.equal(true);
|
|
369
|
+
done();
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe('When a sequential notification with datasetId arrives for a bidirectional attribute', function () {
|
|
376
|
+
const notificationOptions = {
|
|
377
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
|
|
378
|
+
method: 'POST',
|
|
379
|
+
json: utils.readExampleFile(
|
|
380
|
+
'./test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json'
|
|
381
|
+
),
|
|
382
|
+
headers: {
|
|
383
|
+
'fiware-service': 'smartgondor',
|
|
384
|
+
'fiware-servicepath': '/gardens'
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
let executedHandler = false;
|
|
388
|
+
|
|
389
|
+
beforeEach(function () {
|
|
390
|
+
contextBrokerMock
|
|
391
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
392
|
+
.post(
|
|
393
|
+
'/ngsi-ld/v1/subscriptions/',
|
|
394
|
+
utils.readExampleFile(
|
|
395
|
+
'./test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json'
|
|
396
|
+
)
|
|
397
|
+
)
|
|
398
|
+
.reply(201, null, { Location: '/ngsi-ld/v1/subscriptions/51c0ac9ed714fb3b37d7d5a8' });
|
|
399
|
+
|
|
400
|
+
contextBrokerMock
|
|
401
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
402
|
+
.post(
|
|
403
|
+
'/ngsi-ld/v1/entityOperations/upsert/',
|
|
404
|
+
utils.readExampleFile('./test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json')
|
|
405
|
+
)
|
|
406
|
+
.reply(204);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
afterEach(function () {
|
|
410
|
+
iotAgentLib.setNotificationHandler();
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('should execute the original handler', function (done) {
|
|
414
|
+
function mockedHandler(device, notification, callback) {
|
|
415
|
+
notification[0].name.should.equal('location');
|
|
416
|
+
notification[0].value.should.equal('12.4, -9.6');
|
|
417
|
+
notification[0].datasetId.should.equal('urn:ngsi-ld:Property:do-this');
|
|
418
|
+
|
|
419
|
+
notification[1].name.should.equal('location');
|
|
420
|
+
notification[1].value.should.equal('6, 10');
|
|
421
|
+
notification[1].datasetId.should.equal('urn:ngsi-ld:Property:then-do-this');
|
|
422
|
+
|
|
423
|
+
executedHandler = true;
|
|
424
|
+
callback();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
428
|
+
|
|
429
|
+
request(options, function (error, response, body) {
|
|
430
|
+
request(notificationOptions, function (error, response, body) {
|
|
431
|
+
executedHandler.should.equal(true);
|
|
432
|
+
contextBrokerMock.done();
|
|
433
|
+
done();
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should return a 200 OK', function (done) {
|
|
439
|
+
function mockedHandler(device, notification, callback) {
|
|
440
|
+
executedHandler = true;
|
|
441
|
+
callback();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
445
|
+
|
|
446
|
+
request(options, function (error, response, body) {
|
|
447
|
+
request(notificationOptions, function (error, response, body) {
|
|
448
|
+
response.statusCode.should.equal(200);
|
|
449
|
+
contextBrokerMock.done();
|
|
450
|
+
done();
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it('should return the transformed values', function (done) {
|
|
456
|
+
let transformedHandler = false;
|
|
457
|
+
|
|
458
|
+
function mockedHandler(device, values, callback) {
|
|
459
|
+
let latitudeFound = false;
|
|
460
|
+
let longitudeFound = false;
|
|
461
|
+
|
|
462
|
+
for (let i = 0; i < values.length; i++) {
|
|
463
|
+
if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') {
|
|
464
|
+
latitudeFound = true;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (values[i].name === 'longitude' && values[i].type === 'string' && values[i].value === '12.4') {
|
|
468
|
+
longitudeFound = true;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
transformedHandler = values.length >= 2 && longitudeFound && latitudeFound;
|
|
473
|
+
callback();
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
477
|
+
|
|
478
|
+
request(options, function (error, response, body) {
|
|
479
|
+
request(notificationOptions, function (error, response, body) {
|
|
480
|
+
contextBrokerMock.done();
|
|
481
|
+
transformedHandler.should.equal(true);
|
|
482
|
+
done();
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
267
488
|
describe('When a new Group provisioning request arrives with bidirectional attributes', function () {
|
|
268
489
|
const provisionGroup = {
|
|
269
490
|
url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services',
|
package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subscriptionId": "51c0ac9ed714fb3b37d7d5a8",
|
|
3
|
+
"data": [
|
|
4
|
+
{
|
|
5
|
+
"location": {
|
|
6
|
+
"type": "geo:point",
|
|
7
|
+
"value": "12.4, -9.6",
|
|
8
|
+
"metadata": {
|
|
9
|
+
"qos": {
|
|
10
|
+
"type": "Number",
|
|
11
|
+
"value": 1
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"type": "TheLightType",
|
|
16
|
+
"id": "TheFirstLight"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -311,4 +311,110 @@ describe('NGSI-v2 - Command functionalities', function () {
|
|
|
311
311
|
});
|
|
312
312
|
});
|
|
313
313
|
});
|
|
314
|
+
|
|
315
|
+
describe('When a command update with metadata arrives to the IoT Agent as Context Provider', function () {
|
|
316
|
+
const options = {
|
|
317
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update',
|
|
318
|
+
method: 'POST',
|
|
319
|
+
json: {
|
|
320
|
+
actionType: 'update',
|
|
321
|
+
entities: [
|
|
322
|
+
{
|
|
323
|
+
id: 'Robot:r2d2',
|
|
324
|
+
type: 'Robot',
|
|
325
|
+
position: {
|
|
326
|
+
type: 'Array',
|
|
327
|
+
value: '[28, -104, 23]',
|
|
328
|
+
metadata: {
|
|
329
|
+
qos: 1
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
headers: {
|
|
336
|
+
'fiware-service': 'smartgondor',
|
|
337
|
+
'fiware-servicepath': 'gardens'
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
beforeEach(function (done) {
|
|
342
|
+
iotAgentLib.register(device3, function (error) {
|
|
343
|
+
done();
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should call the client handler once including metadata', function (done) {
|
|
348
|
+
let handlerCalled = 0;
|
|
349
|
+
|
|
350
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
351
|
+
id.should.equal(device3.type + ':' + device3.id);
|
|
352
|
+
type.should.equal(device3.type);
|
|
353
|
+
attributes[0].name.should.equal('position');
|
|
354
|
+
attributes[0].value.should.equal('[28, -104, 23]');
|
|
355
|
+
attributes[0].metadata.qos.should.equal(1);
|
|
356
|
+
handlerCalled++;
|
|
357
|
+
callback(null, {
|
|
358
|
+
id,
|
|
359
|
+
type,
|
|
360
|
+
attributes: [
|
|
361
|
+
{
|
|
362
|
+
name: 'position',
|
|
363
|
+
type: 'Array',
|
|
364
|
+
value: '[28, -104, 23]'
|
|
365
|
+
}
|
|
366
|
+
]
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
request(options, function (error, response, body) {
|
|
371
|
+
should.not.exist(error);
|
|
372
|
+
handlerCalled.should.equal(1);
|
|
373
|
+
done();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
it('should create the attribute with the "_status" prefix in the Context Broker', function (done) {
|
|
377
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
378
|
+
callback(null, {
|
|
379
|
+
id,
|
|
380
|
+
type,
|
|
381
|
+
attributes: [
|
|
382
|
+
{
|
|
383
|
+
name: 'position',
|
|
384
|
+
type: 'Array',
|
|
385
|
+
value: '[28, -104, 23]'
|
|
386
|
+
}
|
|
387
|
+
]
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
request(options, function (error, response, body) {
|
|
392
|
+
should.not.exist(error);
|
|
393
|
+
done();
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
it('should create the attribute with the "_status" prefix in the Context Broker', function (done) {
|
|
397
|
+
let serviceAndSubservice = false;
|
|
398
|
+
|
|
399
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
400
|
+
serviceAndSubservice = service === 'smartgondor' && subservice === 'gardens';
|
|
401
|
+
callback(null, {
|
|
402
|
+
id,
|
|
403
|
+
type,
|
|
404
|
+
attributes: [
|
|
405
|
+
{
|
|
406
|
+
name: 'position',
|
|
407
|
+
type: 'Array',
|
|
408
|
+
value: '[28, -104, 23]'
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
request(options, function (error, response, body) {
|
|
415
|
+
serviceAndSubservice.should.equal(true);
|
|
416
|
+
done();
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
});
|
|
314
420
|
});
|
|
@@ -237,6 +237,120 @@ describe('NGSI-v2 - Bidirectional data plugin', function () {
|
|
|
237
237
|
});
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
+
it('should return the transformed values', function (done) {
|
|
241
|
+
let transformedHandler = false;
|
|
242
|
+
|
|
243
|
+
function mockedHandler(device, values, callback) {
|
|
244
|
+
|
|
245
|
+
let latitudeFound = false;
|
|
246
|
+
let longitudeFound = false;
|
|
247
|
+
|
|
248
|
+
for (let i = 0; i < values.length; i++) {
|
|
249
|
+
if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') {
|
|
250
|
+
latitudeFound = true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (values[i].name === 'longitude' && values[i].type === 'string' && values[i].value === '12.4') {
|
|
254
|
+
longitudeFound = true;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
transformedHandler = values.length >= 2 && longitudeFound && latitudeFound;
|
|
259
|
+
callback();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
263
|
+
|
|
264
|
+
request(options, function (error, response, body) {
|
|
265
|
+
request(notificationOptions, function (error, response, body) {
|
|
266
|
+
contextBrokerMock.done();
|
|
267
|
+
transformedHandler.should.equal(true);
|
|
268
|
+
done();
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
describe('When a notification with metadata arrives for a bidirectional attribute', function () {
|
|
276
|
+
const notificationOptions = {
|
|
277
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
|
|
278
|
+
method: 'POST',
|
|
279
|
+
json: utils.readExampleFile(
|
|
280
|
+
'./test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json'
|
|
281
|
+
),
|
|
282
|
+
headers: {
|
|
283
|
+
'fiware-service': 'smartgondor',
|
|
284
|
+
'fiware-servicepath': '/gardens'
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
let executedHandler = false;
|
|
288
|
+
|
|
289
|
+
beforeEach(function () {
|
|
290
|
+
contextBrokerMock
|
|
291
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
292
|
+
.matchHeader('fiware-servicepath', '/gardens')
|
|
293
|
+
.post(
|
|
294
|
+
'/v2/subscriptions',
|
|
295
|
+
utils.readExampleFile(
|
|
296
|
+
'./test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json'
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
.reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' });
|
|
300
|
+
|
|
301
|
+
contextBrokerMock
|
|
302
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
303
|
+
.matchHeader('fiware-servicepath', '/gardens')
|
|
304
|
+
.post(
|
|
305
|
+
'/v2/entities?options=upsert',
|
|
306
|
+
utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')
|
|
307
|
+
)
|
|
308
|
+
.reply(204);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
afterEach(function () {
|
|
312
|
+
iotAgentLib.setNotificationHandler();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('should execute the original handler', function (done) {
|
|
316
|
+
function mockedHandler(device, notification, callback) {
|
|
317
|
+
|
|
318
|
+
notification[0].name.should.equal('location');
|
|
319
|
+
notification[0].value.should.equal('12.4, -9.6');
|
|
320
|
+
notification[0].metadata.qos.value.should.equal(1);
|
|
321
|
+
|
|
322
|
+
executedHandler = true;
|
|
323
|
+
callback();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
327
|
+
|
|
328
|
+
request(options, function (error, response, body) {
|
|
329
|
+
request(notificationOptions, function (error, response, body) {
|
|
330
|
+
executedHandler.should.equal(true);
|
|
331
|
+
contextBrokerMock.done();
|
|
332
|
+
done();
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('should return a 200 OK', function (done) {
|
|
338
|
+
function mockedHandler(device, notification, callback) {
|
|
339
|
+
executedHandler = true;
|
|
340
|
+
callback();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
iotAgentLib.setNotificationHandler(mockedHandler);
|
|
344
|
+
|
|
345
|
+
request(options, function (error, response, body) {
|
|
346
|
+
request(notificationOptions, function (error, response, body) {
|
|
347
|
+
response.statusCode.should.equal(200);
|
|
348
|
+
contextBrokerMock.done();
|
|
349
|
+
done();
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
240
354
|
it('should return the transformed values', function (done) {
|
|
241
355
|
let transformedHandler = false;
|
|
242
356
|
|
|
@@ -270,6 +384,7 @@ describe('NGSI-v2 - Bidirectional data plugin', function () {
|
|
|
270
384
|
});
|
|
271
385
|
});
|
|
272
386
|
|
|
387
|
+
|
|
273
388
|
describe('When a new Group provisioning request arrives with bidirectional attributes', function () {
|
|
274
389
|
const provisionGroup = {
|
|
275
390
|
url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services',
|