iotagent-node-lib 4.2.0 → 4.3.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 +114 -59
- package/lib/errors.js +45 -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 +6 -4
- package/lib/services/devices/deviceService.js +3 -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 +20 -12
- 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 +1 -1
- package/test/functional/testCases.js +34 -34
- 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/provisioning/removeProvisionedDevice-test.js +37 -2
|
@@ -89,7 +89,13 @@ function updateEntityHandlerNgsi2(deviceData, updatedDevice, callback) {
|
|
|
89
89
|
body
|
|
90
90
|
);
|
|
91
91
|
|
|
92
|
-
const errorObj = new errors.EntityGenericError(
|
|
92
|
+
const errorObj = new errors.EntityGenericError(
|
|
93
|
+
deviceData.id,
|
|
94
|
+
deviceData.type,
|
|
95
|
+
deviceData,
|
|
96
|
+
body,
|
|
97
|
+
response.statusCode
|
|
98
|
+
);
|
|
93
99
|
|
|
94
100
|
callback(errorObj);
|
|
95
101
|
}
|
|
@@ -204,7 +210,7 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) {
|
|
|
204
210
|
// Format any GeoJSON attrs properly
|
|
205
211
|
options.json[att] = NGSIv2.formatGeoAttrs(options.json[att]);
|
|
206
212
|
} catch (error) {
|
|
207
|
-
return callback(new errors.BadGeocoordinates(JSON.stringify(options.json)));
|
|
213
|
+
return callback(new errors.BadGeocoordinates(JSON.stringify(options.json), deviceData));
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
216
|
|
|
@@ -243,7 +249,7 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) {
|
|
|
243
249
|
*/
|
|
244
250
|
function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
245
251
|
if (!deviceObj.id || !deviceObj.type) {
|
|
246
|
-
callback(new errors.MissingAttributes('Id or device missing'));
|
|
252
|
+
callback(new errors.MissingAttributes('Id or device missing', deviceObj));
|
|
247
253
|
return;
|
|
248
254
|
}
|
|
249
255
|
|
|
@@ -282,7 +288,7 @@ function updateRegisterDeviceNgsi2(deviceObj, entityInfoUpdated, callback) {
|
|
|
282
288
|
|
|
283
289
|
callback(null, oldDevice);
|
|
284
290
|
} else {
|
|
285
|
-
callback(new errors.DeviceNotFound(newDevice.id));
|
|
291
|
+
callback(new errors.DeviceNotFound(newDevice.id, newDevice));
|
|
286
292
|
}
|
|
287
293
|
}
|
|
288
294
|
|
|
@@ -50,7 +50,7 @@ function exists(group) {
|
|
|
50
50
|
|
|
51
51
|
function createGroup(group, callback) {
|
|
52
52
|
if (exists(group)) {
|
|
53
|
-
callback(new errors.DuplicateGroup(group
|
|
53
|
+
callback(new errors.DuplicateGroup(group));
|
|
54
54
|
} else {
|
|
55
55
|
const storeGroup = _.clone(group);
|
|
56
56
|
|
|
@@ -110,7 +110,7 @@ function createGroup(group, callback) {
|
|
|
110
110
|
group.apikey
|
|
111
111
|
);
|
|
112
112
|
|
|
113
|
-
callback(new errors.DuplicateGroup(group
|
|
113
|
+
callback(new errors.DuplicateGroup(group));
|
|
114
114
|
} else {
|
|
115
115
|
logger.debug(context, 'Error storing device group information: %s', error);
|
|
116
116
|
|
|
@@ -48,7 +48,7 @@ function validateGroup(group, callback) {
|
|
|
48
48
|
return function (error, foundGroup) {
|
|
49
49
|
logger.debug(context, 'generateDuplicateHander error %j and foundGroup %j', error, foundGroup);
|
|
50
50
|
if (!error || (foundGroup && foundGroup.count > 0)) {
|
|
51
|
-
innerCb(new errors.DuplicateGroup(group
|
|
51
|
+
innerCb(new errors.DuplicateGroup(group));
|
|
52
52
|
} else {
|
|
53
53
|
innerCb();
|
|
54
54
|
}
|
|
@@ -291,8 +291,14 @@ function getEffectiveApiKey(service, subservice, type, callback) {
|
|
|
291
291
|
logger.debug(context, 'Using default API Key: %s', config.getConfig().defaultKey);
|
|
292
292
|
callback(null, config.getConfig().defaultKey);
|
|
293
293
|
} else {
|
|
294
|
-
logger.error(
|
|
295
|
-
|
|
294
|
+
logger.error(
|
|
295
|
+
context,
|
|
296
|
+
'Could not find any APIKey information for device in service %s subservice %s and type %s',
|
|
297
|
+
service,
|
|
298
|
+
subservice,
|
|
299
|
+
type
|
|
300
|
+
);
|
|
301
|
+
callback(new errors.GroupNotFound(service, subservice, type));
|
|
296
302
|
}
|
|
297
303
|
}
|
|
298
304
|
|
|
@@ -381,9 +381,9 @@ function generateNGSILDOperationHandler(operationName, entityName, typeInformati
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
if (errorField !== undefined) {
|
|
384
|
-
callback(new errors.DeviceNotFound(entityName));
|
|
384
|
+
callback(new errors.DeviceNotFound(entityName, typeInformation));
|
|
385
385
|
} else {
|
|
386
|
-
callback(new errors.EntityGenericError(entityName, typeInformation.type, body));
|
|
386
|
+
callback(new errors.EntityGenericError(entityName, typeInformation.type, typeInformation, body));
|
|
387
387
|
}
|
|
388
388
|
} else {
|
|
389
389
|
logger.debug(context, 'Unknown error executing ' + operationName + ' operation');
|
|
@@ -391,7 +391,15 @@ function generateNGSILDOperationHandler(operationName, entityName, typeInformati
|
|
|
391
391
|
body = JSON.parse(body);
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
callback(
|
|
394
|
+
callback(
|
|
395
|
+
new errors.EntityGenericError(
|
|
396
|
+
entityName,
|
|
397
|
+
typeInformation.type,
|
|
398
|
+
typeInformation,
|
|
399
|
+
body,
|
|
400
|
+
response.statusCode
|
|
401
|
+
)
|
|
402
|
+
);
|
|
395
403
|
}
|
|
396
404
|
};
|
|
397
405
|
}
|
|
@@ -416,7 +424,7 @@ function sendQueryValueNgsiLD(entityName, attributes, typeInformation, token, ca
|
|
|
416
424
|
options.method = 'GET';
|
|
417
425
|
|
|
418
426
|
if (!typeInformation || !typeInformation.type) {
|
|
419
|
-
callback(new errors.TypeNotFound(null, entityName));
|
|
427
|
+
callback(new errors.TypeNotFound(null, entityName, typeInformation));
|
|
420
428
|
return;
|
|
421
429
|
}
|
|
422
430
|
|
|
@@ -529,7 +537,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
|
|
|
529
537
|
}
|
|
530
538
|
|
|
531
539
|
if (!typeInformation || !typeInformation.type) {
|
|
532
|
-
callback(new errors.TypeNotFound(null, entityName));
|
|
540
|
+
callback(new errors.TypeNotFound(null, entityName, typeInformation));
|
|
533
541
|
return;
|
|
534
542
|
}
|
|
535
543
|
const idTypeSSSList = pluginUtils.getIdTypeServSubServiceFromDevice(typeInformation);
|
|
@@ -1015,7 +1023,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
|
|
|
1015
1023
|
} else if (!utils.IsValidTimestampedNgsi2(payload[n])) {
|
|
1016
1024
|
// legacy check needed?
|
|
1017
1025
|
logger.error(context, 'Invalid timestamp:%s', JSON.stringify(payload[0]));
|
|
1018
|
-
callback(new errors.BadTimestamp(payload, entityName));
|
|
1026
|
+
callback(new errors.BadTimestamp(payload, entityName, typeInformation));
|
|
1019
1027
|
return;
|
|
1020
1028
|
}
|
|
1021
1029
|
}
|
|
@@ -1044,7 +1052,7 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
|
|
|
1044
1052
|
options.json = [formatAsNGSILD(options.json)];
|
|
1045
1053
|
}
|
|
1046
1054
|
} catch (error) {
|
|
1047
|
-
return callback(new errors.BadGeocoordinates(JSON.stringify(payload)));
|
|
1055
|
+
return callback(new errors.BadGeocoordinates(JSON.stringify(payload), typeInformation));
|
|
1048
1056
|
}
|
|
1049
1057
|
|
|
1050
1058
|
if (typeInformation.active) {
|
|
@@ -31,7 +31,6 @@ const request = require('../../request-shim');
|
|
|
31
31
|
const alarms = require('../common/alarmManagement');
|
|
32
32
|
const errors = require('../../errors');
|
|
33
33
|
const pluginUtils = require('../../plugins/pluginUtils');
|
|
34
|
-
const config = require('../../commonConfig');
|
|
35
34
|
const constants = require('../../constants');
|
|
36
35
|
const jexlParser = require('../../plugins/jexlParser');
|
|
37
36
|
const expressionPlugin = require('../../plugins/expressionPlugin');
|
|
@@ -173,9 +172,9 @@ function generateNGSI2OperationHandler(operationName, entityName, typeInformatio
|
|
|
173
172
|
}
|
|
174
173
|
|
|
175
174
|
if (errorField !== undefined) {
|
|
176
|
-
callback(new errors.DeviceNotFound(entityName));
|
|
175
|
+
callback(new errors.DeviceNotFound(entityName, typeInformation));
|
|
177
176
|
} else {
|
|
178
|
-
callback(new errors.EntityGenericError(entityName, typeInformation.type, body));
|
|
177
|
+
callback(new errors.EntityGenericError(entityName, typeInformation.type, typeInformation, body));
|
|
179
178
|
}
|
|
180
179
|
} else {
|
|
181
180
|
logger.debug(context, 'Unknown error executing ' + operationName + ' operation');
|
|
@@ -183,7 +182,15 @@ function generateNGSI2OperationHandler(operationName, entityName, typeInformatio
|
|
|
183
182
|
body = JSON.parse(body);
|
|
184
183
|
}
|
|
185
184
|
|
|
186
|
-
callback(
|
|
185
|
+
callback(
|
|
186
|
+
new errors.EntityGenericError(
|
|
187
|
+
entityName,
|
|
188
|
+
typeInformation.type,
|
|
189
|
+
typeInformation,
|
|
190
|
+
body,
|
|
191
|
+
response.statusCode
|
|
192
|
+
)
|
|
193
|
+
);
|
|
187
194
|
}
|
|
188
195
|
};
|
|
189
196
|
}
|
|
@@ -225,7 +232,7 @@ function sendQueryValueNgsi2(entityName, attributes, typeInformation, token, cal
|
|
|
225
232
|
options.method = 'GET';
|
|
226
233
|
|
|
227
234
|
if (!typeInformation || !typeInformation.type) {
|
|
228
|
-
callback(new errors.TypeNotFound(null, entityName));
|
|
235
|
+
callback(new errors.TypeNotFound(null, entityName, typeInformation));
|
|
229
236
|
return;
|
|
230
237
|
}
|
|
231
238
|
|
|
@@ -279,7 +286,7 @@ function sendUpdateValueNgsi2(entityName, measures, typeInformation, token, call
|
|
|
279
286
|
|
|
280
287
|
//Check mandatory information: type
|
|
281
288
|
if (!typeInformation || !typeInformation.type) {
|
|
282
|
-
callback(new errors.TypeNotFound(null, entityName));
|
|
289
|
+
callback(new errors.TypeNotFound(null, entityName, typeInformation));
|
|
283
290
|
return;
|
|
284
291
|
}
|
|
285
292
|
//Rename all measures with matches with id and type to measure_id and measure_type
|
|
@@ -301,11 +308,9 @@ function sendUpdateValueNgsi2(entityName, measures, typeInformation, token, call
|
|
|
301
308
|
jexlctxt = reduceAttrToPlainObject(idTypeSSSList, jexlctxt);
|
|
302
309
|
|
|
303
310
|
//Managing timestamp (mustInsertTimeInstant flag to decide if we should insert Timestamp later on)
|
|
304
|
-
const mustInsertTimeInstant =
|
|
305
|
-
typeInformation.timestamp !== undefined
|
|
306
|
-
? typeInformation.timestamp
|
|
307
|
-
: config.getConfig().timestamp !== undefined
|
|
308
|
-
? config.getConfig().timestamp
|
|
311
|
+
const mustInsertTimeInstant =
|
|
312
|
+
typeInformation.timestamp !== undefined
|
|
313
|
+
? typeInformation.timestamp
|
|
309
314
|
: false;
|
|
310
315
|
|
|
311
316
|
if (mustInsertTimeInstant) {
|
|
@@ -317,7 +322,10 @@ function sendUpdateValueNgsi2(entityName, measures, typeInformation, token, call
|
|
|
317
322
|
if (moment(plainMeasures[constants.TIMESTAMP_ATTRIBUTE], moment.ISO_8601, true).isValid()) {
|
|
318
323
|
timestamp.value = plainMeasures[constants.TIMESTAMP_ATTRIBUTE];
|
|
319
324
|
} else {
|
|
320
|
-
callback(
|
|
325
|
+
callback(
|
|
326
|
+
new errors.BadTimestamp(plainMeasures[constants.TIMESTAMP_ATTRIBUTE], entityName, typeInformation)
|
|
327
|
+
);
|
|
328
|
+
return;
|
|
321
329
|
}
|
|
322
330
|
} else if (!typeInformation.timezone) {
|
|
323
331
|
timestamp.value = new Date().toISOString();
|
|
@@ -144,9 +144,9 @@ function executeWithDeviceInformation(operationFunction) {
|
|
|
144
144
|
// For preregistered devices, augment the existing deviceInformation with selected attributes.
|
|
145
145
|
if (!callback) {
|
|
146
146
|
callback = deviceInformation;
|
|
147
|
-
typeInformation = deviceGroup || configDeviceInfo;
|
|
147
|
+
typeInformation = deviceGroup || { ...config.getConfig(), ...configDeviceInfo };
|
|
148
148
|
} else {
|
|
149
|
-
typeInformation = deviceInformation;
|
|
149
|
+
typeInformation = { ...config.getConfig(), ...deviceInformation };
|
|
150
150
|
attributeList.forEach((key) => {
|
|
151
151
|
typeInformation[key] =
|
|
152
152
|
typeInformation[key] || (deviceGroup || {})[key] || (configDeviceInfo || {})[key];
|
|
@@ -236,7 +236,7 @@ function setCommandResult(
|
|
|
236
236
|
if (commandInfo.length === 1) {
|
|
237
237
|
exports.update(entityName, typeInformation.type, apikey, attributes, typeInformation, callback);
|
|
238
238
|
} else {
|
|
239
|
-
callback(new errors.CommandNotFound(commandName));
|
|
239
|
+
callback(new errors.CommandNotFound(commandName, typeInformation));
|
|
240
240
|
}
|
|
241
241
|
});
|
|
242
242
|
}
|
|
@@ -62,6 +62,7 @@ function createSubscriptionHandlerNgsiLD(device, triggers, store, callback) {
|
|
|
62
62
|
new errors.EntityGenericError(
|
|
63
63
|
device.name,
|
|
64
64
|
device.type,
|
|
65
|
+
device,
|
|
65
66
|
{
|
|
66
67
|
details: body
|
|
67
68
|
},
|
|
@@ -183,6 +184,7 @@ function createUnsubscribeHandlerNgsiLD(device, id, callback) {
|
|
|
183
184
|
new errors.EntityGenericError(
|
|
184
185
|
device.name,
|
|
185
186
|
device.type,
|
|
187
|
+
device,
|
|
186
188
|
{
|
|
187
189
|
details: body
|
|
188
190
|
},
|
|
@@ -64,6 +64,7 @@ function createSubscriptionHandlerNgsi2(device, triggers, store, callback) {
|
|
|
64
64
|
new errors.EntityGenericError(
|
|
65
65
|
device.name,
|
|
66
66
|
device.type,
|
|
67
|
+
device,
|
|
67
68
|
{
|
|
68
69
|
details: body
|
|
69
70
|
},
|
|
@@ -183,6 +184,7 @@ function createUnsubscribeHandlerNgsi2(device, id, callback) {
|
|
|
183
184
|
new errors.EntityGenericError(
|
|
184
185
|
device.name,
|
|
185
186
|
device.type,
|
|
187
|
+
device,
|
|
186
188
|
{
|
|
187
189
|
details: body
|
|
188
190
|
},
|
|
@@ -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) {
|