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
|
@@ -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;
|