Skip to content

Commit d272d82

Browse files
committed
Add mixed mode
1 parent f7f5a52 commit d272d82

35 files changed

+768
-151
lines changed

doc/api.md

Lines changed: 39 additions & 37 deletions
Large diffs are not rendered by default.

doc/installationguide.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ These are the parameters that can be configured in the global section:
2929
ngsiVersion: 'v2'
3030
}
3131
```
32-
- If you want to use NGSI-LD (experimental):
32+
33+
- If you want to use **NGSI-LD** (experimental):
3334

3435
```javascript
3536
{
@@ -40,8 +41,20 @@ These are the parameters that can be configured in the global section:
4041
}
4142
```
4243

43-
Where `http://context.json-ld` is the location of the NGSI-LD `@context` element which provides additional information allowing the computer to
44-
interpret the rest of the data with more clarity and depth. Read the [JSON-LD specification](https://w3c.github.io/json-ld-syntax/#the-context) for more informtaion.
44+
- If you want to support a "mixed" mode with both **NGSI-v2** and **NGSI-LD** (experimental):
45+
46+
```javascript
47+
{
48+
host: '192.168.56.101',
49+
port: '1026',
50+
ngsiVersion: 'mixed',
51+
jsonLdContext: 'http://context.json-ld' // or ['http://context1.json-ld','http://context2.json-ld'] if you need more than one
52+
}
53+
```
54+
55+
Where `http://context.json-ld` is the location of the NGSI-LD `@context` element which provides additional information
56+
allowing the computer to interpret the rest of the data with more clarity and depth. Read the
57+
[JSON-LD specification](https://w3c.github.io/json-ld-syntax/#the-context) for more informtaion.
4558

4659
- **server**: configuration used to create the Context Server (port where the IoT Agent will be listening as a Context
4760
Provider and base root to prefix all the paths). The `port` attribute is required. If no `baseRoot` attribute is

lib/commonConfig.js

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ function processEnvironmentVariables() {
244244

245245
if (process.env.IOTA_CB_NGSI_VERSION) {
246246
config.contextBroker.ngsiVersion = process.env.IOTA_CB_NGSI_VERSION;
247-
}
247+
}
248248

249249
if (process.env.IOTA_JSON_LD_CONTEXT){
250250
config.contextBroker.jsonLdContext = process.env.IOTA_JSON_LD_CONTEXT.split(',').map(ctx => ctx.trim());
@@ -522,37 +522,41 @@ function getCommandRegistry() {
522522
}
523523

524524
/**
525-
* It checks if the configuration file states the use of NGSIv2
525+
* Returns the supported NGSI format
526526
*
527-
* @return {boolean} Result of the checking
527+
* @return {string} the supported NGSI format
528528
*/
529-
function checkNgsi2() {
530-
if (
531-
config.contextBroker &&
532-
config.contextBroker.ngsiVersion &&
533-
config.contextBroker.ngsiVersion === 'v2'
534-
) {
535-
return true;
529+
function ngsiVersion() {
530+
if (config && config.contextBroker && config.contextBroker.ngsiVersion) {
531+
return config.contextBroker.ngsiVersion.toLowerCase();
536532
}
537-
538-
return false;
533+
return 'unknown';
539534
}
540535

541536
/**
542-
* It checks if the configuration file states the use of NGSI-LD
537+
* It checks if the configuration file states a non-legacy format,
538+
* either v2, LD or mixed.
543539
*
544540
* @return {boolean} Result of the checking
545541
*/
546-
function checkNgsiLD() {
547-
if (
548-
config.contextBroker &&
549-
config.contextBroker.ngsiVersion &&
550-
config.contextBroker.ngsiVersion === 'ld') {
551-
return true;
542+
function isCurrentNgsi() {
543+
if (config.contextBroker && config.contextBroker.ngsiVersion) {
544+
const version = config.contextBroker.ngsiVersion.toLowerCase();
545+
return (version === 'v2' || version === 'ld' || version === 'mixed');
552546
}
553-
554547
return false;
555548
}
549+
/**
550+
* It checks if a combination of typeInformation or common Config is LD
551+
*
552+
* @return {boolean} Result of the checking
553+
*/
554+
function checkNgsiLD(typeInformation){
555+
const format = typeInformation.ngsiVersion || ngsiVersion();
556+
return (format.toLowerCase() === 'ld');
557+
}
558+
559+
556560
function setSecurityService(newSecurityService) {
557561
securityService = newSecurityService;
558562
}
@@ -570,8 +574,9 @@ exports.setGroupRegistry = setGroupRegistry;
570574
exports.getGroupRegistry = getGroupRegistry;
571575
exports.setCommandRegistry = setCommandRegistry;
572576
exports.getCommandRegistry = getCommandRegistry;
573-
exports.checkNgsi2 = checkNgsi2;
577+
exports.ngsiVersion = ngsiVersion;
574578
exports.checkNgsiLD = checkNgsiLD;
579+
exports.isCurrentNgsi = isCurrentNgsi;
575580
exports.setSecurityService = setSecurityService;
576581
exports.getSecurityService = getSecurityService;
577582
exports.getSecretData = getSecretData;

lib/fiware-iotagent-lib.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ var async = require('async'),
2929
intoTrans = require('./services/common/domain').intoTrans,
3030
middlewares = require('./services/common/genericMiddleware'),
3131
db = require('./model/dbConn'),
32-
ngsiService = require('./services/ngsi/ngsiService'),
3332
subscriptions = require('./services/ngsi/subscriptionService'),
3433
statsRegistry = require('./services/stats/statsRegistry'),
3534
domainUtils = require('./services/common/domain'),
@@ -183,7 +182,7 @@ function doActivate(newConfig, callback) {
183182
deviceService.init();
184183
subscriptions.init();
185184
contextServer.init();
186-
ngsiService.init();
185+
ngsi.init();
187186

188187
commands.start();
189188

lib/model/Device.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ var Device = new Schema({
5050
internalAttributes: Object,
5151
autoprovision: Boolean,
5252
expressionLanguage: String,
53-
explicitAttrs: Boolean
53+
explicitAttrs: Boolean,
54+
ngsiVersion: String
5455
});
5556

5657
function load(db) {

lib/model/Group.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ var Group = new Schema({
4444
internalAttributes: Array,
4545
autoprovision: Boolean,
4646
expressionLanguage: String,
47-
explicitAttrs: Boolean
47+
explicitAttrs: Boolean,
48+
ngsiVersion: String
4849
});
4950

5051
function load(db) {

lib/plugins/attributeAlias.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function extractAllMappings(typeInformation) {
7676
function applyAlias(mappings) {
7777
return function aliasApplier(attribute) {
7878
if (mappings.direct[attribute.name]) {
79-
if (config.checkNgsi2() || config.checkNgsiLD()) {
79+
if (config.isCurrentNgsi()) {
8080
/*jshint camelcase: false */
8181
attribute.object_id = attribute.name; // inverse not usefull due to collision
8282
}
@@ -96,7 +96,7 @@ function applyAlias(mappings) {
9696
*/
9797
function updateAttribute(entity, typeInformation, callback) {
9898
var mappings = extractAllMappings(typeInformation);
99-
if (config.checkNgsi2() || config.checkNgsiLD()) {
99+
if (config.isCurrentNgsi()) {
100100
var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity);
101101
attsArray = attsArray.map(applyAlias(mappings));
102102
entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true);

lib/plugins/bidirectionalData.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ function sendSubscriptions(device, attributeList, callback) {
134134

135135
logger.debug(context, 'Sending bidirectionality subscriptions for device [%s]', device.id);
136136

137-
if (config.checkNgsi2() || config.checkNgsiLD()) {
137+
if (config.isCurrentNgsi()) {
138138
async.map(attributeList, sendSingleSubscriptionNgsi2, callback);
139139
} else {
140140
async.map(attributeList, sendSingleSubscriptionNgsi1, callback);

lib/plugins/expressionParser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ function expressionApplier(context, typeInformation) {
177177
};
178178

179179
/*jshint camelcase: false */
180-
if ((config.checkNgsi2() || config.checkNgsiLD()) && attribute.object_id) {
180+
if ((config.isCurrentNgsi()) && attribute.object_id) {
181181
newAttribute.object_id = attribute.object_id;
182182
}
183183

lib/plugins/expressionPlugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ function update(entity, typeInformation, callback) {
114114
}
115115

116116
try {
117-
if (config.checkNgsi2() || config.checkNgsiLD()) {
117+
if (config.isCurrentNgsi()) {
118118
var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity);
119119
attsArray = processEntityUpdateNgsi2(attsArray);
120120
entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true);

lib/plugins/jexlParser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function expressionApplier(context, typeInformation) {
120120
};
121121

122122
/*jshint camelcase: false */
123-
if (config.checkNgsi2() && attribute.object_id) {
123+
if (config.isCurrentNgsi() && attribute.object_id) {
124124
newAttribute.object_id = attribute.object_id;
125125
}
126126

lib/plugins/multiEntity.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ function updateAttributeNgsi2(entity, typeInformation, callback) {
289289
}
290290

291291
function updateAttribute(entity, typeInformation, callback) {
292-
if (config.checkNgsi2() || config.checkNgsiLD()) {
292+
if (config.isCurrentNgsi()) {
293293
updateAttributeNgsi2(entity, typeInformation, callback);
294294
} else {
295295
updateAttributeNgsi1(entity, typeInformation, callback);

lib/plugins/pluginUtils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function createProcessAttribute(fn, attributeType) {
105105
attribute.value = fn(attribute.value);
106106
}
107107

108-
if (config.checkNgsi2() || config.checkNgsiLD()) {
108+
if (config.isCurrentNgsi()) {
109109
// This code is backwards compatible to process metadata in the older NGSIv1-style (array)
110110
// as well as supporting the newer NGSIv2-style (object). The redundant Array Check can be
111111
// therefore be removed if/when NGSIv1 support is removed from the library.
@@ -155,7 +155,7 @@ function createUpdateFilter(fn, attributeType) {
155155
return entity;
156156
}
157157

158-
if (config.checkNgsi2() || config.checkNgsiLD()) {
158+
if (config.isCurrentNgsi()) {
159159
entity = processEntityUpdateNgsi2(entity);
160160
} else {
161161
entity.contextElements = entity.contextElements.map(processEntityUpdateNgsi1);
@@ -189,7 +189,7 @@ function createQueryFilter(fn, attributeType) {
189189
return entity;
190190
}
191191

192-
if (config.checkNgsi2() || config.checkNgsiLD()) {
192+
if (config.isCurrentNgsi()) {
193193
entity = processEntityQueryNgsi2(entity);
194194
} else {
195195
entity.contextResponses = entity.contextResponses.map(processEntityQueryNgsi1);

lib/plugins/timestampProcessPlugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ function updatePluginNgsi1(entity, entityType, callback) {
132132
* @param {Object} entity NGSI Entity as it would have been sent before the plugin.
133133
*/
134134
function updatePlugin(entity, entityType, callback) {
135-
if (config.checkNgsi2() || config.checkNgsiLD()) {
135+
if (config.isCurrentNgsi()) {
136136
updatePluginNgsi2(entity, entityType, callback);
137137
} else {
138138
updatePluginNgsi1(entity, entityType, callback);

lib/services/common/iotManagerService.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ function register(callback) {
5959
timestamp: service.timestamp,
6060
autoprovision: service.autoprovision,
6161
explicitAttrs: service.explicitAttrs,
62-
expressionLanguage: service.expressionLanguage
62+
expressionLanguage: service.expressionLanguage,
63+
ngsiVersion: service.ngsiVersion
6364
};
6465
}
6566

lib/services/devices/deviceRegistryMongoDB.js

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,33 @@ let context = {
3434
op: 'IoTAgentNGSI.MongoDBDeviceRegister'
3535
};
3636

37+
const attributeList = [
38+
'id',
39+
'type',
40+
'name',
41+
'service',
42+
'subservice',
43+
'lazy',
44+
'commands',
45+
'staticAttributes',
46+
'active',
47+
'registrationId',
48+
'internalId',
49+
'internalAttributes',
50+
'resource',
51+
'apikey',
52+
'protocol',
53+
'endpoint',
54+
'transport',
55+
'polling',
56+
'timestamp',
57+
'autoprovision',
58+
'explicitAttrs',
59+
'expressionLanguage',
60+
'ngsiVersion'
61+
];
62+
63+
3764
/**
3865
* Generates a handler for the save device operations. The handler will take the customary error and the saved device
3966
* as the parameters (and pass the serialized DAO as the callback value).
@@ -59,13 +86,10 @@ function saveDeviceHandler(callback) {
5986
*/
6087
function storeDevice(newDevice, callback) {
6188
const deviceObj = new Device.model();
62-
const attributeList = ['id', 'type', 'name', 'service', 'subservice', 'lazy', 'commands', 'staticAttributes',
63-
'active', 'registrationId', 'internalId', 'internalAttributes', 'resource', 'apikey', 'protocol',
64-
'endpoint', 'transport', 'polling', 'timestamp', 'autoprovision', 'explicitAttrs', 'expressionLanguage'];
65-
66-
for (let i = 0; i < attributeList.length; i++) {
67-
deviceObj[attributeList[i]] = newDevice[attributeList[i]];
68-
}
89+
90+
attributeList.forEach((key) => {
91+
deviceObj[key] = newDevice[key];
92+
});
6993

7094
// Ensure protocol is in newDevice
7195
if ( !newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) {
@@ -269,6 +293,7 @@ function update(device, callback) {
269293
data.name = device.name;
270294
data.type = device.type;
271295
data.explicitAttrs = device.explicitAttrs;
296+
data.ngsiVersion = device.ngsiVersion;
272297

273298
data.save(saveDeviceHandler(callback));
274299
}

lib/services/devices/deviceService.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,18 @@ let deviceHandler;
4444
* Loads the correct device handler based on the current config.
4545
*/
4646
function init(){
47-
if (config.checkNgsiLD()) {
48-
deviceHandler = require('./devices-NGSI-LD');
49-
} else if (config.checkNgsi2()) {
50-
deviceHandler = require('./devices-NGSI-v2');
51-
} else {
52-
deviceHandler = require('./devices-NGSI-v1');
47+
switch (config.ngsiVersion()) {
48+
case 'ld':
49+
deviceHandler = require('./devices-NGSI-LD');
50+
break;
51+
case 'v2':
52+
deviceHandler = require('./devices-NGSI-v2');
53+
break;
54+
case 'mixed':
55+
deviceHandler = require('./devices-NGSI-mixed');
56+
break;
57+
default:
58+
deviceHandler = require('./devices-NGSI-v1');
5359
}
5460
}
5561

@@ -158,6 +164,10 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio
158164
if (configuration && configuration.cbHost) {
159165
deviceData.cbHost = configuration.cbHost;
160166
}
167+
if (configuration && configuration.ngsiVersion) {
168+
deviceData.ngsiVersion = configuration.ngsiVersion;
169+
}
170+
161171
logger.debug(context, 'deviceData after merge with conf: %j', deviceData);
162172
callback(null, deviceData);
163173
}
@@ -239,10 +249,15 @@ function registerDevice(deviceObj, callback) {
239249
}
240250
}
241251

252+
if (!deviceData.ngsiVersion) {
253+
if (configuration && configuration.ngsiVersion) {
254+
deviceData.ngsiVersion = configuration.ngsiVersion;
255+
}
256+
}
242257

243258
if (!deviceData.name) {
244259
deviceData.name = deviceData.type + ':' + deviceData.id;
245-
if (config.checkNgsiLD()) {
260+
if (config.checkNgsiLD(configuration)) {
246261
deviceData.name = 'urn:ngsi-ld:' + deviceData.type + ':' + deviceData.id;
247262
}
248263
logger.debug(context, 'Device name not found, falling back to deviceType:deviceId [%s]', deviceData.name);
@@ -525,7 +540,9 @@ function findOrCreate(deviceId, group, callback) {
525540
if ('autoprovision' in group && group.autoprovision !== undefined) {
526541
newDevice.autoprovision = group.autoprovision;
527542
}
528-
543+
if ('ngsiVersion' in group && group.ngsiVersion !== undefined) {
544+
newDevice.ngsiVersion = group.ngsiVersion;
545+
}
529546
registerDevice(newDevice, function(error, device) {
530547
callback(error, device, group);
531548
});

0 commit comments

Comments
 (0)