iotagent-node-lib 4.2.0 → 4.4.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/doc/api.md +178 -69
- package/docker/Mosquitto/Dockerfile +1 -1
- package/lib/commonConfig.js +18 -0
- package/lib/errors.js +48 -20
- package/lib/services/commands/commandRegistryMemory.js +12 -2
- package/lib/services/commands/commandRegistryMongoDB.js +26 -15
- package/lib/services/devices/deviceRegistryMemory.js +1 -1
- package/lib/services/devices/deviceRegistryMongoDB.js +7 -12
- package/lib/services/devices/deviceService.js +4 -3
- package/lib/services/devices/devices-NGSI-LD.js +3 -3
- package/lib/services/devices/devices-NGSI-v2.js +10 -4
- package/lib/services/groups/groupRegistryMemory.js +1 -1
- package/lib/services/groups/groupRegistryMongoDB.js +1 -1
- package/lib/services/groups/groupService.js +9 -3
- package/lib/services/ngsi/entities-NGSI-LD.js +15 -7
- package/lib/services/ngsi/entities-NGSI-v2.js +86 -54
- package/lib/services/ngsi/ngsiService.js +3 -3
- package/lib/services/ngsi/subscription-NGSI-LD.js +2 -0
- package/lib/services/ngsi/subscription-NGSI-v2.js +2 -0
- package/lib/services/northBound/contextServer-NGSI-LD.js +50 -55
- package/lib/services/northBound/contextServer-NGSI-v2.js +1 -1
- package/lib/services/northBound/deviceProvisioningServer.js +100 -26
- package/lib/services/northBound/restUtils.js +1 -1
- package/package.json +2 -2
- package/scripts/legacy_expression_tool/requirements.txt +1 -1
- package/test/functional/testCases.js +797 -66
- package/test/functional/testUtils.js +3 -1
- package/test/unit/ngsi-ld/ngsiService/active-devices-test.js +0 -1
- package/test/unit/ngsiv2/ngsiService/active-devices-test.js +8 -5
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +34 -2
- package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +37 -2
|
@@ -48,41 +48,36 @@ const overwritePaths = ['/ngsi-ld/v1/entities/:entity/attrs', '/ngsi-ld/v1/entit
|
|
|
48
48
|
const updatePaths = ['/ngsi-ld/v1/entities/:entity/attrs', '/ngsi-ld/v1/entities/:entity/attrs/:attr'];
|
|
49
49
|
const queryPaths = ['/ngsi-ld/v1/entities/:entity'];
|
|
50
50
|
|
|
51
|
-
|
|
52
51
|
/**
|
|
53
52
|
* Replacement of NGSI-LD Null placeholders with real null values
|
|
54
53
|
*
|
|
55
54
|
*/
|
|
56
|
-
function replaceNGSILDNull(payload){
|
|
57
|
-
Object.keys(payload).forEach((key) =>{
|
|
55
|
+
function replaceNGSILDNull(payload) {
|
|
56
|
+
Object.keys(payload).forEach((key) => {
|
|
58
57
|
const value = payload[key];
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
} else if (typeof value === 'object' &&
|
|
62
|
-
!Array.isArray(value) &&
|
|
63
|
-
value !== null){
|
|
58
|
+
if (value === constants.NGSI_LD_NULL) {
|
|
59
|
+
payload[key] = null;
|
|
60
|
+
} else if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
|
|
64
61
|
payload[key] = replaceNGSILDNull(payload[key]);
|
|
65
62
|
}
|
|
66
|
-
})
|
|
67
|
-
return
|
|
63
|
+
});
|
|
64
|
+
return payload;
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
/**
|
|
71
68
|
* Check to see if the payload or its subattributes contain null values
|
|
72
69
|
*
|
|
73
70
|
*/
|
|
74
|
-
function containsNulls(payload, result){
|
|
75
|
-
Object.keys(payload).forEach((key) =>{
|
|
71
|
+
function containsNulls(payload, result) {
|
|
72
|
+
Object.keys(payload).forEach((key) => {
|
|
76
73
|
const value = payload[key];
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
} else if (typeof value === 'object' &&
|
|
80
|
-
!Array.isArray(value) &&
|
|
81
|
-
value !== null){
|
|
74
|
+
if (value === null) {
|
|
75
|
+
result.nulls = true;
|
|
76
|
+
} else if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
|
|
82
77
|
containsNulls(payload[key], result);
|
|
83
78
|
}
|
|
84
|
-
})
|
|
85
|
-
return
|
|
79
|
+
});
|
|
80
|
+
return result;
|
|
86
81
|
}
|
|
87
82
|
|
|
88
83
|
/**
|
|
@@ -90,23 +85,23 @@ function containsNulls(payload, result){
|
|
|
90
85
|
* to real nulls and checks for the presence of null and datasetId
|
|
91
86
|
*
|
|
92
87
|
*/
|
|
93
|
-
function preprocessNGSILD(req, res, next){
|
|
94
|
-
res.locals.hasDatasetId =
|
|
95
|
-
const payload = req.body
|
|
96
|
-
if (payload && typeof payload === 'object'){
|
|
97
|
-
Object.keys(payload).forEach((key) =>{
|
|
98
|
-
if (_.isArray(payload[key])){
|
|
88
|
+
function preprocessNGSILD(req, res, next) {
|
|
89
|
+
res.locals.hasDatasetId = false;
|
|
90
|
+
const payload = req.body;
|
|
91
|
+
if (payload && typeof payload === 'object') {
|
|
92
|
+
Object.keys(payload).forEach((key) => {
|
|
93
|
+
if (_.isArray(payload[key])) {
|
|
99
94
|
payload[key].forEach((obj) => {
|
|
100
|
-
if (obj.datasetId){
|
|
95
|
+
if (obj.datasetId) {
|
|
101
96
|
res.locals.hasDatasetId = true;
|
|
102
97
|
}
|
|
103
98
|
});
|
|
104
|
-
} else if (payload[key] && payload[key].datasetId && payload[key].datasetId !== '@none'){
|
|
105
|
-
|
|
106
|
-
}
|
|
99
|
+
} else if (payload[key] && payload[key].datasetId && payload[key].datasetId !== '@none') {
|
|
100
|
+
res.locals.hasDatasetId = true;
|
|
101
|
+
}
|
|
107
102
|
});
|
|
108
103
|
req.body = replaceNGSILDNull(payload);
|
|
109
|
-
const result = { nulls: false }
|
|
104
|
+
const result = { nulls: false };
|
|
110
105
|
containsNulls(payload, result);
|
|
111
106
|
res.locals.hasNulls = result.nulls;
|
|
112
107
|
}
|
|
@@ -124,16 +119,23 @@ function preprocessNGSILD(req, res, next){
|
|
|
124
119
|
function validateNGSILD(supportNull, supportDatasetId) {
|
|
125
120
|
return function validate(req, res, next) {
|
|
126
121
|
if (!supportNull && res.locals.hasNulls) {
|
|
127
|
-
next(
|
|
122
|
+
next(
|
|
123
|
+
new errors.BadRequest(
|
|
124
|
+
'NGSI-LD Null found within the payload. This IoT Agent does not support nulls for this endpoint.'
|
|
125
|
+
)
|
|
126
|
+
);
|
|
128
127
|
} else if (!supportDatasetId && res.locals.hasDatasetId) {
|
|
129
|
-
next(
|
|
128
|
+
next(
|
|
129
|
+
new errors.BadRequest(
|
|
130
|
+
'datasetId found within the payload. This IoT Agent does not support multi-attribute requests.'
|
|
131
|
+
)
|
|
132
|
+
);
|
|
130
133
|
} else {
|
|
131
134
|
next();
|
|
132
135
|
}
|
|
133
136
|
};
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
|
|
137
139
|
/**
|
|
138
140
|
* Extract metadata attributes from input.
|
|
139
141
|
*
|
|
@@ -413,34 +415,31 @@ function defaultQueryHandlerNgsiLD(id, type, service, subservice, attributes, ca
|
|
|
413
415
|
* @param {Object} req Update request to generate Actions from
|
|
414
416
|
*/
|
|
415
417
|
function generateMergePatchActionNgsiLD(req, callback) {
|
|
416
|
-
|
|
417
418
|
const entityId = req.params.entity;
|
|
418
419
|
|
|
419
|
-
|
|
420
|
-
function addAttributes(deviceData, body, attributes){
|
|
420
|
+
function addAttributes(deviceData, body, attributes) {
|
|
421
421
|
const keys = Object.keys(body);
|
|
422
422
|
|
|
423
423
|
for (const j in deviceData) {
|
|
424
424
|
if (keys.includes(deviceData[j].name)) {
|
|
425
|
-
const obj = body[deviceData[j].name]
|
|
426
|
-
if (
|
|
425
|
+
const obj = body[deviceData[j].name];
|
|
426
|
+
if (obj === null) {
|
|
427
427
|
attributes.push({
|
|
428
428
|
type: deviceData[j].type,
|
|
429
429
|
value: null,
|
|
430
430
|
name: deviceData[j].name
|
|
431
431
|
});
|
|
432
432
|
} else {
|
|
433
|
-
|
|
433
|
+
attributes.push({
|
|
434
434
|
type: deviceData[j].type,
|
|
435
435
|
value: obj.value,
|
|
436
436
|
name: deviceData[j].name
|
|
437
437
|
});
|
|
438
438
|
}
|
|
439
|
-
}
|
|
439
|
+
}
|
|
440
440
|
}
|
|
441
441
|
return attributes;
|
|
442
442
|
}
|
|
443
|
-
|
|
444
443
|
|
|
445
444
|
deviceService.getDeviceByName(
|
|
446
445
|
entityId,
|
|
@@ -451,8 +450,8 @@ function generateMergePatchActionNgsiLD(req, callback) {
|
|
|
451
450
|
callback(error);
|
|
452
451
|
} else {
|
|
453
452
|
const attributes = [];
|
|
454
|
-
addAttributes(deviceObj.commands, req.body, attributes)
|
|
455
|
-
addAttributes(deviceObj.lazy, req.body, attributes)
|
|
453
|
+
addAttributes(deviceObj.commands, req.body, attributes);
|
|
454
|
+
addAttributes(deviceObj.lazy, req.body, attributes);
|
|
456
455
|
const executeMergePatchHandler = apply(
|
|
457
456
|
contextServerUtils.mergePatchHandler,
|
|
458
457
|
entityId,
|
|
@@ -461,10 +460,7 @@ function generateMergePatchActionNgsiLD(req, callback) {
|
|
|
461
460
|
contextServerUtils.getLDPath(req),
|
|
462
461
|
attributes
|
|
463
462
|
);
|
|
464
|
-
async.waterfall(
|
|
465
|
-
[executeMergePatchHandler],
|
|
466
|
-
callback()
|
|
467
|
-
);
|
|
463
|
+
async.waterfall([executeMergePatchHandler], callback());
|
|
468
464
|
}
|
|
469
465
|
}
|
|
470
466
|
);
|
|
@@ -477,7 +473,6 @@ function generateMergePatchActionNgsiLD(req, callback) {
|
|
|
477
473
|
* @param {Object} res Response that will be sent.
|
|
478
474
|
*/
|
|
479
475
|
function handleMergePatchNgsiLD(req, res, next) {
|
|
480
|
-
|
|
481
476
|
function handleMergePatchRequest(error, result) {
|
|
482
477
|
if (error) {
|
|
483
478
|
logger.debug(context, 'There was an error handling the merge-patch: %s.', error);
|
|
@@ -492,15 +487,15 @@ function handleMergePatchNgsiLD(req, res, next) {
|
|
|
492
487
|
if ((req.is('json') || req.is('application/ld+json')) === false) {
|
|
493
488
|
return handleMergePatchRequest(new errors.UnsupportedContentType(req.header('content-type')));
|
|
494
489
|
}
|
|
495
|
-
|
|
490
|
+
|
|
496
491
|
if (req.body) {
|
|
497
492
|
logger.debug(context, JSON.stringify(req.body, null, 4));
|
|
498
493
|
}
|
|
499
494
|
|
|
500
|
-
if (contextServerUtils.mergePatchHandler){
|
|
495
|
+
if (contextServerUtils.mergePatchHandler) {
|
|
501
496
|
generateMergePatchActionNgsiLD(req, handleMergePatchRequest);
|
|
502
497
|
} else {
|
|
503
|
-
|
|
498
|
+
return handleMergePatchRequest(new errors.MethodNotSupported(req.method, req.path));
|
|
504
499
|
}
|
|
505
500
|
}
|
|
506
501
|
|
|
@@ -610,7 +605,7 @@ function handleQueryNgsiLD(req, res, next) {
|
|
|
610
605
|
getFunction(function handleFindDevice(error, innerDevice) {
|
|
611
606
|
let deviceList = [];
|
|
612
607
|
if (!innerDevice) {
|
|
613
|
-
return callback(new errors.DeviceNotFound(contextEntity.id));
|
|
608
|
+
return callback(new errors.DeviceNotFound(contextEntity.id, contextEntity));
|
|
614
609
|
}
|
|
615
610
|
|
|
616
611
|
if (innerDevice.count) {
|
|
@@ -689,7 +684,7 @@ function ErrorHandlingNgsiLD(action) {
|
|
|
689
684
|
error: error.name,
|
|
690
685
|
description: error.message.replace(/[<>\"\'=;\(\)]/g, '')
|
|
691
686
|
});
|
|
692
|
-
}
|
|
687
|
+
};
|
|
693
688
|
}
|
|
694
689
|
|
|
695
690
|
/**
|
|
@@ -812,7 +807,7 @@ function loadUnsupportedEndpointsNGSILD(router) {
|
|
|
812
807
|
function loadContextRoutesNGSILD(router) {
|
|
813
808
|
// In a more evolved implementation, more endpoints could be added to queryPathsNgsi2
|
|
814
809
|
// according to https://www.etsi.org/standards-search#page=1&search=GS%20CIM%20009
|
|
815
|
-
|
|
810
|
+
|
|
816
811
|
const support = config.getConfig().server.ldSupport;
|
|
817
812
|
let i;
|
|
818
813
|
|
|
@@ -832,7 +827,7 @@ function loadContextRoutesNGSILD(router) {
|
|
|
832
827
|
router.patch('/ngsi-ld/v1/entities/:entity', [
|
|
833
828
|
preprocessNGSILD,
|
|
834
829
|
validateNGSILD(support.null, support.datasetId),
|
|
835
|
-
handleMergePatchNgsiLD,
|
|
830
|
+
handleMergePatchNgsiLD,
|
|
836
831
|
ErrorHandlingNgsiLD('Merge-Patch')
|
|
837
832
|
]);
|
|
838
833
|
|
|
@@ -503,7 +503,7 @@ function handleQueryNgsi2(req, res, next) {
|
|
|
503
503
|
getFunction(function handleFindDevice(error, innerDevice) {
|
|
504
504
|
let deviceList = [];
|
|
505
505
|
if (!innerDevice) {
|
|
506
|
-
return callback(new errors.DeviceNotFound(contextEntity.id));
|
|
506
|
+
return callback(new errors.DeviceNotFound(contextEntity.id), contextEntity);
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
if (innerDevice.count) {
|
|
@@ -263,40 +263,50 @@ function handleGetDevice(req, res, next) {
|
|
|
263
263
|
} else if (device) {
|
|
264
264
|
res.status(200).json(toProvisioningAPIFormat(device));
|
|
265
265
|
} else {
|
|
266
|
-
next(new errors.DeviceNotFound(req.params.deviceId)
|
|
266
|
+
next(new errors.DeviceNotFound(req.params.deviceId), {
|
|
267
|
+
apikey: req.query.apikey,
|
|
268
|
+
service: req.headers['fiware-service'],
|
|
269
|
+
subservice: req.headers['fiware-servicepath']
|
|
270
|
+
});
|
|
267
271
|
}
|
|
268
272
|
}
|
|
269
273
|
);
|
|
270
274
|
}
|
|
271
275
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
deviceService.getDevice(deviceId, apikey, service, subservice, function (error, device) {
|
|
278
|
-
if (error) {
|
|
279
|
-
callback(error);
|
|
280
|
-
} else if (device) {
|
|
281
|
-
callback(null, device);
|
|
282
|
-
} else {
|
|
283
|
-
callback(new errors.DeviceNotFound(deviceId));
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function applyRemoveDeviceHandler(device, callback) {
|
|
289
|
-
if (removeDeviceHandler) {
|
|
290
|
-
removeDeviceHandler(device, callback);
|
|
291
|
-
} else {
|
|
276
|
+
function getDevice(deviceId, apikey, service, subservice, callback) {
|
|
277
|
+
deviceService.getDevice(deviceId, apikey, service, subservice, function (error, device) {
|
|
278
|
+
if (error) {
|
|
279
|
+
callback(error);
|
|
280
|
+
} else if (device) {
|
|
292
281
|
callback(null, device);
|
|
282
|
+
} else {
|
|
283
|
+
callback(
|
|
284
|
+
new errors.DeviceNotFound(deviceId, {
|
|
285
|
+
apikey: apikey,
|
|
286
|
+
service: service,
|
|
287
|
+
subservice: subservice
|
|
288
|
+
})
|
|
289
|
+
);
|
|
293
290
|
}
|
|
294
|
-
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
295
293
|
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
function applyRemoveDeviceHandler(device, callback) {
|
|
295
|
+
if (removeDeviceHandler) {
|
|
296
|
+
removeDeviceHandler(device, callback);
|
|
297
|
+
} else {
|
|
298
|
+
callback(null, device);
|
|
298
299
|
}
|
|
300
|
+
}
|
|
299
301
|
|
|
302
|
+
function unregisterDevice(deviceId, apikey, service, subservice, device, callback) {
|
|
303
|
+
return deviceService.unregister(deviceId, apikey, service, subservice, callback);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* This middleware handles the removal of a particular device specified with the deviceId.
|
|
308
|
+
*/
|
|
309
|
+
function handleRemoveDevice(req, res, next) {
|
|
300
310
|
async.waterfall(
|
|
301
311
|
[
|
|
302
312
|
apply(statsRegistry.add, 'deviceRemovalRequests', 1),
|
|
@@ -320,7 +330,13 @@ function handleRemoveDevice(req, res, next) {
|
|
|
320
330
|
if (error && error.code !== 404) {
|
|
321
331
|
next(error);
|
|
322
332
|
} else if (error && error.code === 404) {
|
|
323
|
-
next(
|
|
333
|
+
next(
|
|
334
|
+
new errors.DeviceNotFound(req.params.deviceId, {
|
|
335
|
+
apikey: req.query.apikey,
|
|
336
|
+
service: req.headers['fiware-service'],
|
|
337
|
+
subservice: req.headers['fiware-servicepath']
|
|
338
|
+
})
|
|
339
|
+
);
|
|
324
340
|
} else {
|
|
325
341
|
res.status(204).send();
|
|
326
342
|
}
|
|
@@ -328,6 +344,56 @@ function handleRemoveDevice(req, res, next) {
|
|
|
328
344
|
);
|
|
329
345
|
}
|
|
330
346
|
|
|
347
|
+
/**
|
|
348
|
+
* This middleware handles the removal of several devices specified in a array into a body
|
|
349
|
+
*/
|
|
350
|
+
function handleRemoveDevices(req, res, next) {
|
|
351
|
+
logger.debug(context, 'Handling delete of devices: %j', req.body);
|
|
352
|
+
let theErrorOut = false;
|
|
353
|
+
for (let devicetoRemove of req.body.devices) {
|
|
354
|
+
let theError = theErrorOut;
|
|
355
|
+
async.waterfall(
|
|
356
|
+
[
|
|
357
|
+
apply(statsRegistry.add, 'deviceRemovalRequests', 1),
|
|
358
|
+
apply(
|
|
359
|
+
getDevice,
|
|
360
|
+
devicetoRemove.deviceId,
|
|
361
|
+
devicetoRemove.apikey,
|
|
362
|
+
req.headers['fiware-service'],
|
|
363
|
+
req.headers['fiware-servicepath']
|
|
364
|
+
),
|
|
365
|
+
applyRemoveDeviceHandler,
|
|
366
|
+
apply(
|
|
367
|
+
unregisterDevice,
|
|
368
|
+
devicetoRemove.deviceId,
|
|
369
|
+
devicetoRemove.apikey,
|
|
370
|
+
req.headers['fiware-service'],
|
|
371
|
+
req.headers['fiware-servicepath']
|
|
372
|
+
)
|
|
373
|
+
],
|
|
374
|
+
function (error) {
|
|
375
|
+
if (error && error.code !== 404) {
|
|
376
|
+
theError = !theError ? error : theError;
|
|
377
|
+
} else if (error && error.code === 404) {
|
|
378
|
+
theError = !theError
|
|
379
|
+
? new errors.DeviceNotFound(devicetoRemove.deviceId, {
|
|
380
|
+
apikey: devicetoRemove.apikey,
|
|
381
|
+
service: req.headers['fiware-service'],
|
|
382
|
+
subservice: req.headers['fiware-servicepath']
|
|
383
|
+
})
|
|
384
|
+
: theError;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
); // waterfall
|
|
388
|
+
theErrorOut = theError;
|
|
389
|
+
} // for
|
|
390
|
+
if (theErrorOut) {
|
|
391
|
+
next(theErrorOut);
|
|
392
|
+
} else {
|
|
393
|
+
res.status(204).send();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
331
397
|
/**
|
|
332
398
|
* This middleware handles updates in the provisioning devices. The only attribute
|
|
333
399
|
*/
|
|
@@ -379,7 +445,13 @@ function handleUpdateDevice(req, res, next) {
|
|
|
379
445
|
}
|
|
380
446
|
);
|
|
381
447
|
} else {
|
|
382
|
-
next(
|
|
448
|
+
next(
|
|
449
|
+
new errors.DeviceNotFound(req.params.deviceId, {
|
|
450
|
+
apikey: req.query.apikey,
|
|
451
|
+
service: req.headers['fiware-service'],
|
|
452
|
+
subservice: req.headers['fiware-servicepath']
|
|
453
|
+
})
|
|
454
|
+
);
|
|
383
455
|
}
|
|
384
456
|
}
|
|
385
457
|
);
|
|
@@ -414,6 +486,8 @@ function loadContextRoutes(router) {
|
|
|
414
486
|
handleUpdateDevice
|
|
415
487
|
);
|
|
416
488
|
|
|
489
|
+
router.post('/iot/op/delete', restUtils.checkRequestAttributes('headers', mandatoryHeaders), handleRemoveDevices);
|
|
490
|
+
|
|
417
491
|
router.delete(
|
|
418
492
|
'/iot/devices/:deviceId',
|
|
419
493
|
restUtils.checkRequestAttributes('headers', mandatoryHeaders),
|
|
@@ -65,7 +65,7 @@ function checkMandatoryQueryParams(mandatoryAttributes, body, callback) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
if (missing.length !== 0) {
|
|
68
|
-
const error = new errors.MissingAttributes('Missing attributes: ' + JSON.stringify(missing));
|
|
68
|
+
const error = new errors.MissingAttributes('Missing attributes: ' + JSON.stringify(missing), body);
|
|
69
69
|
error.code = '400';
|
|
70
70
|
|
|
71
71
|
callback(error);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "iotagent-node-lib",
|
|
3
3
|
"license": "AGPL-3.0-only",
|
|
4
4
|
"description": "IoT Agent library to interface with NGSI Context Broker",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.4.0",
|
|
6
6
|
"homepage": "https://github.com/telefonicaid/iotagent-node-lib",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"fiware",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"async": "2.6.4",
|
|
47
47
|
"body-parser": "~1.20.0",
|
|
48
|
-
"express": "~4.
|
|
48
|
+
"express": "~4.19.2",
|
|
49
49
|
"got": "~11.8.5",
|
|
50
50
|
"jexl": "2.3.0",
|
|
51
51
|
"jison": "0.4.18",
|