iotagent-node-lib 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES_NEXT_RELEASE +0 -2
- package/config.js +5 -5
- package/doc/api.md +1540 -298
- package/doc/deprecated.md +3 -1
- package/doc/development.md +120 -0
- package/doc/installationguide.md +3 -6
- package/lib/commonConfig.js +7 -10
- package/lib/fiware-iotagent-lib.js +0 -10
- package/lib/jexlTranformsMap.js +2 -1
- package/lib/plugins/bidirectionalData.js +8 -26
- package/lib/plugins/expressionPlugin.js +8 -40
- package/lib/plugins/jexlParser.js +28 -0
- package/lib/services/commands/commandService.js +1 -1
- package/lib/services/devices/deviceService.js +2 -1
- package/lib/services/ngsi/entities-NGSI-LD.js +13 -57
- package/lib/services/ngsi/entities-NGSI-v2.js +145 -108
- package/lib/services/northBound/deviceProvisioningServer.js +17 -14
- package/lib/templates/createDevice.json +5 -2
- package/lib/templates/createDeviceLax.json +7 -5
- package/lib/templates/updateDevice.json +5 -2
- package/lib/templates/updateDeviceLax.json +3 -5
- package/package.json +1 -1
- package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +5 -5
- package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +1 -0
- package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +4 -4
- package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -2
- package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +8 -8
- package/test/unit/ngsi-ld/plugins/custom-plugin_test.js +152 -0
- package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json +5 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin31.json +0 -8
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin35.json +20 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin40.json +42 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +32 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +37 -0
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +228 -6
- package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +1 -2
- package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +6 -6
- package/test/unit/ngsiv2/plugins/custom-plugin_test.js +151 -0
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +85 -12
- package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +11 -3
- package/doc/advanced-topics.md +0 -626
- package/doc/expressionLanguage.md +0 -762
- package/lib/plugins/expressionParser.js +0 -205
- package/test/unit/expressions/expression-test.js +0 -197
- package/test/unit/ngsi-ld/expressions/expressionBasedTransformations-test.js +0 -882
- package/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js +0 -951
- package/test/unit/ngsiv2/expressions/expressionCombinedTransformations-test.js +0 -296
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "iotagent-node-lib",
|
|
3
3
|
"license": "AGPL-3.0-only",
|
|
4
4
|
"description": "IoT Agent library to interface with NGSI Context Broker",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.2.0",
|
|
6
6
|
"homepage": "https://github.com/telefonicaid/iotagent-node-lib",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"fiware",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
{
|
|
13
13
|
"name":"location",
|
|
14
14
|
"type":"geo:point",
|
|
15
|
-
"expression": "
|
|
15
|
+
"expression": "latitude,longitude",
|
|
16
16
|
"reverse": [
|
|
17
17
|
{
|
|
18
18
|
"object_id":"latitude",
|
|
19
|
-
"type": "
|
|
20
|
-
"expression": "
|
|
19
|
+
"type": "Number",
|
|
20
|
+
"expression": "location | split(', ')[1] | parsefloat()"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"object_id":"longitude",
|
|
24
|
-
"type": "
|
|
25
|
-
"expression": "
|
|
24
|
+
"type": "Number",
|
|
25
|
+
"expression": "location | split(', ')[0] | parsefloat()"
|
|
26
26
|
}
|
|
27
27
|
]
|
|
28
28
|
}
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
"reverse": [
|
|
15
15
|
{
|
|
16
16
|
"object_id":"latitude",
|
|
17
|
-
"type": "
|
|
18
|
-
"expression": "
|
|
17
|
+
"type": "Number",
|
|
18
|
+
"expression": "location | split(', ')[1] | parsefloat()"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"object_id":"longitude",
|
|
22
|
-
"type": "
|
|
23
|
-
"expression": "
|
|
22
|
+
"type": "Number",
|
|
23
|
+
"expression": "location | split(', ')[0] | parsefloat()"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -40,7 +40,6 @@ const iotAgentConfig = {
|
|
|
40
40
|
ngsiVersion: 'ld',
|
|
41
41
|
jsonLdContext: 'http://context.json-ld'
|
|
42
42
|
},
|
|
43
|
-
defaultExpressionLanguage: 'jexl',
|
|
44
43
|
server: {
|
|
45
44
|
port: 4041
|
|
46
45
|
},
|
|
@@ -266,7 +265,6 @@ const iotAgentConfigTS = {
|
|
|
266
265
|
ngsiVersion: 'ld',
|
|
267
266
|
jsonLdContext: 'http://context.json-ld'
|
|
268
267
|
},
|
|
269
|
-
defaultExpressionLanguage: 'jexl',
|
|
270
268
|
server: {
|
|
271
269
|
port: 4041
|
|
272
270
|
},
|
|
@@ -240,11 +240,11 @@ describe('NGSI-LD - Bidirectional data plugin', function () {
|
|
|
240
240
|
let longitudeFound = false;
|
|
241
241
|
|
|
242
242
|
for (let i = 0; i < values.length; i++) {
|
|
243
|
-
if (values[i].name === 'latitude' && values[i].type === '
|
|
243
|
+
if (values[i].name === 'latitude' && values[i].type === 'Number' && values[i].value === -9.6) {
|
|
244
244
|
latitudeFound = true;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
if (values[i].name === 'longitude' && values[i].type === '
|
|
247
|
+
if (values[i].name === 'longitude' && values[i].type === 'Number' && values[i].value === 12.4) {
|
|
248
248
|
longitudeFound = true;
|
|
249
249
|
}
|
|
250
250
|
}
|
|
@@ -348,11 +348,11 @@ describe('NGSI-LD - Bidirectional data plugin', function () {
|
|
|
348
348
|
let longitudeFound = false;
|
|
349
349
|
|
|
350
350
|
for (let i = 0; i < values.length; i++) {
|
|
351
|
-
if (values[i].name === 'latitude' && values[i].type === '
|
|
351
|
+
if (values[i].name === 'latitude' && values[i].type === 'Number' && values[i].value === -9.6) {
|
|
352
352
|
latitudeFound = true;
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
if (values[i].name === 'longitude' && values[i].type === '
|
|
355
|
+
if (values[i].name === 'longitude' && values[i].type === 'Number' && values[i].value === 12.4) {
|
|
356
356
|
longitudeFound = true;
|
|
357
357
|
}
|
|
358
358
|
}
|
|
@@ -461,11 +461,11 @@ describe('NGSI-LD - Bidirectional data plugin', function () {
|
|
|
461
461
|
let longitudeFound = false;
|
|
462
462
|
|
|
463
463
|
for (let i = 0; i < values.length; i++) {
|
|
464
|
-
if (values[i].name === 'latitude' && values[i].type === '
|
|
464
|
+
if (values[i].name === 'latitude' && values[i].type === 'Number' && values[i].value === -9.6) {
|
|
465
465
|
latitudeFound = true;
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
if (values[i].name === 'longitude' && values[i].type === '
|
|
468
|
+
if (values[i].name === 'longitude' && values[i].type === 'Number' && values[i].value === 12.4) {
|
|
469
469
|
longitudeFound = true;
|
|
470
470
|
}
|
|
471
471
|
}
|
|
@@ -603,11 +603,11 @@ describe('NGSI-LD - Bidirectional data plugin', function () {
|
|
|
603
603
|
let longitudeFound = false;
|
|
604
604
|
|
|
605
605
|
for (let i = 0; i < values.length; i++) {
|
|
606
|
-
if (values[i].name === 'latitude' && values[i].type === '
|
|
606
|
+
if (values[i].name === 'latitude' && values[i].type === 'Number' && values[i].value === -9.6) {
|
|
607
607
|
latitudeFound = true;
|
|
608
608
|
}
|
|
609
609
|
|
|
610
|
-
if (values[i].name === 'longitude' && values[i].type === '
|
|
610
|
+
if (values[i].name === 'longitude' && values[i].type === 'Number' && values[i].value === 12.4) {
|
|
611
611
|
longitudeFound = true;
|
|
612
612
|
}
|
|
613
613
|
}
|
|
@@ -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::daniel.moranjimenez@telefonica.com
|
|
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
|
+
});
|
|
@@ -1,2 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
+
"TimeInstant": {
|
|
3
|
+
"type": "DateTime",
|
|
4
|
+
"value": "2015-08-05T07:35:01.468+00:00"
|
|
5
|
+
},
|
|
6
|
+
"location": {
|
|
7
|
+
"value": {
|
|
8
|
+
"coordinates": [
|
|
9
|
+
13,
|
|
10
|
+
52
|
|
11
|
+
],
|
|
12
|
+
"type": "Point"
|
|
13
|
+
},
|
|
14
|
+
"type": "geo:json",
|
|
15
|
+
"metadata": {
|
|
16
|
+
"TimeInstant": {
|
|
17
|
+
"type": "DateTime",
|
|
18
|
+
"value": "2015-08-05T07:35:01.468+00:00"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
2
22
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entities": [
|
|
3
|
+
{
|
|
4
|
+
"id": "water1",
|
|
5
|
+
"type": "WaterTank",
|
|
6
|
+
"contB": {
|
|
7
|
+
"value": "31450.000",
|
|
8
|
+
"type": "Number",
|
|
9
|
+
"metadata": {
|
|
10
|
+
"TimeInstant": {
|
|
11
|
+
"type": "DateTime",
|
|
12
|
+
"value": "2015-08-05T07:35:01.468Z"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"TimeInstant": {
|
|
17
|
+
"type": "DateTime",
|
|
18
|
+
"value": "2015-08-05T07:35:01.468Z"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "PA_B_0001",
|
|
23
|
+
"type": "WaterTank",
|
|
24
|
+
"waterLeavingTanks": {
|
|
25
|
+
"value": 3145,
|
|
26
|
+
"type": "Number",
|
|
27
|
+
"metadata": {
|
|
28
|
+
"TimeInstant": {
|
|
29
|
+
"type": "DateTime",
|
|
30
|
+
"value": "2015-08-05T07:35:01.468Z"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"TimeInstant": {
|
|
35
|
+
"type": "DateTime",
|
|
36
|
+
"value": "2015-08-05T07:35:01.468Z"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"actionType": "update"
|
|
41
|
+
}
|
|
42
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"TimeInstant": {
|
|
3
|
+
"type": "DateTime",
|
|
4
|
+
"value": "2015-08-05T07:35:01.468+00:00"
|
|
5
|
+
},
|
|
6
|
+
"location": {
|
|
7
|
+
"value": {
|
|
8
|
+
"coordinates": [
|
|
9
|
+
13,
|
|
10
|
+
52
|
|
11
|
+
],
|
|
12
|
+
"type": "Point"
|
|
13
|
+
},
|
|
14
|
+
"type": "geo:json",
|
|
15
|
+
"metadata": {
|
|
16
|
+
"TimeInstant": {
|
|
17
|
+
"type": "DateTime",
|
|
18
|
+
"value": "2015-08-05T07:35:01.468+00:00"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"temperature": {
|
|
23
|
+
"value": null,
|
|
24
|
+
"type": "Number",
|
|
25
|
+
"metadata": {
|
|
26
|
+
"TimeInstant": {
|
|
27
|
+
"type": "DateTime",
|
|
28
|
+
"value": "2015-08-05T07:35:01.468+00:00"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"actionType": "update",
|
|
3
|
+
"entities": [
|
|
4
|
+
{
|
|
5
|
+
"id": "gps1",
|
|
6
|
+
"type": "GPS",
|
|
7
|
+
"explicit": {
|
|
8
|
+
"type": "number",
|
|
9
|
+
"value": 12
|
|
10
|
+
},
|
|
11
|
+
"expectedAtt": {
|
|
12
|
+
"type": "number",
|
|
13
|
+
"value": 13
|
|
14
|
+
},
|
|
15
|
+
"nonexpectedAtt": {
|
|
16
|
+
"type": "number",
|
|
17
|
+
"value": null
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"explicit": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"value": 52
|
|
24
|
+
},
|
|
25
|
+
"type": "GPS",
|
|
26
|
+
"id": "SO5"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"explicit": {
|
|
30
|
+
"type": "number",
|
|
31
|
+
"value": 13
|
|
32
|
+
},
|
|
33
|
+
"type": "GPS",
|
|
34
|
+
"id": "SO6"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|