iotagent-node-lib 2.21.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/{76bc24ff-5fac-4b5a-997d-de2799342eb0.json → 33364de2-1199-4ec2-b33c-cae063ef8cc4.json} +1 -1
- package/.nyc_output/processinfo/index.json +1 -1
- package/CHANGES_NEXT_RELEASE +0 -1
- package/doc/Contribution.md +3 -3
- package/doc/advanced-topics.md +73 -9
- package/doc/api.md +7 -5
- package/doc/architecture.md +52 -5
- package/doc/expressionLanguage.md +18 -3
- package/doc/operations.md +8 -5
- package/doc/usermanual.md +18 -16
- package/docker/Mosquitto/Dockerfile +1 -1
- package/lib/errors.js +9 -1
- package/lib/model/Group.js +2 -1
- package/lib/model/dbConn.js +4 -0
- package/lib/plugins/bidirectionalData.js +104 -6
- package/lib/plugins/expressionPlugin.js +18 -7
- package/lib/plugins/multiEntity.js +42 -29
- package/lib/plugins/pluginUtils.js +17 -0
- package/lib/request-shim.js +2 -1
- package/lib/services/commands/commandService.js +29 -2
- package/lib/services/common/iotManagerService.js +2 -1
- package/lib/services/devices/deviceService.js +35 -9
- package/lib/services/groups/groupRegistryMongoDB.js +13 -12
- package/lib/services/ngsi/entities-NGSI-LD.js +7 -0
- package/lib/services/ngsi/entities-NGSI-v2.js +70 -11
- package/lib/services/ngsi/ngsiService.js +1 -1
- package/lib/services/northBound/contextServer-NGSI-LD.js +110 -15
- package/lib/services/northBound/contextServer-NGSI-v2.js +8 -3
- package/lib/services/northBound/contextServerUtils.js +9 -9
- package/lib/services/northBound/deviceProvisioningServer.js +2 -1
- package/lib/templates/createDevice.json +1 -2
- package/lib/templates/createDeviceLax.json +2 -3
- package/lib/templates/updateDevice.json +1 -2
- package/package.json +24 -24
- package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +14 -0
- package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +51 -0
- package/test/unit/mongodb/mongoDBUtils.js +2 -2
- package/test/unit/mongodb/mongodb-group-registry-test.js +25 -1
- package/test/unit/mongodb/mongodb-registry-test.js +51 -3
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgentCommands.json +2 -1
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextLanguageProperties1.json +15 -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 +995 -27
- package/test/unit/ngsi-ld/ngsiService/languageProperties-test.js +112 -0
- 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/ngsi-mixed/provisioning/ngsi-versioning-test.js +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json +8 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus2.json +6 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json +12 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json +27 -0
- package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +19 -0
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +10 -8
- package/test/unit/ngsiv2/lazyAndCommands/command-test.js +106 -0
- package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +151 -0
- package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +115 -0
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +63 -0
- package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +60 -0
- package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +2 -1
- package/.nyc_output/76bc24ff-5fac-4b5a-997d-de2799342eb0.json +0 -1
|
@@ -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
|
});
|
|
@@ -98,6 +98,18 @@ const iotAgentConfig = {
|
|
|
98
98
|
lazy: [],
|
|
99
99
|
staticAttributes: [],
|
|
100
100
|
active: []
|
|
101
|
+
},
|
|
102
|
+
RobotExp: {
|
|
103
|
+
commands: [
|
|
104
|
+
{
|
|
105
|
+
name: 'positionExp',
|
|
106
|
+
type: 'Array',
|
|
107
|
+
expression: '[22]'
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
lazy: [],
|
|
111
|
+
staticAttributes: [],
|
|
112
|
+
active: []
|
|
101
113
|
}
|
|
102
114
|
},
|
|
103
115
|
deviceRegistry: {
|
|
@@ -122,6 +134,14 @@ const device3 = {
|
|
|
122
134
|
subservice: 'gardens',
|
|
123
135
|
polling: true
|
|
124
136
|
};
|
|
137
|
+
const device4 = {
|
|
138
|
+
id: 'r2d4',
|
|
139
|
+
type: 'RobotExp',
|
|
140
|
+
service: 'smartgondor',
|
|
141
|
+
subservice: 'gardens',
|
|
142
|
+
polling: true,
|
|
143
|
+
expressionLanguage: 'jexl'
|
|
144
|
+
};
|
|
125
145
|
|
|
126
146
|
describe('NGSI-v2 - Polling commands', function () {
|
|
127
147
|
beforeEach(function (done) {
|
|
@@ -386,3 +406,134 @@ describe('NGSI-v2 - Polling commands', function () {
|
|
|
386
406
|
});
|
|
387
407
|
});
|
|
388
408
|
});
|
|
409
|
+
|
|
410
|
+
describe('NGSI-v2 - Polling commands expressions', function () {
|
|
411
|
+
beforeEach(function (done) {
|
|
412
|
+
logger.setLevel('FATAL');
|
|
413
|
+
|
|
414
|
+
nock.cleanAll();
|
|
415
|
+
|
|
416
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
417
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
418
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
419
|
+
.post('/v2/registrations')
|
|
420
|
+
.reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584m' });
|
|
421
|
+
|
|
422
|
+
contextBrokerMock
|
|
423
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
424
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
425
|
+
.post('/v2/entities?options=upsert')
|
|
426
|
+
.reply(204);
|
|
427
|
+
|
|
428
|
+
iotAgentConfig.pollingExpiration = 0;
|
|
429
|
+
iotAgentConfig.pollingDaemonFrequency = 0;
|
|
430
|
+
iotAgentLib.activate(iotAgentConfig, done);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
afterEach(function (done) {
|
|
434
|
+
delete device4.registrationId;
|
|
435
|
+
iotAgentLib.clearAll(function () {
|
|
436
|
+
iotAgentLib.deactivate(function () {
|
|
437
|
+
mongoUtils.cleanDbs(function () {
|
|
438
|
+
nock.cleanAll();
|
|
439
|
+
iotAgentLib.setDataUpdateHandler();
|
|
440
|
+
iotAgentLib.setCommandHandler();
|
|
441
|
+
done();
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe('When a command update arrives to the IoT Agent for a device with polling', function () {
|
|
448
|
+
const options = {
|
|
449
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update',
|
|
450
|
+
method: 'POST',
|
|
451
|
+
json: {
|
|
452
|
+
actionType: 'update',
|
|
453
|
+
entities: [
|
|
454
|
+
{
|
|
455
|
+
id: 'RobotExp:r2d4',
|
|
456
|
+
type: 'RobotExp',
|
|
457
|
+
positionExp: {
|
|
458
|
+
type: 'Array',
|
|
459
|
+
value: '[28, -104, 23]'
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
]
|
|
463
|
+
},
|
|
464
|
+
headers: {
|
|
465
|
+
'fiware-service': 'smartgondor',
|
|
466
|
+
'fiware-servicepath': 'gardens'
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
beforeEach(function (done) {
|
|
471
|
+
statusAttributeMock = nock('http://192.168.1.1:1026')
|
|
472
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
473
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
474
|
+
.patch(
|
|
475
|
+
'/v2/entities/RobotExp:r2d4/attrs?type=RobotExp',
|
|
476
|
+
utils.readExampleFile(
|
|
477
|
+
'./test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus2.json'
|
|
478
|
+
)
|
|
479
|
+
)
|
|
480
|
+
.reply(204);
|
|
481
|
+
|
|
482
|
+
iotAgentLib.register(device4, function (error) {
|
|
483
|
+
done();
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('should not call the client handler', function (done) {
|
|
488
|
+
let handlerCalled = false;
|
|
489
|
+
|
|
490
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
491
|
+
handlerCalled = true;
|
|
492
|
+
callback(null, {
|
|
493
|
+
id,
|
|
494
|
+
type,
|
|
495
|
+
attributes: [
|
|
496
|
+
{
|
|
497
|
+
name: 'positionExp',
|
|
498
|
+
type: 'Array',
|
|
499
|
+
value: '[28, -104, 23]'
|
|
500
|
+
}
|
|
501
|
+
]
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
request(options, function (error, response, body) {
|
|
506
|
+
should.not.exist(error);
|
|
507
|
+
handlerCalled.should.equal(false);
|
|
508
|
+
done();
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
it('should create the attribute with the "_status" prefix in the Context Broker', function (done) {
|
|
512
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
513
|
+
callback(null);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
request(options, function (error, response, body) {
|
|
517
|
+
should.not.exist(error);
|
|
518
|
+
statusAttributeMock.done();
|
|
519
|
+
done();
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
it('should store the commands in the queue', function (done) {
|
|
523
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
524
|
+
callback(null);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
request(options, function (error, response, body) {
|
|
528
|
+
iotAgentLib.commandQueue('smartgondor', 'gardens', 'r2d4', function (error, listCommands) {
|
|
529
|
+
should.not.exist(error);
|
|
530
|
+
listCommands.count.should.equal(1);
|
|
531
|
+
listCommands.commands[0].name.should.equal('positionExp');
|
|
532
|
+
listCommands.commands[0].type.should.equal('Array');
|
|
533
|
+
listCommands.commands[0].value[0].should.equal(22);
|
|
534
|
+
done();
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
});
|
|
@@ -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',
|
|
@@ -215,6 +215,31 @@ const iotAgentConfig = {
|
|
|
215
215
|
}
|
|
216
216
|
]
|
|
217
217
|
},
|
|
218
|
+
WeatherStation9: {
|
|
219
|
+
commands: [],
|
|
220
|
+
type: 'WeatherStation',
|
|
221
|
+
name: 'ws9b',
|
|
222
|
+
lazy: [],
|
|
223
|
+
active: [
|
|
224
|
+
{
|
|
225
|
+
object_id: 'p',
|
|
226
|
+
name: 'pressure',
|
|
227
|
+
type: 'Hgmm'
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
object_id: 'h',
|
|
231
|
+
name: 'humidity',
|
|
232
|
+
type: 'Percentage',
|
|
233
|
+
entity_type: 'Higrometer',
|
|
234
|
+
metadata: {
|
|
235
|
+
unitCode: {
|
|
236
|
+
type: 'Text',
|
|
237
|
+
value: 'Hgmm'
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
218
243
|
WeatherStation8Jexl: {
|
|
219
244
|
commands: [],
|
|
220
245
|
type: 'WeatherStation',
|
|
@@ -581,6 +606,44 @@ describe('NGSI-v2 - Multi-entity plugin', function () {
|
|
|
581
606
|
});
|
|
582
607
|
});
|
|
583
608
|
|
|
609
|
+
describe('When an update comes for a multientity measurement based on entity_type', function () {
|
|
610
|
+
const values = [
|
|
611
|
+
{
|
|
612
|
+
name: 'p',
|
|
613
|
+
type: 'centigrades',
|
|
614
|
+
value: '52'
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
name: 'h',
|
|
618
|
+
type: 'Percentage',
|
|
619
|
+
value: '12'
|
|
620
|
+
}
|
|
621
|
+
];
|
|
622
|
+
|
|
623
|
+
beforeEach(function () {
|
|
624
|
+
nock.cleanAll();
|
|
625
|
+
|
|
626
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
627
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
628
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
629
|
+
.post(
|
|
630
|
+
'/v2/op/update',
|
|
631
|
+
utils.readExampleFile(
|
|
632
|
+
'./test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json'
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
.reply(204);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
it('should send two context elements, one for each entity', function (done) {
|
|
639
|
+
iotAgentLib.update('ws9b', 'WeatherStation9', '', values, function (error) {
|
|
640
|
+
should.not.exist(error);
|
|
641
|
+
contextBrokerMock.done();
|
|
642
|
+
done();
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
|
|
584
647
|
describe('When an update comes for a multientity measurement with same attribute name', function () {
|
|
585
648
|
const values = [
|
|
586
649
|
{
|
|
@@ -705,6 +705,66 @@ describe('NGSI-v2 - Device provisioning API: Provision devices', function () {
|
|
|
705
705
|
}
|
|
706
706
|
);
|
|
707
707
|
|
|
708
|
+
describe('When a device provisioning request arrives to the IoTA and entityNameExp was configured at group level', function () {
|
|
709
|
+
const options = {
|
|
710
|
+
url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
|
|
711
|
+
method: 'POST',
|
|
712
|
+
json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json'),
|
|
713
|
+
headers: {
|
|
714
|
+
'fiware-service': 'smartgondor',
|
|
715
|
+
'fiware-servicepath': '/gardens'
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
const groupCreation = {
|
|
719
|
+
url: 'http://localhost:4041/iot/services',
|
|
720
|
+
method: 'POST',
|
|
721
|
+
json: {
|
|
722
|
+
services: [
|
|
723
|
+
{
|
|
724
|
+
resource: '/Thing',
|
|
725
|
+
apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
|
|
726
|
+
/*jshint camelcase: false */
|
|
727
|
+
entity_type: 'MicroLights',
|
|
728
|
+
entityNameExp: 'EntityNameByExp',
|
|
729
|
+
cbroker: 'http://192.168.1.1:1026'
|
|
730
|
+
}
|
|
731
|
+
]
|
|
732
|
+
},
|
|
733
|
+
headers: {
|
|
734
|
+
'fiware-service': 'smartgondor',
|
|
735
|
+
'fiware-servicepath': '/gardens'
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
beforeEach(function (done) {
|
|
740
|
+
nock.cleanAll();
|
|
741
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
742
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
743
|
+
.matchHeader('fiware-servicepath', '/gardens')
|
|
744
|
+
.post(
|
|
745
|
+
'/v2/entities?options=upsert',
|
|
746
|
+
utils.readExampleFile(
|
|
747
|
+
'./test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json'
|
|
748
|
+
)
|
|
749
|
+
)
|
|
750
|
+
.reply(204);
|
|
751
|
+
|
|
752
|
+
done();
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it('should store the entity name defined by expression', function (done) {
|
|
756
|
+
request(groupCreation, function (error, response, body) {
|
|
757
|
+
request(options, function (error, response, body) {
|
|
758
|
+
iotAgentLib.listDevices('smartgondor', '/gardens', function (error, results) {
|
|
759
|
+
should.exist(results.devices[0].name);
|
|
760
|
+
results.devices[0].name.should.equal('EntityNameByExp');
|
|
761
|
+
done();
|
|
762
|
+
});
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
708
768
|
describe(
|
|
709
769
|
'When a device provisioning request with static attributes arrives to the IoTA' +
|
|
710
770
|
' and same static attribute is also configured at group level',
|
|
@@ -484,10 +484,11 @@ describe('NGSI-v2 - Device provisioning API: Update provisioned devices', functi
|
|
|
484
484
|
|
|
485
485
|
it('should provision the explicitAttrs attribute appropriately', function (done) {
|
|
486
486
|
request(optionsUpdate, function (error, response, body) {
|
|
487
|
+
should.not.exist(error);
|
|
488
|
+
response.statusCode.should.equal(204);
|
|
487
489
|
request(optionsGetDevice, function (error, response, body) {
|
|
488
490
|
should.not.exist(error);
|
|
489
491
|
response.statusCode.should.equal(200);
|
|
490
|
-
|
|
491
492
|
body.explicitAttrs.should.equal(false);
|
|
492
493
|
done();
|
|
493
494
|
});
|