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.
Files changed (67) hide show
  1. package/.nyc_output/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +1 -0
  2. package/.nyc_output/processinfo/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +1 -0
  3. package/.nyc_output/processinfo/index.json +1 -0
  4. package/.readthedocs.yml +3 -1
  5. package/CHANGES_NEXT_RELEASE +1 -0
  6. package/README.md +5 -56
  7. package/doc/Contribution.md +3 -3
  8. package/doc/advanced-topics.md +8 -41
  9. package/doc/api.md +14 -3
  10. package/doc/expressionLanguage.md +17 -0
  11. package/doc/northboundinteractions.md +40 -33
  12. package/doc/operations.md +8 -5
  13. package/doc/requirements.txt +4 -0
  14. package/{docs → doc}/roadmap.md +21 -6
  15. package/doc/usermanual.md +4 -4
  16. package/docker/Mosquitto/Dockerfile +28 -12
  17. package/docker/Mosquitto/README.md +8 -7
  18. package/docker/Mosquitto/startMosquitto.sh +8 -0
  19. package/lib/fiware-iotagent-lib.js +1 -2
  20. package/lib/jexlTranformsMap.js +3 -1
  21. package/lib/model/Group.js +2 -1
  22. package/lib/model/dbConn.js +4 -0
  23. package/lib/plugins/expressionPlugin.js +56 -21
  24. package/lib/plugins/multiEntity.js +43 -49
  25. package/lib/plugins/pluginUtils.js +16 -0
  26. package/lib/services/commands/commandService.js +29 -2
  27. package/lib/services/common/domain.js +6 -2
  28. package/lib/services/common/iotManagerService.js +2 -1
  29. package/lib/services/devices/deviceRegistryMemory.js +13 -2
  30. package/lib/services/devices/deviceRegistryMongoDB.js +15 -7
  31. package/lib/services/devices/deviceService.js +52 -16
  32. package/lib/services/groups/groupRegistryMongoDB.js +13 -12
  33. package/lib/services/ngsi/entities-NGSI-LD.js +13 -4
  34. package/lib/services/ngsi/entities-NGSI-v2.js +8 -6
  35. package/lib/services/ngsi/ngsiService.js +3 -3
  36. package/lib/services/northBound/contextServer-NGSI-LD.js +20 -1
  37. package/lib/services/northBound/contextServer-NGSI-v2.js +39 -30
  38. package/lib/services/northBound/contextServerUtils.js +10 -10
  39. package/lib/services/northBound/deviceProvisioningServer.js +4 -1
  40. package/lib/templates/createDevice.json +13 -2
  41. package/lib/templates/createDeviceLax.json +2 -3
  42. package/lib/templates/updateDevice.json +13 -2
  43. package/package.json +27 -33
  44. package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +14 -0
  45. package/test/unit/mongodb/mongoDBUtils.js +2 -2
  46. package/test/unit/mongodb/mongodb-group-registry-test.js +1 -1
  47. package/test/unit/mongodb/mongodb-registry-test.js +2 -3
  48. package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgentCommands.json +2 -1
  49. package/test/unit/ngsi-ld/examples/contextRequests/updateContextLanguageProperties1.json +15 -0
  50. package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +315 -1
  51. package/test/unit/ngsi-ld/ngsiService/languageProperties-test.js +112 -0
  52. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +1 -1
  53. package/test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json +8 -0
  54. package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus2.json +6 -0
  55. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin35.json +2 -0
  56. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json +1 -0
  57. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json +27 -0
  58. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +63 -2
  59. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +151 -0
  60. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +63 -0
  61. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +60 -0
  62. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +2 -1
  63. package/bin/agentConsole.js +0 -257
  64. package/bin/iotAgentTester.js +0 -44
  65. package/lib/command/commandLine.js +0 -918
  66. package/lib/command/migration.js +0 -176
  67. package/test/unit/general/migration-test.js +0 -257
@@ -1,918 +0,0 @@
1
- /*
2
- * Copyright 2016 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
-
24
- const fs = require('fs');
25
- const clUtils = require('command-shell-lib');
26
- const migrationLib = require('./migration');
27
- const constants = require('../constants');
28
- const request = require('../request-shim');
29
- const async = require('async');
30
- const mu = require('mu2');
31
- let config;
32
- let configIot;
33
- const configMigration = {
34
- host: 'localhost',
35
- port: 27017,
36
- originDb: 'iotagent-protocols',
37
- protocols: {
38
- 'PDI-IoTA-UltraLight': 'IoTA-UL'
39
- }
40
- };
41
- let protocol = 'http://';
42
- let token;
43
-
44
- function queryContext(commands, callback) {
45
- const options = {
46
- url: protocol + config.host + ':' + config.port + '/NGSI10/queryContext',
47
- method: 'POST',
48
- json: {
49
- entities: [
50
- {
51
- type: commands[1],
52
- isPattern: 'false',
53
- id: commands[0]
54
- }
55
- ]
56
- },
57
- headers: {
58
- 'fiware-service': config.service,
59
- 'fiware-servicepath': config.subservice
60
- }
61
- };
62
-
63
- if (token) {
64
- options.headers[config.authorization.header] = token;
65
- }
66
-
67
- request(options, function (error, response, body) {
68
- if (error) {
69
- clUtils.getWriter().error('\nConnection error querying context: ' + error);
70
- } else if (body && body.orionError) {
71
- clUtils
72
- .getWriter()
73
- .error('\nApplication error querying context:\n ' + JSON.stringify(body.orionError.details, null, 4));
74
- } else if (response && body && response.statusCode === 200) {
75
- clUtils.getWriter().log('\nEntity context result:\n', JSON.stringify(body, null, 4));
76
- } else {
77
- clUtils.getWriter().log('\nTransport error querying context: ' + response.statusCode);
78
- }
79
- clUtils.prompt();
80
-
81
- if (callback) {
82
- callback();
83
- }
84
- });
85
- }
86
-
87
- function queryContextAttribute(commands, callback) {
88
- const options = {
89
- url: protocol + config.host + ':' + config.port + '/NGSI10/queryContext',
90
- method: 'POST',
91
- json: {
92
- entities: [
93
- {
94
- type: commands[1],
95
- isPattern: 'false',
96
- id: commands[0]
97
- }
98
- ],
99
- attributes: commands[2].split(',')
100
- },
101
- headers: {
102
- 'fiware-service': config.service,
103
- 'fiware-servicepath': config.subservice
104
- }
105
- };
106
-
107
- if (token) {
108
- options.headers[config.authorization.header] = token;
109
- }
110
-
111
- request(options, function (error, response, body) {
112
- if (error) {
113
- clUtils.getWriter().error('\nConnection error querying context: ' + error);
114
- } else if (body && body.orionError) {
115
- clUtils
116
- .getWriter()
117
- .error('\nApplication error querying context:\n ' + JSON.stringify(body.orionError.details, null, 4));
118
- } else if (response && body && response.statusCode === 200) {
119
- clUtils.getWriter().log('\nEntity context result:\n', JSON.stringify(body, null, 4));
120
- } else {
121
- clUtils.getWriter().log('\nTransport error querying context: ' + response.statusCode);
122
- }
123
- clUtils.prompt();
124
-
125
- if (callback) {
126
- callback();
127
- }
128
- });
129
- }
130
-
131
- function parseAttributes(payload) {
132
- function split(pair) {
133
- const fields = [];
134
- const colon = pair.indexOf('#');
135
- const equal = pair.indexOf('=');
136
-
137
- fields.push(pair.substr(0, colon));
138
- fields.push(pair.substr(colon + 1, equal - colon - 1));
139
- fields.push(pair.substr(equal + 1));
140
- return fields;
141
- }
142
-
143
- function group(previous, current) {
144
- if (current && current.length === 3) {
145
- const attributes = {
146
- name: current[0],
147
- type: current[1],
148
- value: current[2]
149
- };
150
-
151
- previous.push(attributes);
152
- }
153
-
154
- return previous;
155
- }
156
-
157
- return payload.split('|').map(split).reduce(group, []);
158
- }
159
-
160
- function modifyContext(action) {
161
- return function (commands, callback) {
162
- const options = {
163
- url: protocol + config.host + ':' + config.port + '/NGSI10/updateContext',
164
- method: 'POST',
165
- json: {
166
- contextElements: [
167
- {
168
- type: commands[1],
169
- isPattern: 'false',
170
- id: commands[0],
171
- attributes: parseAttributes(commands[2])
172
- }
173
- ],
174
- updateAction: action
175
- },
176
- headers: {
177
- 'fiware-service': config.service,
178
- 'fiware-servicepath': config.subservice
179
- }
180
- };
181
-
182
- if (token) {
183
- options.headers[config.authorization.header] = token;
184
- }
185
-
186
- request(options, function (error, response, body) {
187
- if (error) {
188
- clUtils.getWriter().error('\nConnection error updating context: ' + error);
189
- } else if (body && body.orionError) {
190
- clUtils
191
- .getWriter()
192
- .error(
193
- '\nApplication error updating context:\n ' + JSON.stringify(body.orionError.details, null, 4)
194
- );
195
- } else if (response && body && response.statusCode === 200) {
196
- clUtils.getWriter().log('\nEntity successfully updated:\n', JSON.stringify(body, null, 4));
197
- } else {
198
- clUtils.getWriter().log('\nTransport error updating context: ' + response.statusCode);
199
- }
200
- clUtils.prompt();
201
-
202
- if (callback) {
203
- callback();
204
- }
205
- });
206
- };
207
- }
208
-
209
- function configure(commands) {
210
- config.host = commands[0];
211
- config.port = commands[1];
212
- config.service = commands[2];
213
- config.subservice = commands[3];
214
- }
215
-
216
- /* eslint-disable-next-line no-unused-vars */
217
- function showConfig(commands) {
218
- clUtils.getWriter().log('\nCurrent configuration:\n\n');
219
- clUtils.getWriter().log(JSON.stringify(config, null, 4));
220
- clUtils.getWriter().log('\n');
221
- clUtils.prompt();
222
- }
223
-
224
- function configureIot(commands) {
225
- configIot.host = commands[0];
226
- configIot.port = commands[1];
227
- configIot.service = commands[2];
228
- configIot.subservice = commands[3];
229
- }
230
- /* eslint-disable-next-line no-unused-vars */
231
- function showConfigIot(commands) {
232
- clUtils.getWriter().log('\nCurrent IoT configuration:\n\n');
233
- clUtils.getWriter().log(JSON.stringify(configIot, null, 4));
234
- clUtils.getWriter().log('\n');
235
- clUtils.prompt();
236
- }
237
-
238
- function setConfigMigration(commands) {
239
- configMigration.host = commands[0];
240
- configMigration.port = commands[1];
241
- configMigration.originDb = commands[2];
242
- }
243
- /* eslint-disable-next-line no-unused-vars */
244
- function showConfigMigration(commands) {
245
- clUtils.getWriter().log('\nCurrent migration configuration:\n\n');
246
- clUtils.getWriter().log(JSON.stringify(configMigration, null, 4));
247
- clUtils.getWriter().log('\n');
248
- clUtils.prompt();
249
- }
250
-
251
- function addProtocols(commands) {
252
- const protocols = commands[0].split(';');
253
-
254
- configMigration.protocols = {};
255
-
256
- for (let i = 0; i < protocols.length; i++) {
257
- const protocol = protocols[i].split('=');
258
-
259
- configMigration.protocols[protocol[0]] = protocol[1];
260
- }
261
- }
262
-
263
- function discoverContext(commands, callback) {
264
- const options = {
265
- url: protocol + config.host + ':' + config.port + '/v1/registry/discoverContextAvailability',
266
- method: 'POST',
267
- json: {
268
- entities: [
269
- {
270
- type: commands[1],
271
- isPattern: 'false',
272
- id: commands[0]
273
- }
274
- ]
275
- },
276
- headers: {
277
- 'fiware-service': config.service,
278
- 'fiware-servicepath': config.subservice
279
- }
280
- };
281
-
282
- if (token) {
283
- options.headers[config.getConfig().authorization.header] = token;
284
- }
285
-
286
- request(options, function (error, response, body) {
287
- if (error) {
288
- clUtils.getWriter().error('\nConnection error discovering context registrations: ' + error);
289
- } else if (body && body.orionError) {
290
- clUtils
291
- .getWriter()
292
- .error(
293
- '\nApplication error discovering context registrations:\n ' +
294
- JSON.stringify(body.orionError.details, null, 4)
295
- );
296
- } else if (response && body && response.statusCode === 200) {
297
- clUtils.getWriter().log('\nContext registration result:\n', JSON.stringify(body, null, 4));
298
- } else {
299
- clUtils.getWriter().log('\nTransport error discovering context registrations: ' + response.statusCode);
300
- }
301
- clUtils.prompt();
302
-
303
- if (callback) {
304
- callback();
305
- }
306
- });
307
- }
308
-
309
- function provisionDevice(commands, callback) {
310
- function generateOptions(deviceConfig, callback) {
311
- const options = {
312
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/devices',
313
- method: 'POST',
314
- headers: {
315
- 'fiware-service': configIot.service,
316
- 'fiware-servicepath': configIot.subservice
317
- }
318
- };
319
-
320
- if (token) {
321
- options.headers[config.authorization.header] = token;
322
- }
323
-
324
- try {
325
- const payload = JSON.parse(deviceConfig);
326
- options.json = payload;
327
- callback(null, options);
328
- } catch (e) {
329
- callback("Wrong JSON. Couldn't parse");
330
- }
331
- }
332
-
333
- function sendProvisionRequest(options, callback) {
334
- request(options, function (error, result, body) {
335
- if (error) {
336
- callback("Couldn't connect with the provisioning server: " + error.toString());
337
- } else if ((result.statusCode === 200 || result.statusCode === 201) && body) {
338
- callback(null, 'Device successfully provisioned');
339
- } else {
340
- clUtils.getWriter().log('Error body: %s', JSON.stringify(body, null, 4));
341
-
342
- callback('Unexpected application error. Status: ' + result.statusCode);
343
- }
344
- });
345
- }
346
-
347
- function handleOut(error, msg) {
348
- if (error) {
349
- clUtils.getWriter().error(error);
350
- } else {
351
- clUtils.getWriter().log(msg);
352
- }
353
- clUtils.prompt();
354
-
355
- if (callback) {
356
- callback();
357
- }
358
- }
359
-
360
- fs.readFile(commands[0], 'utf8', function (error, deviceConfig) {
361
- if (error && error.code === 'ENOENT') {
362
- clUtils.getWriter().error('File not found');
363
- clUtils.prompt();
364
- } else {
365
- async.waterfall([async.apply(generateOptions, deviceConfig), sendProvisionRequest], handleOut);
366
- }
367
- });
368
- }
369
-
370
- function provisionGroup(commands, callback) {
371
- function createDeviceObj(rawData) {
372
- const deviceData = rawData.split(' ');
373
-
374
- return {
375
- deviceId: deviceData[0],
376
- deviceName: deviceData[1],
377
- deviceType: commands[2]
378
- };
379
- }
380
-
381
- function parseDataFile(data) {
382
- const lines = data.split('\n').slice(1, -1);
383
-
384
- return lines.map(createDeviceObj);
385
- }
386
-
387
- function createPayload(csvData, callback) {
388
- const dataList = parseDataFile(csvData);
389
-
390
- async.map(
391
- dataList,
392
- function (item, innerCallback) {
393
- let buffer;
394
-
395
- mu.compileAndRender(commands[0], item)
396
- .on('data', function (data) {
397
- if (buffer) {
398
- buffer += data;
399
- } else {
400
- buffer = data;
401
- }
402
- })
403
- /* eslint-disable-next-line no-unused-vars */
404
- .on('end', function (data) {
405
- innerCallback(null, JSON.parse(buffer.toString()));
406
- });
407
- },
408
- callback
409
- );
410
- }
411
-
412
- function sendFiles(payloadList, callback) {
413
- const options = {
414
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/devices',
415
- method: 'POST',
416
- headers: {
417
- 'fiware-service': configIot.service,
418
- 'fiware-servicepath': configIot.subservice
419
- },
420
- json: {
421
- devices: payloadList
422
- }
423
- };
424
-
425
- if (token) {
426
- options.headers[config.authorization.header] = token;
427
- }
428
-
429
- request(options, callback);
430
- }
431
-
432
- function processProvisioningResults(result, body, callback) {
433
- if (result.statusCode !== 200 && result.statusCode !== 201) {
434
- callback('Error sending provisioning request to the IoT Agent. StatusCode [' + result.statusCode + ']');
435
- } else {
436
- callback(null);
437
- }
438
- }
439
- /* eslint-disable-next-line no-unused-vars */
440
- function processResult(error, result) {
441
- if (error) {
442
- clUtils.getWriter().log('Error processing group of files [%s]. Skipping.', error);
443
- } else {
444
- clUtils.getWriter().log('Devices provisioned successfully');
445
- }
446
-
447
- if (callback) {
448
- callback();
449
- }
450
- }
451
-
452
- function getFiles(callback) {
453
- fs.readFile(commands[1], 'utf8', callback);
454
- }
455
-
456
- clUtils.getWriter().log('Creating group of devices of type [%s]', commands[2]);
457
-
458
- async.waterfall([getFiles, createPayload, sendFiles, processProvisioningResults], processResult);
459
- }
460
-
461
- function listProvisioned(commands, callback) {
462
- const options = {
463
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/devices',
464
- method: 'GET',
465
- headers: {
466
- 'fiware-service': configIot.service,
467
- 'fiware-servicepath': configIot.subservice
468
- }
469
- };
470
-
471
- if (token) {
472
- options.headers[config.authorization.header] = token;
473
- }
474
-
475
- clUtils.getWriter().log('Devices provisioned in host [%s:%s]', configIot.host, configIot.port);
476
- clUtils.getWriter().log('----------------------------------------------------------------');
477
-
478
- request(options, function (error, result, body) {
479
- if (error) {
480
- clUtils.getWriter().log("Couldn't connect with the provisioning server: " + error.toString());
481
- } else if (result.statusCode === 200 && body) {
482
- const parsedBody = JSON.parse(body);
483
- clUtils.getWriter().log(JSON.stringify(parsedBody, null, 4));
484
- } else {
485
- clUtils.getWriter().log('Unexpected application error. Status: ' + result.statusCode);
486
- }
487
- clUtils.prompt();
488
-
489
- if (callback) {
490
- callback();
491
- }
492
- });
493
- }
494
-
495
- function removeProvisioned(commands, callback) {
496
- const options = {
497
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/devices/' + commands[0],
498
- method: 'DELETE',
499
- headers: {
500
- 'fiware-service': configIot.service,
501
- 'fiware-servicepath': configIot.subservice
502
- }
503
- };
504
-
505
- if (token) {
506
- options.headers[config.authorization.header] = token;
507
- }
508
-
509
- clUtils.getWriter().log('Removing device [%s] [%s:%s]', commands[0], configIot.host, configIot.port);
510
- clUtils.getWriter().log('----------------------------------------------------------------');
511
-
512
- request(options, function (error, result, body) {
513
- if (error) {
514
- clUtils.getWriter().log("Couldn't connect with the provisioning server: " + error.toString());
515
- } else if (result.statusCode === 200 && body) {
516
- clUtils.getWriter().log('Device [%s] removed successfully', commands[0]);
517
- } else {
518
- clUtils.getWriter().log('Unexpected application error. Status: ' + result.statusCode);
519
- }
520
- clUtils.prompt();
521
-
522
- if (callback) {
523
- callback();
524
- }
525
- });
526
- }
527
-
528
- function addGroup(commands, callback) {
529
- clUtils
530
- .getWriter()
531
- .log('Adding device groups to host [%s:%s] from file [%s]', configIot.host, configIot.port, commands[0]);
532
-
533
- function generateOptions(deviceConfig, callback) {
534
- const options = {
535
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/services',
536
- method: 'POST',
537
- headers: {
538
- 'fiware-service': configIot.service,
539
- 'fiware-servicepath': configIot.subservice
540
- }
541
- };
542
-
543
- if (token) {
544
- options.headers[config.authorization.header] = token;
545
- }
546
-
547
- try {
548
- const payload = JSON.parse(deviceConfig);
549
- options.json = payload;
550
- callback(null, options);
551
- } catch (e) {
552
- callback("Wrong JSON. Couldn't parse");
553
- }
554
- }
555
-
556
- function sendProvisionRequest(options, callback) {
557
- request(options, function (error, result, body) {
558
- if (error) {
559
- callback("Couldn't connect with the provisioning server: " + error.toString());
560
- } else if (result.statusCode === 201 && body) {
561
- callback(null, 'Device group successfully provisioned');
562
- } else {
563
- clUtils.getWriter().log('Error body: %s', JSON.stringify(body, null, 4));
564
- callback('Unexpected application error. Status: ' + result.statusCode);
565
- }
566
- });
567
- }
568
-
569
- function handleOut(error, msg) {
570
- if (error) {
571
- clUtils.getWriter().error(error);
572
- } else {
573
- clUtils.getWriter().log(msg);
574
- }
575
- clUtils.prompt();
576
-
577
- if (callback) {
578
- callback();
579
- }
580
- }
581
-
582
- fs.readFile(commands[0], 'utf8', function (error, deviceConfig) {
583
- if (error && error.code === 'ENOENT') {
584
- clUtils.getWriter().error('File not found');
585
- clUtils.prompt();
586
- } else {
587
- async.waterfall([async.apply(generateOptions, deviceConfig), sendProvisionRequest], handleOut);
588
- }
589
- });
590
- }
591
-
592
- function removeGroup(commands, callback) {
593
- const options = {
594
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/services',
595
- method: 'DELETE',
596
- qs: {
597
- apikey: commands[0],
598
- resource: commands[1]
599
- },
600
- headers: {
601
- 'fiware-service': configIot.service,
602
- 'fiware-servicepath': configIot.subservice
603
- }
604
- };
605
-
606
- if (token) {
607
- options.headers[config.authorization.header] = token;
608
- }
609
-
610
- clUtils
611
- .getWriter()
612
- .log(
613
- 'Removing device group for subservice [%s] from [%s:%s]',
614
- configIot.subservice,
615
- configIot.host,
616
- configIot.port
617
- );
618
-
619
- clUtils.getWriter().log('----------------------------------------------------------------');
620
- /* eslint-disable-next-line no-unused-vars */
621
- request(options, function (error, result, body) {
622
- if (error) {
623
- clUtils.getWriter().log("Couldn't connect with the provisioning server: " + error.toString());
624
- } else if (result.statusCode === 200) {
625
- clUtils.getWriter().log('Device group for subservice [%s] removed successfully', configIot.subservice);
626
- } else {
627
- clUtils.getWriter().log('Unexpected application error. Status: ' + result.statusCode);
628
- }
629
- clUtils.prompt();
630
-
631
- if (callback) {
632
- callback();
633
- }
634
- });
635
- }
636
-
637
- function listGroups(commands, callback) {
638
- clUtils.getWriter().log('Devices groups provisioned in host [%s:%s]', configIot.host, configIot.port);
639
- clUtils.getWriter().log('----------------------------------------------------------------');
640
-
641
- const options = {
642
- uri: protocol + configIot.host + ':' + configIot.port + '/iot/services',
643
- method: 'GET',
644
- headers: {
645
- 'fiware-service': configIot.service,
646
- 'fiware-servicepath': '/*'
647
- }
648
- };
649
-
650
- if (token) {
651
- options.headers[config.authorization.header] = token;
652
- }
653
-
654
- request(options, function (error, result, body) {
655
- if (error) {
656
- clUtils.getWriter().log('Error requesting groups list.\n');
657
- } else if (result) {
658
- if (error) {
659
- clUtils.getWriter().log("Couldn't connect with the provisioning server: " + error.toString());
660
- } else if (result.statusCode === 200 && body) {
661
- const parsedBody = JSON.parse(body);
662
- clUtils.getWriter().log(JSON.stringify(parsedBody, null, 4));
663
- } else {
664
- clUtils.getWriter().log('Unexpected application error. Status: ' + result.statusCode);
665
- }
666
- } else {
667
- clUtils.getWriter().log('No result was returned while listing groups.\n');
668
- }
669
- clUtils.prompt();
670
-
671
- if (callback) {
672
- callback();
673
- }
674
- });
675
- }
676
-
677
- function authenticate(command, callback) {
678
- const options = {
679
- uri: protocol + command[0] + ':' + command[1] + '/v3/auth/tokens',
680
- method: 'POST',
681
- headers: {},
682
- json: {
683
- auth: {
684
- identity: {
685
- methods: ['password'],
686
- password: {
687
- user: {
688
- domain: {
689
- name: command[4]
690
- },
691
- name: command[2],
692
- password: command[3]
693
- }
694
- }
695
- }
696
- }
697
- }
698
- };
699
-
700
- clUtils
701
- .getWriter()
702
- .log(
703
- 'Authenticating to host [%s:%s] with user [%s] in service [%s]',
704
- command[0],
705
- command[1],
706
- command[2],
707
- command[4]
708
- );
709
-
710
- clUtils.getWriter().log('----------------------------------------------------------------');
711
-
712
- clUtils.getWriter().log(JSON.stringify(options, null, 4));
713
- /* eslint-disable-next-line no-unused-vars */
714
- request(options, function (error, result, body) {
715
- if (error) {
716
- clUtils.getWriter().log('Error sending authentication request: %s', error);
717
- } else if (result.statusCode === 201) {
718
- clUtils.getWriter().log('Authentication successful');
719
- clUtils.getWriter().log('The new token is: [%s]', result.headers['x-subject-token']);
720
- token = result.headers['x-subject-token'];
721
- } else {
722
- clUtils.getWriter().log('Unexpected return code during authentication: %s.', result.statusCode);
723
- }
724
-
725
- clUtils.prompt();
726
-
727
- if (callback) {
728
- callback();
729
- }
730
- });
731
- }
732
-
733
- function setProtocol(command) {
734
- if (command[0] && (command[0] === 'http' || command[0] === 'https')) {
735
- protocol = command[0] + '://';
736
- } else {
737
- clUtils.getWriter().log('Unsupported protocol: %s.', command[0]);
738
- }
739
- }
740
-
741
- function migrate(command) {
742
- let service;
743
- let subservice;
744
-
745
- if (command[1] === '*') {
746
- service = null;
747
- } else {
748
- service = command[1];
749
- }
750
-
751
- if (command[2] === '*') {
752
- subservice = null;
753
- } else {
754
- subservice = command[2];
755
- }
756
-
757
- migrationLib.migrate(configMigration, configMigration.originDb, command[0], service, subservice, function (error) {
758
- if (error) {
759
- clUtils.getWriter().log('Migration concluded with error: %j', error);
760
- } else {
761
- clUtils.getWriter().log('Migration concluded successfully.');
762
- }
763
- });
764
- }
765
-
766
- const commands = {
767
- update: {
768
- parameters: ['entity', 'type', 'attributes'],
769
- description:
770
- '\tUpdate the values of the defined set of attributes, using the following format: ' +
771
- 'name#type=value(|name#type=value)*',
772
- handler: modifyContext('UPDATE'),
773
- asynchronous: true
774
- },
775
- append: {
776
- parameters: ['entity', 'type', 'attributes'],
777
- description:
778
- '\tAppend a new Entity with the defined set of attributes, using the following format: ' +
779
- 'name:type=value(,name:type=value)*',
780
- handler: modifyContext('APPEND'),
781
- asynchronous: true
782
- },
783
- query: {
784
- parameters: ['entity', 'type'],
785
- description: '\tGet all the information on the selected object.',
786
- handler: queryContext,
787
- asynchronous: true
788
- },
789
- queryAttr: {
790
- parameters: ['entity', 'type', 'attributes'],
791
- description: '\tGet information on the selected object for the selected attributes.',
792
- handler: queryContextAttribute
793
- },
794
- discover: {
795
- parameters: ['entity', 'type'],
796
- description: '\tGet all the context providers for a entity and type.',
797
- handler: discoverContext,
798
- asynchronous: true
799
- },
800
- configCb: {
801
- parameters: ['host', 'port', 'service', 'subservice'],
802
- description: '\tConfig a new host and port for the remote Context Broker.',
803
- handler: configure
804
- },
805
- showConfigCb: {
806
- parameters: [],
807
- description: '\tShow the current configuration of the client for the Context Broker.',
808
- handler: showConfig
809
- },
810
- configIot: {
811
- parameters: ['host', 'port', 'service', 'subservice'],
812
- description: '\tConfig a new host and port for the remote IoT Agent.',
813
- handler: configureIot
814
- },
815
- showConfigIot: {
816
- parameters: [],
817
- description: '\tShow the current configuration of the client for the IoT Agent.',
818
- handler: showConfigIot
819
- },
820
- provision: {
821
- parameters: ['filename'],
822
- description:
823
- '\tProvision a new device using the Device Provisioning API. The device configuration is \n' +
824
- '\tread from the file specified in the "filename" parameter.',
825
- handler: provisionDevice,
826
- asynchronous: true
827
- },
828
- provisionGroup: {
829
- parameters: ['template', 'data', 'type'],
830
- description:
831
- '\tProvision a group of devices with the selected template, taking the information needed to\n' +
832
- '\tfill the template from a CSV with two columns, DEVICE_ID and DEVICE_NAME. The third parameter, type\n' +
833
- '\twill be used to replace the DEVICE_TYPE field in the template. All the devices will be provisioned\n' +
834
- '\tto the same IoT Agent, once the templates have been fulfilled.',
835
- handler: provisionGroup,
836
- asynchronous: true
837
- },
838
- listProvisioned: {
839
- parameters: [],
840
- description: '\tList all the provisioned devices in an IoT Agent.',
841
- handler: listProvisioned,
842
- asynchronous: true
843
- },
844
- removeProvisioned: {
845
- parameters: ['deviceId'],
846
- description: '\tRemove the selected provisioned device from the IoT Agent, specified by its Device ID.',
847
- handler: removeProvisioned,
848
- asynchronous: true
849
- },
850
- addGroup: {
851
- parameters: ['filename'],
852
- description:
853
- '\tAdd a new device group to the specified IoT Agent through the Configuration API. The \n' +
854
- '\tbody is taken from the file specified in the "filename" parameter.',
855
- handler: addGroup,
856
- asynchronous: true
857
- },
858
- listGroups: {
859
- parameters: [],
860
- description: '\tList all the device groups created in the selected IoT Agent for the configured service',
861
- handler: listGroups,
862
- asynchronous: true
863
- },
864
- removeGroup: {
865
- parameters: ['apiKey', 'resource'],
866
- description: '\tRemove the device group corresponding to the current configured subservice.',
867
- handler: removeGroup,
868
- asynchronous: true
869
- },
870
- authenticate: {
871
- parameters: ['host', 'port', 'user', 'password', 'service'],
872
- description: '\tAuthenticates to the given authentication server, and use the token in subsequent requests.',
873
- handler: authenticate,
874
- asynchronous: true
875
- },
876
- setProtocol: {
877
- parameters: ['protocol'],
878
- description: '\tSets the protocol to use in the requests (http or https). Defaults to http.',
879
- handler: setProtocol
880
- },
881
- configMigration: {
882
- parameters: ['host', 'port', 'originDb'],
883
- description: '\tSets the configuration for a migration between a C++ IoTA and a Node.js one.',
884
- handler: setConfigMigration
885
- },
886
- showConfigMigration: {
887
- parameters: [],
888
- description: '\tShows the current migration configuration.',
889
- handler: showConfigMigration
890
- },
891
- addProtocols: {
892
- parameters: ['protocols'],
893
- description:
894
- '\tAdd a protocol translation table, in the following format:\n' +
895
- '\t\tprotocolOrigin1=protocolTarget1;protocolOrigin2=protocolTarget2...\n',
896
- handler: addProtocols
897
- },
898
- migrate: {
899
- parameters: ['targetDb', 'service', 'subservice'],
900
- description:
901
- '\tMigrate all the devices and services for the selected service and subservice into the\n' +
902
- '\tspecified Mongo database. To perform the migration for all the services or all the\n' +
903
- '\tsubservices, use the "*" value.',
904
- handler: migrate
905
- }
906
- };
907
-
908
- function init(cbCfg, iotCfg) {
909
- config = cbCfg;
910
- configIot = iotCfg;
911
- if (config.authorization && !config.authorization.header) {
912
- config.authorization.header = constants.AUTH_HEADER;
913
- }
914
- }
915
-
916
- exports.init = init;
917
- exports.commands = commands;
918
- exports.clUtils = clUtils;