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.
Files changed (48) hide show
  1. package/CHANGES_NEXT_RELEASE +0 -2
  2. package/config.js +5 -5
  3. package/doc/api.md +1540 -298
  4. package/doc/deprecated.md +3 -1
  5. package/doc/development.md +120 -0
  6. package/doc/installationguide.md +3 -6
  7. package/lib/commonConfig.js +7 -10
  8. package/lib/fiware-iotagent-lib.js +0 -10
  9. package/lib/jexlTranformsMap.js +2 -1
  10. package/lib/plugins/bidirectionalData.js +8 -26
  11. package/lib/plugins/expressionPlugin.js +8 -40
  12. package/lib/plugins/jexlParser.js +28 -0
  13. package/lib/services/commands/commandService.js +1 -1
  14. package/lib/services/devices/deviceService.js +2 -1
  15. package/lib/services/ngsi/entities-NGSI-LD.js +13 -57
  16. package/lib/services/ngsi/entities-NGSI-v2.js +145 -108
  17. package/lib/services/northBound/deviceProvisioningServer.js +17 -14
  18. package/lib/templates/createDevice.json +5 -2
  19. package/lib/templates/createDeviceLax.json +7 -5
  20. package/lib/templates/updateDevice.json +5 -2
  21. package/lib/templates/updateDeviceLax.json +3 -5
  22. package/package.json +1 -1
  23. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +5 -5
  24. package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +1 -0
  25. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +4 -4
  26. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -2
  27. package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +8 -8
  28. package/test/unit/ngsi-ld/plugins/custom-plugin_test.js +152 -0
  29. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +1 -1
  30. package/test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice4.json +5 -1
  31. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin31.json +0 -8
  32. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin35.json +20 -0
  33. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin40.json +42 -0
  34. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +32 -0
  35. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +37 -0
  36. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +228 -6
  37. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +1 -2
  38. package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +6 -6
  39. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +151 -0
  40. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +85 -12
  41. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +11 -3
  42. package/doc/advanced-topics.md +0 -626
  43. package/doc/expressionLanguage.md +0 -762
  44. package/lib/plugins/expressionParser.js +0 -205
  45. package/test/unit/expressions/expression-test.js +0 -197
  46. package/test/unit/ngsi-ld/expressions/expressionBasedTransformations-test.js +0 -882
  47. package/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js +0 -951
  48. 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.1.0",
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": "${latitude}, ${longitude}",
15
+ "expression": "latitude,longitude",
16
16
  "reverse": [
17
17
  {
18
18
  "object_id":"latitude",
19
- "type": "string",
20
- "expression": "${trim(substr(@location, indexOf(@location, \",\") + 1, length(@location)))}"
19
+ "type": "Number",
20
+ "expression": "location | split(', ')[1] | parsefloat()"
21
21
  },
22
22
  {
23
23
  "object_id":"longitude",
24
- "type": "string",
25
- "expression": "${trim(substr(@location, 0, indexOf(@location, \",\")))}"
24
+ "type": "Number",
25
+ "expression": "location | split(', ')[0] | parsefloat()"
26
26
  }
27
27
  ]
28
28
  }
@@ -3,6 +3,7 @@
3
3
  {
4
4
  "device_id": "MicroLight1",
5
5
  "protocol": "GENERIC_PROTO",
6
+ "expressionLanguage": "jexl",
6
7
  "attributes": [
7
8
  {
8
9
  "name": "attr_name",
@@ -14,13 +14,13 @@
14
14
  "reverse": [
15
15
  {
16
16
  "object_id":"latitude",
17
- "type": "string",
18
- "expression": "${trim(substr(@location, indexOf(@location, \",\") + 1, length(@location)))}"
17
+ "type": "Number",
18
+ "expression": "location | split(', ')[1] | parsefloat()"
19
19
  },
20
20
  {
21
21
  "object_id":"longitude",
22
- "type": "string",
23
- "expression": "${trim(substr(@location, 0, indexOf(@location, \",\")))}"
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 === 'string' && values[i].value === '-9.6') {
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 === 'string' && values[i].value === '12.4') {
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 === 'string' && values[i].value === '-9.6') {
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 === 'string' && values[i].value === '12.4') {
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 === 'string' && values[i].value === '-9.6') {
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 === 'string' && values[i].value === '12.4') {
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 === 'string' && values[i].value === '-9.6') {
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 === 'string' && values[i].value === '12.4') {
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
+ });
@@ -96,7 +96,7 @@ const iotAgentConfig = {
96
96
  object_id: 'h',
97
97
  name: 'humidity',
98
98
  type: 'Percentage',
99
- entity_name: 'Station Number ${@sn * 10}'
99
+ entity_name: '"Station Number "+sn*10'
100
100
  }
101
101
  ]
102
102
  },
@@ -1,8 +1,12 @@
1
1
  {
2
- "id": "EntityNameByExp",
2
+ "id": "MicroLight1__SUFFIX",
3
3
  "type": "MicroLights",
4
4
  "attr_name": {
5
5
  "type": "string",
6
6
  "value": null
7
+ },
8
+ "suffix_st": {
9
+ "type": "Text",
10
+ "value": "SUFFIX"
7
11
  }
8
12
  }
@@ -1,12 +1,4 @@
1
1
  {
2
- "undef": {
3
- "type": "json",
4
- "value": null
5
- },
6
- "nil": {
7
- "type": "json",
8
- "value": null
9
- },
10
2
  "falsy": {
11
3
  "type": "Boolean",
12
4
  "value": false
@@ -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
+ }