Skip to content

Commit aaef13e

Browse files
authored
Merge pull request #1348 from jason-fox/feature/plugins
Re-enable Custom Update Plugins
2 parents 6e17bc4 + db069ab commit aaef13e

File tree

5 files changed

+323
-9
lines changed

5 files changed

+323
-9
lines changed

CHANGES_NEXT_RELEASE

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
- Add: JEXL support to bidirectinal plugin
2-
- Remove: remove legacy expression support (removing IOTA_DEFAULT_EXPRESSION_LANGUAGE env var and associated defaultExpressionLanguage config.js setting) (#1340)
3-
- Fix: avoid usage of newlines in logs (#1342)
4-
- Fix: explicitAttributes true case: should progress just active attributes which receives measures and all active attributes with expressions
5-
- Fix: add missed active attributes (with expressions) for ctxt for evaluate explicitAttrs expression (#1351)
6-
- Fix: allow use static attributes from group in entityNameExp of group
7-
- Fix: disable device attribute entity_name validation using pattern
1+
- Add: JEXL support to bidirectinal plugin
2+
- Remove: remove legacy expression support (removing IOTA_DEFAULT_EXPRESSION_LANGUAGE env var and associated defaultExpressionLanguage config.js setting) (#1340)
3+
- Fix: avoid usage of newlines in logs (#1342)
4+
- Fix: explicitAttributes true case: should progress just active attributes which receives measures and all active attributes with expressions
5+
- Fix: add missed active attributes (with expressions) for ctxt for evaluate explicitAttrs expression (#1351)
6+
- Fix: allow use static attributes from group in entityNameExp of group
7+
- Fix: disable device attribute entity_name validation using pattern
8+
- Fix: reenable invocation of custom plugins on update (#1348)
89
- Fix: change level of log about not context available for apply expression from warn to info

lib/services/ngsi/entities-NGSI-LD.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,5 +1000,9 @@ function sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, c
10001000

10011001
exports.convertAttrNGSILD = convertAttrNGSILD;
10021002
exports.formatAsNGSILD = formatAsNGSILD;
1003-
exports.sendUpdateValue = sendUpdateValueNgsiLD;
1003+
exports.sendUpdateValue = function (entityName, attributes, typeInformation, token, callback) {
1004+
NGSIUtils.applyMiddlewares(NGSIUtils.updateMiddleware, attributes, typeInformation, () => {
1005+
return sendUpdateValueNgsiLD(entityName, attributes, typeInformation, token, callback);
1006+
});
1007+
};
10041008
exports.sendQueryValue = sendQueryValueNgsiLD;

lib/services/ngsi/entities-NGSI-v2.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
370370
callback(new errors.TypeNotFound(null, entityName));
371371
return;
372372
}
373+
373374
let idTypeSSSList = pluginUtils.getIdTypeServSubServiceFromDevice(typeInformation);
374375
logger.debug(context, 'sendUpdateValueNgsi2 idTypeSSS are %j ', idTypeSSSList);
375376
let measureAttrsForCtxt = [];
@@ -673,6 +674,7 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
673674
});
674675
}
675676
}
677+
676678
logger.debug(context, 'sendUpdateValueNgsi2 currentEntity sorted %j ', currentEntity);
677679
let timestampValue = undefined;
678680
// Loop for each final attribute to apply alias, multientity and expressions
@@ -979,6 +981,10 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca
979981
}
980982

981983
exports.sendQueryValue = sendQueryValueNgsi2;
982-
exports.sendUpdateValue = sendUpdateValueNgsi2;
984+
exports.sendUpdateValue = function (entityName, attributes, typeInformation, token, callback) {
985+
NGSIUtils.applyMiddlewares(NGSIUtils.updateMiddleware, attributes, typeInformation, () => {
986+
return sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, callback);
987+
});
988+
};
983989
exports.addTimestamp = addTimestampNgsi2;
984990
exports.formatGeoAttrs = formatGeoAttrs;
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U
3+
*
4+
* This file is part of fiware-iotagent-lib
5+
*
6+
* fiware-iotagent-lib is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Affero General Public License as
8+
* published by the Free Software Foundation, either version 3 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* fiware-iotagent-lib is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public
17+
* License along with fiware-iotagent-lib.
18+
* If not, see http://www.gnu.org/licenses/.
19+
*
20+
* For those usages not covered by the GNU Affero General Public License
21+
* please contact with::[email protected]
22+
*
23+
* Modified by: Daniel Calvo - ATOS Research & Innovation
24+
*/
25+
26+
const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
27+
const should = require('should');
28+
const logger = require('logops');
29+
const nock = require('nock');
30+
let contextBrokerMock;
31+
const iotAgentConfig = {
32+
contextBroker: {
33+
host: '192.168.1.1',
34+
port: '1026',
35+
ngsiVersion: 'ld',
36+
jsonLdContext: 'http://context.json-ld'
37+
},
38+
server: {
39+
port: 4041
40+
},
41+
types: {
42+
Light: {
43+
commands: [],
44+
type: 'Light',
45+
lazy: [
46+
{
47+
name: 'temperature',
48+
type: 'centigrades'
49+
}
50+
],
51+
active: [
52+
{
53+
name: 'pressure',
54+
type: 'Hgmm'
55+
}
56+
]
57+
}
58+
},
59+
service: 'smartgondor',
60+
subservice: 'gardens',
61+
providerUrl: 'http://smartgondor.com'
62+
};
63+
64+
describe('NGSI-LD - Custom plugin', function () {
65+
let updateInvoked = false;
66+
let queryInvoked = false;
67+
68+
function updatePlugin(entity, typeInformation, callback) {
69+
updateInvoked = true;
70+
return callback(null, entity, typeInformation);
71+
}
72+
function queryPlugin(entity, typeInformation, callback) {
73+
queryInvoked = true;
74+
return callback(null, entity, typeInformation);
75+
}
76+
beforeEach(function (done) {
77+
logger.setLevel('FATAL');
78+
79+
iotAgentLib.activate(iotAgentConfig, function () {
80+
iotAgentLib.clearAll(function () {
81+
iotAgentLib.addUpdateMiddleware(updatePlugin);
82+
iotAgentLib.addQueryMiddleware(queryPlugin);
83+
done();
84+
});
85+
});
86+
});
87+
88+
afterEach(function (done) {
89+
iotAgentLib.clearAll(function () {
90+
iotAgentLib.deactivate(done);
91+
updateInvoked = false;
92+
queryInvoked = false;
93+
});
94+
});
95+
describe('When an update occurs', function () {
96+
const values = [
97+
{
98+
name: 'state',
99+
type: 'Boolean',
100+
value: 'true'
101+
},
102+
{
103+
name: 'dimming',
104+
type: 'Number',
105+
value: 23
106+
}
107+
];
108+
109+
beforeEach(function () {
110+
nock.cleanAll();
111+
112+
contextBrokerMock = nock('http://192.168.1.1:1026')
113+
.matchHeader('fiware-service', 'smartgondor')
114+
.matchHeader('fiware-servicepath', 'gardens')
115+
.post('/ngsi-ld/v1/entityOperations/upsert/')
116+
.query({ options: 'update' })
117+
.reply(204);
118+
});
119+
120+
it('should invoke the plugin', function (done) {
121+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
122+
should.not.exist(error);
123+
contextBrokerMock.done();
124+
updateInvoked.should.equal(true);
125+
done();
126+
});
127+
});
128+
});
129+
describe('When an query occurs', function () {
130+
beforeEach(function () {
131+
nock.cleanAll();
132+
133+
contextBrokerMock = nock('http://192.168.1.1:1026')
134+
.matchHeader('fiware-service', 'smartgondor')
135+
.matchHeader('fiware-servicepath', 'gardens')
136+
.get('/ngsi-ld/v1/entities/urn:ngsi-ld:Light:light1')
137+
.query({ attrs: 'state,dimming' })
138+
.reply(200, { state: 'good', dimming: '23' });
139+
});
140+
141+
it('should invoke the plugin', function (done) {
142+
const attributes = ['state', 'dimming'];
143+
iotAgentLib.query('light1', 'Light', '', attributes, function (error) {
144+
should.not.exist(error);
145+
contextBrokerMock.done();
146+
should.not.exist(error);
147+
queryInvoked.should.equal(true);
148+
done();
149+
});
150+
});
151+
});
152+
});
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U
3+
*
4+
* This file is part of fiware-iotagent-lib
5+
*
6+
* fiware-iotagent-lib is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Affero General Public License as
8+
* published by the Free Software Foundation, either version 3 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* fiware-iotagent-lib is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public
17+
* License along with fiware-iotagent-lib.
18+
* If not, see http://www.gnu.org/licenses/.
19+
*
20+
* For those usages not covered by the GNU Affero General Public License
21+
* please contact with::[email protected]
22+
*
23+
* Modified by: Daniel Calvo - ATOS Research & Innovation
24+
*/
25+
26+
const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
27+
const should = require('should');
28+
const logger = require('logops');
29+
const nock = require('nock');
30+
let contextBrokerMock;
31+
const iotAgentConfig = {
32+
contextBroker: {
33+
host: '192.168.1.1',
34+
port: '1026',
35+
ngsiVersion: 'v2'
36+
},
37+
server: {
38+
port: 4041
39+
},
40+
types: {
41+
Light: {
42+
commands: [],
43+
type: 'Light',
44+
lazy: [
45+
{
46+
name: 'temperature',
47+
type: 'centigrades'
48+
}
49+
],
50+
active: [
51+
{
52+
name: 'pressure',
53+
type: 'Hgmm'
54+
}
55+
]
56+
}
57+
},
58+
service: 'smartgondor',
59+
subservice: 'gardens',
60+
providerUrl: 'http://smartgondor.com'
61+
};
62+
63+
describe('NGSI-v2 - Custom plugin', function () {
64+
let updateInvoked = false;
65+
let queryInvoked = false;
66+
67+
function updatePlugin(entity, typeInformation, callback) {
68+
updateInvoked = true;
69+
return callback(null, entity, typeInformation);
70+
}
71+
function queryPlugin(entity, typeInformation, callback) {
72+
queryInvoked = true;
73+
return callback(null, entity, typeInformation);
74+
}
75+
beforeEach(function (done) {
76+
logger.setLevel('FATAL');
77+
78+
iotAgentLib.activate(iotAgentConfig, function () {
79+
iotAgentLib.clearAll(function () {
80+
iotAgentLib.addUpdateMiddleware(updatePlugin);
81+
iotAgentLib.addQueryMiddleware(queryPlugin);
82+
done();
83+
});
84+
});
85+
});
86+
87+
afterEach(function (done) {
88+
iotAgentLib.clearAll(function () {
89+
iotAgentLib.deactivate(done);
90+
updateInvoked = false;
91+
queryInvoked = false;
92+
});
93+
});
94+
describe('When an update occurs', function () {
95+
const values = [
96+
{
97+
name: 'state',
98+
type: 'Boolean',
99+
value: 'true'
100+
},
101+
{
102+
name: 'dimming',
103+
type: 'Number',
104+
value: 23
105+
}
106+
];
107+
108+
beforeEach(function () {
109+
nock.cleanAll();
110+
111+
contextBrokerMock = nock('http://192.168.1.1:1026')
112+
.matchHeader('fiware-service', 'smartgondor')
113+
.matchHeader('fiware-servicepath', 'gardens')
114+
.patch('/v2/entities/light1/attrs')
115+
.query({ type: 'Light' })
116+
.reply(204);
117+
});
118+
119+
it('should invoke the plugin', function (done) {
120+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
121+
should.not.exist(error);
122+
contextBrokerMock.done();
123+
updateInvoked.should.equal(true);
124+
done();
125+
});
126+
});
127+
});
128+
describe('When an query occurs', function () {
129+
beforeEach(function () {
130+
nock.cleanAll();
131+
132+
contextBrokerMock = nock('http://192.168.1.1:1026')
133+
.matchHeader('fiware-service', 'smartgondor')
134+
.matchHeader('fiware-servicepath', 'gardens')
135+
.get('/v2/entities/light1/attrs')
136+
.query({ type: 'Light', attrs: 'state,dimming' })
137+
.reply(200, { state: 'good', dimming: '23' });
138+
});
139+
140+
it('should invoke the plugin', function (done) {
141+
const attributes = ['state', 'dimming'];
142+
iotAgentLib.query('light1', 'Light', '', attributes, function (error) {
143+
should.not.exist(error);
144+
contextBrokerMock.done();
145+
should.not.exist(error);
146+
queryInvoked.should.equal(true);
147+
done();
148+
});
149+
});
150+
});
151+
});

0 commit comments

Comments
 (0)