Skip to content

Commit d2fd301

Browse files
committed
Add mixed mode
1 parent ad2e658 commit d2fd301

34 files changed

+731
-141
lines changed

doc/api.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ correspondence between the API resource fields and the same fields in the databa
9090
| `attributes` | `attributes` | list of common active attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. |
9191
| `static_attributes` | `staticAttributes` | this attributes will be added to all the entities of this group 'as is', additional `metadata` is optional. |
9292
| `internal_attributes` | `internalAttributes` | optional section with free format, to allow specific IoT Agents to store information along with the devices in the Device Registry. |
93-
| `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, legacy is used as default value. |
94-
| `explicitAttrs` | `explicitAttrs` | optional boolean value, to support selective ignore of measures so that IOTA doesn’t progress. If not specified default is false. |
93+
| `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, `legacy` is used as default value. |
94+
| `explicitAttrs` | `explicitAttrs` | optional boolean value, to support selective ignore of measures so that IOTA doesn’t progress. If not specified default is `false`. |
95+
| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. The default is `v2`.
9596

9697
### Service Group Endpoint
9798

@@ -224,7 +225,12 @@ the API resource fields and the same fields in the database model.
224225
| `internal_attributes` | `internalAttributes` | List of internal attributes with free format for specific IoT Agent configuration | LWM2M mappings from object URIs to attributes |
225226
| `static_attributes` | `staticAttributes` | List of static attributes to append to the entity. All the updateContext requests to the CB will have this set of attributes appended. | `[ { "name": "attr_name", "type": "Text" } ]` |
226227
| `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, legacy is used as default value. |
228+
<<<<<<< HEAD
227229
| `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is false. | `true/false` |
230+
=======
231+
| `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is `false`. | `true/false` |
232+
| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD**payloads. The default is `v2`. | `v2/ld` |
233+
>>>>>>> d272d82... Add mixed mode
228234
229235
#### Attribute lists
230236

doc/installationguide.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ These are the parameters that can be configured in the global section:
2020
}
2121
```
2222

23-
- If you want to use NGSI v2:
23+
- If you want to use **NGSI v2**:
2424

2525
```javascript
2626
{
@@ -30,7 +30,7 @@ These are the parameters that can be configured in the global section:
3030
}
3131
```
3232

33-
- If you want to use NGSI-LD (experimental):
33+
- If you want to use **NGSI-LD** (experimental):
3434

3535
```javascript
3636
{
@@ -41,6 +41,17 @@ These are the parameters that can be configured in the global section:
4141
}
4242
```
4343

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+
4455
Where `http://context.json-ld` is the location of the NGSI-LD `@context` element which provides additional information
4556
allowing the computer to interpret the rest of the data with more clarity and depth. Read the
4657
[JSON-LD specification](https://w3c.github.io/json-ld-syntax/#the-context) for more informtaion.

lib/commonConfig.js

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -504,30 +504,40 @@ function getCommandRegistry() {
504504
}
505505

506506
/**
507-
* It checks if the configuration file states the use of NGSIv2
507+
* Returns the supported NGSI format
508508
*
509-
* @return {boolean} Result of the checking
509+
* @return {string} the supported NGSI format
510510
*/
511-
function checkNgsi2() {
512-
if (config.contextBroker && config.contextBroker.ngsiVersion && config.contextBroker.ngsiVersion === 'v2') {
513-
return true;
511+
function ngsiVersion() {
512+
if (config && config.contextBroker && config.contextBroker.ngsiVersion) {
513+
return config.contextBroker.ngsiVersion.toLowerCase();
514514
}
515-
516-
return false;
515+
return 'unknown';
517516
}
518517

519518
/**
520-
* It checks if the configuration file states the use of NGSI-LD
519+
* It checks if the configuration file states a non-legacy format,
520+
* either v2, LD or mixed.
521521
*
522522
* @return {boolean} Result of the checking
523523
*/
524-
function checkNgsiLD() {
525-
if (config.contextBroker && config.contextBroker.ngsiVersion && config.contextBroker.ngsiVersion === 'ld') {
526-
return true;
524+
function isCurrentNgsi() {
525+
if (config.contextBroker && config.contextBroker.ngsiVersion) {
526+
const version = config.contextBroker.ngsiVersion.toLowerCase();
527+
return version === 'v2' || version === 'ld' || version === 'mixed';
527528
}
528-
529529
return false;
530530
}
531+
/**
532+
* It checks if a combination of typeInformation or common Config is LD
533+
*
534+
* @return {boolean} Result of the checking
535+
*/
536+
function checkNgsiLD(typeInformation) {
537+
const format = typeInformation.ngsiVersion || ngsiVersion();
538+
return format.toLowerCase() === 'ld';
539+
}
540+
531541
function setSecurityService(newSecurityService) {
532542
securityService = newSecurityService;
533543
}
@@ -544,8 +554,9 @@ exports.setGroupRegistry = setGroupRegistry;
544554
exports.getGroupRegistry = getGroupRegistry;
545555
exports.setCommandRegistry = setCommandRegistry;
546556
exports.getCommandRegistry = getCommandRegistry;
547-
exports.checkNgsi2 = checkNgsi2;
557+
exports.ngsiVersion = ngsiVersion;
548558
exports.checkNgsiLD = checkNgsiLD;
559+
exports.isCurrentNgsi = isCurrentNgsi;
549560
exports.setSecurityService = setSecurityService;
550561
exports.getSecurityService = getSecurityService;
551562
exports.getSecretData = getSecretData;

lib/fiware-iotagent-lib.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const ngsi = require('./services/ngsi/ngsiService');
2727
const intoTrans = require('./services/common/domain').intoTrans;
2828
const middlewares = require('./services/common/genericMiddleware');
2929
const db = require('./model/dbConn');
30-
const ngsiService = require('./services/ngsi/ngsiService');
3130
const subscriptions = require('./services/ngsi/subscriptionService');
3231
const statsRegistry = require('./services/stats/statsRegistry');
3332
const domainUtils = require('./services/common/domain');
@@ -179,7 +178,7 @@ function doActivate(newConfig, callback) {
179178
deviceService.init();
180179
subscriptions.init();
181180
contextServer.init();
182-
ngsiService.init();
181+
ngsi.init();
183182

184183
commands.start();
185184

lib/model/Device.js

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

5556
function load(db) {

lib/model/Group.js

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

4950
function load(db) {

lib/plugins/attributeAlias.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function extractAllMappings(typeInformation) {
7373
function applyAlias(mappings) {
7474
return function aliasApplier(attribute) {
7575
if (mappings.direct[attribute.name]) {
76-
if (config.checkNgsi2() || config.checkNgsiLD()) {
76+
if (config.isCurrentNgsi()) {
7777
/*jshint camelcase: false */
7878
attribute.object_id = attribute.name; // inverse not usefull due to collision
7979
}
@@ -93,7 +93,7 @@ function applyAlias(mappings) {
9393
*/
9494
function updateAttribute(entity, typeInformation, callback) {
9595
const mappings = extractAllMappings(typeInformation);
96-
if (config.checkNgsi2() || config.checkNgsiLD()) {
96+
if (config.isCurrentNgsi()) {
9797
let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity);
9898
attsArray = attsArray.map(applyAlias(mappings));
9999
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
@@ -130,7 +130,7 @@ function sendSubscriptions(device, attributeList, callback) {
130130

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

133-
if (config.checkNgsi2() || config.checkNgsiLD()) {
133+
if (config.isCurrentNgsi()) {
134134
async.map(attributeList, sendSingleSubscriptionNgsi2, callback);
135135
} else {
136136
async.map(attributeList, sendSingleSubscriptionNgsi1, callback);

lib/plugins/expressionParser.js

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

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

lib/plugins/expressionPlugin.js

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

114114
try {
115-
if (config.checkNgsi2() || config.checkNgsiLD()) {
115+
if (config.isCurrentNgsi()) {
116116
let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity);
117117
attsArray = processEntityUpdateNgsi2(attsArray);
118118
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
@@ -119,7 +119,7 @@ function expressionApplier(context, typeInformation) {
119119
};
120120

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

lib/plugins/multiEntity.js

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

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

lib/plugins/pluginUtils.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ function createProcessAttribute(fn, attributeType) {
102102
if (attribute.type && attribute.type === attributeType) {
103103
attribute.value = fn(attribute.value);
104104
}
105-
106-
if (config.checkNgsi2() || config.checkNgsiLD()) {
105+
if (config.isCurrentNgsi()) {
107106
// This code is backwards compatible to process metadata in the older NGSIv1-style (array)
108107
// as well as supporting the newer NGSIv2-style (object). The redundant Array Check can be
109108
// therefore be removed if/when NGSIv1 support is removed from the library.
@@ -149,7 +148,7 @@ function createUpdateFilter(fn, attributeType) {
149148
return entity;
150149
}
151150

152-
if (config.checkNgsi2() || config.checkNgsiLD()) {
151+
if (config.isCurrentNgsi()) {
153152
entity = processEntityUpdateNgsi2(entity);
154153
} else {
155154
entity.contextElements = entity.contextElements.map(processEntityUpdateNgsi1);
@@ -184,7 +183,7 @@ function createQueryFilter(fn, attributeType) {
184183
return entity;
185184
}
186185

187-
if (config.checkNgsi2() || config.checkNgsiLD()) {
186+
if (config.isCurrentNgsi()) {
188187
entity = processEntityQueryNgsi2(entity);
189188
} else {
190189
entity.contextResponses = entity.contextResponses.map(processEntityQueryNgsi1);

lib/plugins/timestampProcessPlugin.js

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

lib/services/common/iotManagerService.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ function register(callback) {
5656
timestamp: service.timestamp,
5757
autoprovision: service.autoprovision,
5858
explicitAttrs: service.explicitAttrs,
59-
expressionLanguage: service.expressionLanguage
59+
expressionLanguage: service.expressionLanguage,
60+
ngsiVersion: service.ngsiVersion
6061
};
6162
}
6263

lib/services/devices/deviceRegistryMongoDB.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,32 @@ 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+
3763
/**
3864
* Generates a handler for the save device operations. The handler will take the customary error and the saved device
3965
* as the parameters (and pass the serialized DAO as the callback value).
@@ -58,35 +84,11 @@ function saveDeviceHandler(callback) {
5884
* @param {Object} newDevice Device object to be stored
5985
*/
6086
function storeDevice(newDevice, callback) {
61-
const deviceObj = new Device.model(); // eslint-disable-line new-cap
62-
const attributeList = [
63-
'id',
64-
'type',
65-
'name',
66-
'service',
67-
'subservice',
68-
'lazy',
69-
'commands',
70-
'staticAttributes',
71-
'active',
72-
'registrationId',
73-
'internalId',
74-
'internalAttributes',
75-
'resource',
76-
'apikey',
77-
'protocol',
78-
'endpoint',
79-
'transport',
80-
'polling',
81-
'timestamp',
82-
'autoprovision',
83-
'explicitAttrs',
84-
'expressionLanguage'
85-
];
86-
87-
for (let i = 0; i < attributeList.length; i++) {
88-
deviceObj[attributeList[i]] = newDevice[attributeList[i]];
89-
}
87+
/* eslint-disable-next-line new-cap */
88+
const deviceObj = new Device.model();
89+
attributeList.forEach((key) => {
90+
deviceObj[key] = newDevice[key];
91+
});
9092

9193
// Ensure protocol is in newDevice
9294
if (!newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) {
@@ -286,6 +288,7 @@ function update(device, callback) {
286288
data.name = device.name;
287289
data.type = device.type;
288290
data.explicitAttrs = device.explicitAttrs;
291+
data.ngsiVersion = device.ngsiVersion;
289292

290293
data.save(saveDeviceHandler(callback));
291294
}

0 commit comments

Comments
 (0)