iotagent-node-lib 2.19.0 → 2.22.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 -0
- package/.readthedocs.yml +3 -1
- package/CHANGES_NEXT_RELEASE +1 -0
- package/README.md +5 -56
- package/doc/Contribution.md +3 -3
- package/doc/advanced-topics.md +8 -41
- package/doc/api.md +14 -3
- package/doc/expressionLanguage.md +17 -0
- package/doc/northboundinteractions.md +40 -33
- package/doc/operations.md +8 -5
- package/doc/requirements.txt +4 -0
- package/{docs → doc}/roadmap.md +21 -6
- package/doc/usermanual.md +4 -4
- package/docker/Mosquitto/Dockerfile +28 -12
- package/docker/Mosquitto/README.md +8 -7
- package/docker/Mosquitto/startMosquitto.sh +8 -0
- package/lib/fiware-iotagent-lib.js +1 -2
- package/lib/jexlTranformsMap.js +3 -1
- package/lib/model/Group.js +2 -1
- package/lib/model/dbConn.js +4 -0
- package/lib/plugins/expressionPlugin.js +56 -21
- package/lib/plugins/multiEntity.js +43 -49
- package/lib/plugins/pluginUtils.js +16 -0
- package/lib/services/commands/commandService.js +29 -2
- package/lib/services/common/domain.js +6 -2
- package/lib/services/common/iotManagerService.js +2 -1
- package/lib/services/devices/deviceRegistryMemory.js +13 -2
- package/lib/services/devices/deviceRegistryMongoDB.js +15 -7
- package/lib/services/devices/deviceService.js +52 -16
- package/lib/services/groups/groupRegistryMongoDB.js +13 -12
- package/lib/services/ngsi/entities-NGSI-LD.js +13 -4
- package/lib/services/ngsi/entities-NGSI-v2.js +8 -6
- package/lib/services/ngsi/ngsiService.js +3 -3
- package/lib/services/northBound/contextServer-NGSI-LD.js +20 -1
- package/lib/services/northBound/contextServer-NGSI-v2.js +39 -30
- package/lib/services/northBound/contextServerUtils.js +10 -10
- package/lib/services/northBound/deviceProvisioningServer.js +4 -1
- package/lib/templates/createDevice.json +13 -2
- package/lib/templates/createDeviceLax.json +2 -3
- package/lib/templates/updateDevice.json +13 -2
- package/package.json +27 -33
- package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +14 -0
- package/test/unit/mongodb/mongoDBUtils.js +2 -2
- package/test/unit/mongodb/mongodb-group-registry-test.js +1 -1
- package/test/unit/mongodb/mongodb-registry-test.js +2 -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/lazyAndCommands/command-test.js +315 -1
- package/test/unit/ngsi-ld/ngsiService/languageProperties-test.js +112 -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/updateContextExpressionPlugin35.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json +1 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json +27 -0
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +63 -2
- package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +151 -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/bin/agentConsole.js +0 -257
- package/bin/iotAgentTester.js +0 -44
- package/lib/command/commandLine.js +0 -918
- package/lib/command/migration.js +0 -176
- package/test/unit/general/migration-test.js +0 -257
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"actionType": "update",
|
|
3
|
+
"entities": [
|
|
4
|
+
{
|
|
5
|
+
"id": "ws9b",
|
|
6
|
+
"type": "WeatherStation",
|
|
7
|
+
"pressure": {
|
|
8
|
+
"type": "Hgmm",
|
|
9
|
+
"value": "52"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"humidity": {
|
|
14
|
+
"type": "Percentage",
|
|
15
|
+
"value": "12",
|
|
16
|
+
"metadata": {
|
|
17
|
+
"unitCode": {
|
|
18
|
+
"type": "Text",
|
|
19
|
+
"value": "Hgmm"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"type": "Higrometer",
|
|
24
|
+
"id": "ws9b"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -319,7 +319,7 @@ const iotAgentConfig = {
|
|
|
319
319
|
expression: "{coordinates: [lon,lat], type: 'Point'}"
|
|
320
320
|
}
|
|
321
321
|
],
|
|
322
|
-
explicitAttrs:
|
|
322
|
+
explicitAttrs: "[ 'myattr' ]"
|
|
323
323
|
},
|
|
324
324
|
GPS6: {
|
|
325
325
|
commands: [],
|
|
@@ -345,6 +345,30 @@ const iotAgentConfig = {
|
|
|
345
345
|
}
|
|
346
346
|
],
|
|
347
347
|
explicitAttrs: true
|
|
348
|
+
},
|
|
349
|
+
GPS7: {
|
|
350
|
+
commands: [],
|
|
351
|
+
type: 'GPS',
|
|
352
|
+
lazy: [],
|
|
353
|
+
static: [
|
|
354
|
+
{
|
|
355
|
+
name: 'color',
|
|
356
|
+
type: 'string',
|
|
357
|
+
value: 'blue'
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
active: [
|
|
361
|
+
{
|
|
362
|
+
name: 'price',
|
|
363
|
+
type: 'number'
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
name: 'location',
|
|
367
|
+
type: 'geo:json',
|
|
368
|
+
expression: "{coordinates: [lon,lat], type: 'Point'}"
|
|
369
|
+
}
|
|
370
|
+
],
|
|
371
|
+
explicitAttrs: '[ ]'
|
|
348
372
|
}
|
|
349
373
|
},
|
|
350
374
|
service: 'smartgondor',
|
|
@@ -1180,7 +1204,7 @@ describe('Java expression language (JEXL) based transformations plugin', functio
|
|
|
1180
1204
|
.patch(
|
|
1181
1205
|
'/v2/entities/gps1/attrs',
|
|
1182
1206
|
utils.readExampleFile(
|
|
1183
|
-
'./test/unit/ngsiv2/examples/contextRequests/
|
|
1207
|
+
'./test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json'
|
|
1184
1208
|
)
|
|
1185
1209
|
)
|
|
1186
1210
|
.query({ type: 'GPS' })
|
|
@@ -1230,6 +1254,43 @@ describe('Java expression language (JEXL) based transformations plugin', functio
|
|
|
1230
1254
|
});
|
|
1231
1255
|
});
|
|
1232
1256
|
});
|
|
1257
|
+
|
|
1258
|
+
describe('When there is an extra TimeInstant sent by the device to be removed by jexl expression with context but with empty explicitAttrs', function () {
|
|
1259
|
+
// Case: Expression which results is sent as a new attribute
|
|
1260
|
+
const values = [
|
|
1261
|
+
{
|
|
1262
|
+
name: 'lat',
|
|
1263
|
+
type: 'Number',
|
|
1264
|
+
value: 52
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
name: 'lon',
|
|
1268
|
+
type: 'Number',
|
|
1269
|
+
value: 13
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
name: 'myattr',
|
|
1273
|
+
type: 'String',
|
|
1274
|
+
value: 'location'
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
name: 'TimeInstant',
|
|
1278
|
+
type: 'DateTime',
|
|
1279
|
+
value: '2015-08-05T07:35:01.468+00:00'
|
|
1280
|
+
}
|
|
1281
|
+
];
|
|
1282
|
+
|
|
1283
|
+
beforeEach(function () {
|
|
1284
|
+
nock.cleanAll();
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
it('should calculate them and remove non-explicitAttrs by jexl expression with context from the payload ', function (done) {
|
|
1288
|
+
iotAgentLib.update('gps1', 'GPS7', '', values, function (error) {
|
|
1289
|
+
should.not.exist(error);
|
|
1290
|
+
done();
|
|
1291
|
+
});
|
|
1292
|
+
});
|
|
1293
|
+
});
|
|
1233
1294
|
});
|
|
1234
1295
|
|
|
1235
1296
|
describe('Java expression language (JEXL) based transformations plugin - Timestamps', function () {
|
|
@@ -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
|
+
});
|
|
@@ -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
|
});
|
package/bin/agentConsole.js
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
|
|
5
|
-
*
|
|
6
|
-
* This file is part of fiware-iotagent-lib
|
|
7
|
-
*
|
|
8
|
-
* fiware-iotagent-lib is free software: you can redistribute it and/or
|
|
9
|
-
* modify it under the terms of the GNU Affero General Public License as
|
|
10
|
-
* published by the Free Software Foundation, either version 3 of the License,
|
|
11
|
-
* or (at your option) any later version.
|
|
12
|
-
*
|
|
13
|
-
* fiware-iotagent-lib is distributed in the hope that it will be useful,
|
|
14
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
16
|
-
* See the GNU Affero General Public License for more details.
|
|
17
|
-
*
|
|
18
|
-
* You should have received a copy of the GNU Affero General Public
|
|
19
|
-
* License along with fiware-iotagent-lib.
|
|
20
|
-
* If not, see http://www.gnu.org/licenses/.
|
|
21
|
-
*
|
|
22
|
-
* For those usages not covered by the GNU Affero General Public License
|
|
23
|
-
* please contact with::[contacto@tid.es]
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/* eslint-disable no-unused-vars */
|
|
27
|
-
/* eslint-disable no-console */
|
|
28
|
-
|
|
29
|
-
const readline = require('readline');
|
|
30
|
-
const iotAgentLib = require('../lib/fiware-iotagent-lib');
|
|
31
|
-
const commandUtils = require('command-shell-lib');
|
|
32
|
-
let config = require('../config');
|
|
33
|
-
const logger = require('logops');
|
|
34
|
-
const async = require('async');
|
|
35
|
-
const separator = '\n\n\t';
|
|
36
|
-
|
|
37
|
-
const commands = {
|
|
38
|
-
start: {
|
|
39
|
-
parameters: [],
|
|
40
|
-
description: '\tStart the IoT Agent',
|
|
41
|
-
handler: startApp
|
|
42
|
-
},
|
|
43
|
-
stop: {
|
|
44
|
-
parameters: [],
|
|
45
|
-
description: '\tStop the IoT Agent',
|
|
46
|
-
handler: stopApp
|
|
47
|
-
},
|
|
48
|
-
register: {
|
|
49
|
-
parameters: ['id', 'type'],
|
|
50
|
-
description:
|
|
51
|
-
'\tRegister a new device in the IoT Agent. The attributes to register will be extracted from the\n' +
|
|
52
|
-
'\ttype configuration',
|
|
53
|
-
handler: registerDevice
|
|
54
|
-
},
|
|
55
|
-
unregister: {
|
|
56
|
-
parameters: ['id', 'type'],
|
|
57
|
-
description: '\tUnregister the selected device',
|
|
58
|
-
handler: unregisterDevice
|
|
59
|
-
},
|
|
60
|
-
showConfig: {
|
|
61
|
-
parameters: [],
|
|
62
|
-
description: '\tShow the current configuration file',
|
|
63
|
-
handler: showConfig
|
|
64
|
-
},
|
|
65
|
-
config: {
|
|
66
|
-
parameters: ['newConfig'],
|
|
67
|
-
description: '\tChange the configuration file to a new one',
|
|
68
|
-
handler: changeConfig
|
|
69
|
-
},
|
|
70
|
-
updatevalue: {
|
|
71
|
-
parameters: ['deviceId', 'deviceType', 'attributes'],
|
|
72
|
-
description:
|
|
73
|
-
'\tUpdate a device value in the Context Broker. The attributes should be triads with the following\n' +
|
|
74
|
-
'\tformat: "name/type/value" sepparated by commas.',
|
|
75
|
-
handler: updateDeviceValue
|
|
76
|
-
},
|
|
77
|
-
listdevices: {
|
|
78
|
-
parameters: [],
|
|
79
|
-
description: '\tList all the devices that have been registered in this IoT Agent session\n',
|
|
80
|
-
handler: listDevices
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
function handleError(message) {
|
|
85
|
-
return function (error) {
|
|
86
|
-
if (error) {
|
|
87
|
-
console.log('\n\\033[31mERROR:\\033[0m %s', error.message);
|
|
88
|
-
} else {
|
|
89
|
-
console.log(message);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
commandUtils.prompt();
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function listDevices() {
|
|
97
|
-
iotAgentLib.listDevices(config.service, config.subservice, function (error, devices) {
|
|
98
|
-
if (error) {
|
|
99
|
-
console.log('\n\\033[31mERROR:\\033[0m %s', error.message);
|
|
100
|
-
} else {
|
|
101
|
-
const keys = Object.keys(devices);
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < keys.length; i++) {
|
|
104
|
-
console.log('\n\n%s\n', JSON.stringify(devices[keys[i]], null, 4));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
commandUtils.prompt();
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function extractAttributes(attributeString, callback) {
|
|
113
|
-
const attributes = attributeString.split(',');
|
|
114
|
-
const attributesResult = [];
|
|
115
|
-
|
|
116
|
-
for (let i = 0; i < attributes.length; i++) {
|
|
117
|
-
const fields = attributes[i].split('/');
|
|
118
|
-
const attribute = {
|
|
119
|
-
name: fields[0],
|
|
120
|
-
type: fields[1]
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
if (fields[2]) {
|
|
124
|
-
attribute.value = fields[2];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
attributesResult.push(attribute);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
callback(null, attributesResult);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function showConfig() {
|
|
134
|
-
console.log('Current configuration file:\n\n%s', JSON.stringify(config, null, 4));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function changeConfig(command) {
|
|
138
|
-
config = require(command[0]);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function writeHandler(id, type, attributes, callback) {
|
|
142
|
-
console.log(
|
|
143
|
-
'\n\nFake WRITE handler for update in entity [%s] with type [%s]\n%s\n',
|
|
144
|
-
id,
|
|
145
|
-
type,
|
|
146
|
-
JSON.stringify(attributes, null, 4)
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
callback(null, {
|
|
150
|
-
id,
|
|
151
|
-
type,
|
|
152
|
-
attributes
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function readHandler(id, type, attributes, callback) {
|
|
157
|
-
console.log(
|
|
158
|
-
'\n\nFake READ handler for update in entity [%s] with type [%s]\n%s\n',
|
|
159
|
-
id,
|
|
160
|
-
type,
|
|
161
|
-
JSON.stringify(attributes, null, 4)
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
const sensorData = {
|
|
165
|
-
id,
|
|
166
|
-
isPattern: false,
|
|
167
|
-
type,
|
|
168
|
-
attributes: [
|
|
169
|
-
{
|
|
170
|
-
name: 'luminance',
|
|
171
|
-
type: 'lumens',
|
|
172
|
-
value: 19
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
callback(null, sensorData);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function startApp(command) {
|
|
181
|
-
iotAgentLib.setDataUpdateHandler(writeHandler);
|
|
182
|
-
iotAgentLib.setCommandHandler(writeHandler);
|
|
183
|
-
iotAgentLib.setDataQueryHandler(readHandler);
|
|
184
|
-
iotAgentLib.activate(config, handleError('Application started'));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function stopApp(command) {
|
|
188
|
-
iotAgentLib.deactivate(handleError('Application stopped'));
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function exitAgent(command) {
|
|
192
|
-
process.exit(0);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function registerDevice(command) {
|
|
196
|
-
const device = {
|
|
197
|
-
id: command[0],
|
|
198
|
-
type: command[1]
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
console.log('Registering device');
|
|
202
|
-
iotAgentLib.register(device, handleError('Device registered in the Context Broker'));
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function unregisterDevice(command) {
|
|
206
|
-
console.log('Unregistering device');
|
|
207
|
-
iotAgentLib.unregister(command[0], handleError('Device unregistered'));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function updateDeviceValue(command) {
|
|
211
|
-
iotAgentLib.getDevice(command[0], function (error, device) {
|
|
212
|
-
if (device) {
|
|
213
|
-
extractAttributes(command[2], function (error, attributes) {
|
|
214
|
-
iotAgentLib.update(
|
|
215
|
-
device.name,
|
|
216
|
-
device.type,
|
|
217
|
-
'',
|
|
218
|
-
attributes,
|
|
219
|
-
device,
|
|
220
|
-
handleError('Device value updated')
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
} else {
|
|
224
|
-
async.waterfall(
|
|
225
|
-
[
|
|
226
|
-
async.apply(extractAttributes, command[2]),
|
|
227
|
-
async.apply(iotAgentLib.update, command[0], command[1], '')
|
|
228
|
-
],
|
|
229
|
-
handleError('Device value updated')
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function queryHandler(id, type, attributes, callback) {
|
|
236
|
-
console.log('Handling query for [%s] of type [%s]:\n%s', JSON.stringify(attributes));
|
|
237
|
-
|
|
238
|
-
callback(null, {
|
|
239
|
-
type,
|
|
240
|
-
isPattern: false,
|
|
241
|
-
id,
|
|
242
|
-
attributes: []
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function updateHandler(id, type, attributes, callback) {
|
|
247
|
-
console.log('Update message received for device with id [%s] and type [%s]', id, type);
|
|
248
|
-
|
|
249
|
-
callback(null, {
|
|
250
|
-
type,
|
|
251
|
-
isPattern: false,
|
|
252
|
-
id,
|
|
253
|
-
attributes: []
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
commandUtils.initialize(commands, 'IoTAgent> ');
|