Skip to content

Commit

Permalink
Merge branch 'master' into fix/use_trust_cbHost_from_deviceGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
AlvaroVega committed Nov 19, 2018
2 parents cf202c5 + 7da6d83 commit b61faa3
Show file tree
Hide file tree
Showing 24 changed files with 510 additions and 43 deletions.
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"node": true,
"expr": true,
"unused": "vars",
"esversion": 6,
"globals": {
"describe":true,
"it": true,
Expand Down
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ install:
before_install:
- npm update -q

before_script:
- npm run lint

3 changes: 3 additions & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Fix: use trust and cbHost from deviceGroup (#685)
Fix: multientity multimeasure with the same att name
Add missed conf env vars about authentication (#704)
Add timestamp in device and group provision (#655)
Fix: missing support for device=true in the delete service endpoint (see #596)
Expand All @@ -23,3 +24,5 @@ Fix: updating dependencies due to known vulnerabilities in the previous ones
Remove: old unused dependencies (sax, grunt, closure-linter-wrapper)
Fix: mosquitto.conf.example file not found by iot/mosquitto Dockerfile (#554)
Fix: isDomain is not used anymore for context availability registration (#701)
Fix: checks ISO8601 timeinstants provided by devices (#679)
Fix: corrects linting and includes npm run lint in travis
7 changes: 7 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*
* For those usages not covered by the GNU Affero General Public License
* please contact with::[email protected]
*
* Modified by: Daniel Calvo - ATOS Research & Innovation
*/

'use strict';
Expand Down Expand Up @@ -168,5 +170,10 @@ module.exports = {
this.name = 'BAD_ANSWER';
this.message = 'Invalid statusCode in operation [' + operation + ']';
this.code = 400;
},
BadTimestamp: function(payload) {
this.name = 'BAD_TIMESTAMP';
this.message = 'Invalid ISO8601 timestamp [' + payload + ']';
this.code = 400;
}
};
8 changes: 4 additions & 4 deletions lib/plugins/attributeAlias.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@

var config = require('../commonConfig'),
utils = require('./pluginUtils'),
/*jshint unused:false*/
logger = require('logops'),
/*jshint unused:false*/
context = {
op: 'IoTAgentNGSI.attributeAlias'
},
Expand All @@ -38,10 +40,7 @@ function extractSingleMapping(previous, current) {

previous.direct[current.object_id] = current.name;
previous.types[current.object_id] = current.type;
if (!previous.inverse[current.name]) {
previous.inverse[current.name] = [];
}
previous.inverse[current.name].push(current.object_id); // collision using multientity
previous.inverse[current.name] = current.object_id; // collision using multientity
return previous;
}

Expand Down Expand Up @@ -79,6 +78,7 @@ function applyAlias(mappings) {
return function aliasApplier(attribute) {
if (mappings.direct[attribute.name]) {
if (config.checkNgsi2()) {
/*jshint camelcase: false */
attribute.object_id = attribute.name; // inverse not usefull due to collision
}
attribute.type = mappings.types[attribute.name];
Expand Down
2 changes: 2 additions & 0 deletions lib/plugins/expressionParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ function expressionApplier(context, typeInformation) {
name: attribute.name,
type: attribute.type
};

/*jshint camelcase: false */
if (config.checkNgsi2() && attribute.object_id) {
newAttribute.object_id = attribute.object_id;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/plugins/expressionPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
var _ = require('underscore'),
parser = require('./expressionParser'),
config = require('../commonConfig'),
/*jshint unused:false*/
logger = require('logops'),
/*jshint unused:false*/
context = {
op: 'IoTAgentNGSI.expressionPlugin'
},
Expand Down
47 changes: 40 additions & 7 deletions lib/plugins/multiEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
var _ = require('underscore'),
parser = require('./expressionParser'),
config = require('../commonConfig'),
/*jshint unused:false*/
logger = require('logops'),
/*jshint unused:false*/
context = {
op: 'IoTAgentNGSI.MultiEntityPlugin'
},
Expand Down Expand Up @@ -158,6 +160,7 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation,
if (entity.hasOwnProperty(att)) {
if (_.contains(newEntityAttributeNames, att)) {
if (entity[att].multi && entity[att].multi.length > 0) {
// jshint maxdepth:7
if (mappings.inverse[att] && mappings.inverse[att].length > 0) {
for (var j in (mappings.inverse[att])) {
if (_.contains(newEntityAttributeObjectIds, mappings.inverse[att][j])) {
Expand All @@ -167,10 +170,12 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation,
}
}
}
for (var j in entity[att].multi) {
if (entity[att].multi[j].object_id && _.contains(newEntityAttributeObjectIds, entity[att].multi[j].object_id)) {
result[att] = entity[att].multi[j];
delete entity[att].multi[j].object_id;
// jshint maxdepth:7
for (var k in entity[att].multi) {
if (entity[att].multi[k].object_id && _.contains(newEntityAttributeObjectIds,
entity[att].multi[k].object_id)) {
result[att] = entity[att].multi[k];
delete entity[att].multi[k].object_id;
}
}
} else {
Expand All @@ -184,13 +189,41 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation,
return result;
}

function filterByAttributeObjectIds() {
var result = {};
for (var att in entity) {
if (entity.hasOwnProperty(att)) {
if (_.contains(newEntityAttributeNames, att)) {
if (entity[att].object_id && _.contains(newEntityAttributeObjectIds, entity[att].object_id )){
result[att] = entity[att];
delete entity[att].object_id;
} else {
// Check matches in rest of multientity attributes with same name (#635)
// jshint maxdepth:7
if (entity[att].multi) {
for (var j in entity[att].multi) {
if (entity[att].multi[j].object_id &&
_.contains(newEntityAttributeObjectIds, entity[att].multi[j].object_id)) {
result[att] = entity[att].multi[j];
delete entity[att].multi[j].object_id;
}
}
}
}
}
}
}
return result;
}

var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity);
ctx = parser.extractContext(attsArray);

for (var i = 0; i < newEntities.length; i++) {
newEntityAttributeNames = _.pluck(multiEntityAttributes.filter(filterByEntityName(newEntities[i])), 'name');
newEntityAttributeObjectIds = _.pluck(multiEntityAttributes.filter(filterByEntityName(newEntities[i])), 'object_id');
newEntityAttributes = filterAttributes();
newEntityAttributeObjectIds = _.pluck(multiEntityAttributes.filter(
filterByEntityName(newEntities[i])), 'object_id');
newEntityAttributes = filterByAttributeObjectIds();
entityName = parser.applyExpression(newEntities[i], ctx, typeInformation);

newEntityAttributes.type = entityTypes[newEntities[i]];
Expand Down Expand Up @@ -264,4 +297,4 @@ function updateAttribute(entity, typeInformation, callback) {
}
}

exports.update = updateAttribute;
exports.update = updateAttribute;
11 changes: 9 additions & 2 deletions lib/plugins/pluginUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function extractAttributesArrayFromNgsi2Entity(entity) {
if (i !== 'id' && i !== 'type') {
var att = Object.assign({}, entity[i]);
if (att.multi) {
// jshint maxdepth:5
for (var j in att.multi) {
var matt = Object.assign({}, entity[i].multi[j]);
matt.name = i;
Expand All @@ -61,21 +62,24 @@ function extractAttributesArrayFromNgsi2Entity(entity) {
* @param {String} id The identifier
* @param {String} type The type
* @param {Object} attsArray The atts array
* @param {Object} withObjectId The flag to keep object_id
* @return {Object} A NGSIv2 entity
*/
function createNgsi2Entity(id, type, attsArray, objectId) {
function createNgsi2Entity(id, type, attsArray, withObjectId) {
var entity = {};
entity.id = id;
entity.type = type;
for (var i = 0; i < attsArray.length; i++) {
if (entity[attsArray[i].name] && objectId && attsArray[i].object_id) {
/*jshint camelcase: false */
if (entity[attsArray[i].name] && withObjectId && attsArray[i].object_id) {
// Check if multiple measures with multientity attributes with same name(#635)
if (!entity[attsArray[i].name].multi) {
entity[attsArray[i].name].multi = [];
}
entity[attsArray[i].name].multi.push({
'type' : attsArray[i].type,
'value' : attsArray[i].value,
/*jshint camelcase: false */
'object_id' : attsArray[i].object_id,
'metadata' : attsArray[i].metadata
});
Expand All @@ -85,6 +89,9 @@ function createNgsi2Entity(id, type, attsArray, objectId) {
'value' : attsArray[i].value,
'metadata' : attsArray[i].metadata
};
if (withObjectId && attsArray[i].object_id) {
entity[attsArray[i].name].object_id = attsArray[i].object_id;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/services/devices/deviceRegistryMongoDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ function storeDevice(newDevice, callback) {
}

// Ensure protocol is in newDevice
if ( !newDevice['protocol'] && config.getConfig().iotManager && config.getConfig().iotManager.protocol) {
deviceObj['protocol'] = config.getConfig().iotManager.protocol;
if ( !newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) {
deviceObj.protocol = config.getConfig().iotManager.protocol;
}

logger.debug(context, 'Storing device with id [%s] and type [%s]', newDevice.id, newDevice.type);
Expand Down
24 changes: 15 additions & 9 deletions lib/services/devices/deviceService.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ function formatAttributesNgsi2(originalVector, staticAtts) {

// (#628) check if attribute has entity_name:
// In that case attribute should not be appear in current entity
/*jshint camelcase: false */
if (!originalVector[i].entity_name) {
attributeList[originalVector[i].name] = {
type: originalVector[i].type,
Expand Down Expand Up @@ -293,9 +294,10 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) {
jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands));

logger.debug(context, 'deviceData: %j', deviceData);
if ( (('timestamp' in deviceData && deviceData['timestamp'] !== undefined) ? deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestampedNgsi2(options.json)) {
logger.debug(context, 'config.timestamp %s %s', deviceData['timestamp'], config.getConfig().timestamp);
if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ?
deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestampedNgsi2(options.json)) {
logger.debug(context, 'config.timestamp %s %s', deviceData.timestamp, config.getConfig().timestamp);
options.json[constants.TIMESTAMP_ATTRIBUTE] = {
type: constants.TIMESTAMP_TYPE_NGSI2,
value: moment()
Expand Down Expand Up @@ -344,6 +346,7 @@ function createInitialEntityNgsi1(deviceData, newDevice, callback) {
for (var i = 0; i < originalVector.length; i++) {
// (#628) check if attribute has entity_name:
// In that case attribute should not be appear in current entity
/*jshint camelcase: false */
if (!originalVector[i].entity_name) {
attributeList.push({
name: originalVector[i].name,
Expand Down Expand Up @@ -383,8 +386,9 @@ function createInitialEntityNgsi1(deviceData, newDevice, callback) {
deviceData.staticAttributes,
formatCommands(deviceData.commands));

if ( (('timestamp' in deviceData && deviceData['timestamp'] !== undefined) ? deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestamped(options.json)) {
if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ?
deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestamped(options.json)) {
options.json.contextElements[0].attributes.push({
name: constants.TIMESTAMP_ATTRIBUTE,
type: constants.TIMESTAMP_TYPE,
Expand Down Expand Up @@ -441,8 +445,9 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) {
jsonConcat(options.json, formatAttributesNgsi2(deviceData.staticAttributes, true));
jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands));

if ( (('timestamp' in deviceData && deviceData['timestamp'] !== undefined) ? deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestampedNgsi2(options.json)) {
if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ?
deviceData.timestamp : config.getConfig().timestamp) &&
! utils.isTimestampedNgsi2(options.json)) {
options.json[constants.TIMESTAMP_ATTRIBUTE] = {
type: constants.TIMESTAMP_TYPE_NGSI2,
value: moment()
Expand Down Expand Up @@ -533,7 +538,8 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio

if (deviceData[fields[i]] && configuration && configuration[confField]) {
deviceData[fields[i]] = mergeArrays(deviceData[fields[i]], configuration[confField]);
} else if (!deviceData[fields[i]] && configuration && confField in configuration && configuration[confField] !== undefined) {
} else if (!deviceData[fields[i]] && configuration &&
confField in configuration && configuration[confField] !== undefined) {
deviceData[fields[i]] = configuration[confField];
} else if (!deviceData[fields[i]] && (!configuration || !configuration[confField])) {
deviceData[fields[i]] = defaults[i];
Expand Down Expand Up @@ -1035,7 +1041,7 @@ function findOrCreate(deviceId, group, callback) {
newDevice.protocol = config.getConfig().iotManager.protocol;
}

if ('timestamp' in group && group['timestamp'] !== undefined) {
if ('timestamp' in group && group.timestamp !== undefined) {
newDevice.timestamp = group.timestamp;
}

Expand Down
3 changes: 2 additions & 1 deletion lib/services/devices/registrationUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ function sendRegistrationsNgsi2(unregister, deviceData, callback) {
).reduce(mergeWithSameName, []);

if (options.json.dataProvided.attrs.length === 0) {
logger.debug(context, 'Registration with Context Provider is not needed. Device without lazy atts or commands');
logger.debug(context, 'Registration with Context Provider is not needed.' +
'Device without lazy atts or commands');
callback(null, deviceData);
} else {
logger.debug(context, 'Sending device registrations to Context Broker at [%s]', options.url);
Expand Down
13 changes: 10 additions & 3 deletions lib/services/groups/groupService.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,20 +172,27 @@ function remove(service, subservice, resource, apikey, device, callback) {
callback(null, deviceGroup._id);
}

function unregisterDevice(device, cb) {
deviceService.unregister(device.id, service, subservice, function(error) {
if (error) {
cb(error);
}
});
}

function deleteDevices(device, service, subservice, id, callback) {
if(device) {
deviceService.listDevices(service, subservice, function (error, devices) {
if (error) {
callback(error);
} else {
if (devices && devices.count > 0){
for(var device of devices.devices) {
deviceService.unregister(device.id, service, subservice, function(error) {

async.map(devices.devices, unregisterDevice, function(error) {
if (error) {
callback(error);
}
});
}
}
}
});
Expand Down
Loading

0 comments on commit b61faa3

Please sign in to comment.