Skip to content

Commit

Permalink
Merge pull request #677 from telefonicaid/task/use_sendUpdate_multime…
Browse files Browse the repository at this point in the history
…asures

send to CB using multimeasures
  • Loading branch information
fgalan authored May 23, 2024
2 parents 932bc41 + 83ba444 commit a8a0791
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 122 deletions.
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- Fix: allow send multiple measures to CB in a batch (POST /v2/op/update) and sorted by TimeInstant when possible, instead of using multiples single request (iotagent-json#825, iotagent-node-lib#1612)
- Fix: default express limit to 1Mb instead default 100Kb and allow change it throught a conf env var 'IOTA_EXPRESS_LIMIT' (iota-json#827)
5 changes: 2 additions & 3 deletions docs/usermanual.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ t|15|k|abc
In this example, two attributes, one named "t" with value "15" and another named "k" with value "abc" are transmitted.
Values in Ultralight 2.0 are not typed (everything is treated as a string).

Multiple groups of measures can be combined into a single request, using the `#` character. In that case, a different
Multiple groups of measures can be combined into a single request (but just for HTTP/POST or MQTT), using the `#` character. In that case, a different
NGSI request will be generated for each group of measures. E.g.:

```text
gps|1.2/3.4#t|10
```

This will generate two NGSI requests for the same entity, one for each one of the values. Each one of those requests can
contain any number of attributes.
This will generate two elements in the NGSI batch update request (POST /v2/op/update) for the same entity, one for each one of the measures. Each one of those elements can contain any number of attributes.

Measure groups can additionally have an optional timestamp, with the following syntax:

Expand Down
6 changes: 3 additions & 3 deletions lib/bindings/HTTPBindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ function returnCommands(req, res, next) {
}

function handleIncomingMeasure(req, res, next) {
let updates = [];
let update = [];
context = fillService(context, { service: 'n/a', subservice: 'n/a' });
// prettier-ignore
config.getLogger().debug(context, 'Processing multiple HTTP measures for device %s with apiKey %j',
Expand All @@ -223,10 +223,10 @@ function handleIncomingMeasure(req, res, next) {
function processHTTPWithDevice(device) {
context = fillService(context, device);
if (req.ulPayload) {
updates = req.ulPayload.reduce(commonBindings.processMeasureGroup.bind(null, device, req.apiKey), []);
update = [req.ulPayload].reduce(commonBindings.processMeasureGroup.bind(null, device, req.apiKey), []);
}

async.series(updates, function (error) {
async.series(update, function (error) {
if (error) {
next(error);
// prettier-ignore
Expand Down
35 changes: 19 additions & 16 deletions lib/commonBindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,32 +128,35 @@ function manageConfigurationRequest(apiKey, deviceId, device, objMessage) {

/* eslint-disable-next-line no-unused-vars */
function processMeasureGroup(device, apikey, previous, current, index) {
const values = [];
if (current.command) {
if (current[0] && current[0].command) {
previous.push(
iotAgentLib.setCommandResult.bind(
null,
device.name,
config.getConfig().iota.defaultResource,
apikey,
current.command,
current.value,
current[0].command,
current[0].value,
constants.COMMAND_STATUS_COMPLETED,
device
)
);
} else {
for (const k in current) {
if (current.hasOwnProperty(k)) {
values.push({
name: k,
type: guessType(k, device),
value: current[k]
});
const val = [];
for (let curr of current) {
const values = [];
for (const k in curr) {
if (curr.hasOwnProperty(k)) {
values.push({
name: k,
type: guessType(k, device),
value: curr[k]
});
}
}
val.push(values);
}

previous.push(iotAgentLib.update.bind(null, device.name, device.type, '', values, device));
previous.push(iotAgentLib.update.bind(null, device.name, device.type, '', val, device));
}

return previous;
Expand All @@ -168,7 +171,7 @@ function processMeasureGroup(device, apikey, previous, current, index) {
* @param {String} messageStr UL payload parsed to string.
*/
function multipleMeasures(apiKey, device, messageStr) {
let updates = [];
let update = [];
let parsedMessage;
context = fillService(context, device);
config.getLogger().debug(context, 'Processing multiple measures for device %s with apiKey %s', device.id, apiKey);
Expand All @@ -181,9 +184,9 @@ function multipleMeasures(apiKey, device, messageStr) {
return;
}
config.getLogger().debug(context, 'stringMessage: %s parsedMessage: %s', messageStr, parsedMessage);
updates = parsedMessage.reduce(processMeasureGroup.bind(null, device, apiKey), []);
update = [parsedMessage].reduce(processMeasureGroup.bind(null, device, apiKey), []);

async.series(updates, function (error) {
async.series(update, function (error) {
if (error) {
config.getLogger().error(
context,
Expand Down
28 changes: 2 additions & 26 deletions test/unit/ngsiv2/amqpBinding-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,19 +218,7 @@ describe('AMQP Transport binding: measures', function () {
contextBrokerMock
.matchHeader('fiware-service', 'smartgondor')
.matchHeader('fiware-servicepath', '/gardens')
.post(
'/v2/entities?options=upsert',
utils.readExampleFile('./test/unit/ngsiv2/contextRequests/singleMeasure.json')
)
.reply(204);

contextBrokerMock
.matchHeader('fiware-service', 'smartgondor')
.matchHeader('fiware-servicepath', '/gardens')
.post(
'/v2/entities?options=upsert',
utils.readExampleFile('./test/unit/ngsiv2/contextRequests/secondSingleMeasure.json')
)
.post('/v2/op/update', utils.readExampleFile('./test/unit/ngsiv2/contextRequests/multimeasure.json'))
.reply(204);
});

Expand All @@ -248,19 +236,7 @@ describe('AMQP Transport binding: measures', function () {
contextBrokerMock
.matchHeader('fiware-service', 'smartgondor')
.matchHeader('fiware-servicepath', '/gardens')
.post(
'/v2/entities?options=upsert',
utils.readExampleFile('./test/unit/ngsiv2/contextRequests/multipleMeasure.json')
)
.reply(204);

contextBrokerMock
.matchHeader('fiware-service', 'smartgondor')
.matchHeader('fiware-servicepath', '/gardens')
.post(
'/v2/entities?options=upsert',
utils.readExampleFile('./test/unit/ngsiv2/contextRequests/secondMultipleMeasure.json')
)
.post('/v2/op/update', utils.readExampleFile('./test/unit/ngsiv2/contextRequests/multimeasure2.json'))
.reply(204);
});

Expand Down
21 changes: 21 additions & 0 deletions test/unit/ngsiv2/contextRequests/multimeasure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"actionType": "append",
"entities": [
{
"id": "Second UL Device",
"type": "AnMQTTDevice",
"temperature": {
"type": "celsius",
"value": 23
}
},
{
"id": "Second UL Device",
"type": "AnMQTTDevice",
"humidity": {
"type": "degrees",
"value": 98
}
}
]
}
29 changes: 29 additions & 0 deletions test/unit/ngsiv2/contextRequests/multimeasure2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"actionType": "append",
"entities": [
{
"id": "Second UL Device",
"type": "AnMQTTDevice",
"temperature": {
"type": "celsius",
"value": 23
},
"humidity": {
"type": "degrees",
"value": 98
}
},
{
"id": "Second UL Device",
"type": "AnMQTTDevice",
"temperature": {
"type": "celsius",
"value": 16
},
"humidity": {
"type": "degrees",
"value": 34
}
}
]
}
Loading

0 comments on commit a8a0791

Please sign in to comment.