iotagent-node-lib 2.18.0 → 2.19.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/.github/workflows/ci.yml +1 -2
- package/doc/advanced-topics.md +122 -53
- package/doc/api.md +52 -52
- package/doc/development.md +8 -9
- package/doc/expressionLanguage.md +514 -316
- package/doc/installationguide.md +66 -64
- package/doc/usermanual.md +48 -16
- package/docker/Mosquitto/Dockerfile +1 -0
- package/docker/Mosquitto/README.md +1 -0
- package/docker/Mosquitto/startMosquitto.sh +6 -4
- package/lib/command/commandLine.js +1 -1
- package/lib/fiware-iotagent-lib.js +3 -0
- package/lib/jexlTranformsMap.js +9 -1
- package/lib/model/Device.js +4 -1
- package/lib/model/Group.js +19 -1
- package/lib/plugins/expressionParser.js +6 -4
- package/lib/plugins/expressionPlugin.js +8 -1
- package/lib/plugins/jexlParser.js +3 -1
- package/lib/request-shim.js +111 -0
- package/lib/services/common/genericMiddleware.js +6 -2
- package/lib/services/common/iotManagerService.js +1 -1
- package/lib/services/common/securityServiceKeystone.js +1 -1
- package/lib/services/common/securityServiceOAuth2.js +3 -2
- package/lib/services/devices/deviceRegistryMongoDB.js +1 -0
- package/lib/services/devices/devices-NGSI-LD.js +1 -1
- package/lib/services/devices/devices-NGSI-v2.js +2 -6
- package/lib/services/devices/registrationUtils.js +0 -2
- package/lib/services/ngsi/entities-NGSI-LD.js +95 -11
- package/lib/services/ngsi/entities-NGSI-v2.js +93 -8
- package/lib/services/ngsi/ngsiService.js +3 -2
- package/lib/services/northBound/contextServer-NGSI-LD.js +3 -2
- package/lib/services/northBound/deviceProvisioningServer.js +29 -6
- package/lib/services/northBound/northboundServer.js +2 -0
- package/lib/services/northBound/restUtils.js +1 -1
- package/package.json +4 -4
- package/test/tools/utils.js +2 -0
- package/test/unit/expressions/jexlExpression-test.js +5 -5
- package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +1 -1
- package/test/unit/general/deviceService-test.js +2 -5
- package/test/unit/general/loglevel-api_test.js +6 -11
- package/test/unit/general/migration-test.js +1 -0
- package/test/unit/general/startup-test.js +1 -0
- package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +1 -0
- package/test/unit/mongodb/mongodb-group-registry-test.js +1 -1
- package/test/unit/mongodb/mongodb-registry-test.js +2 -1
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin12a.json +7 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin13.json +13 -13
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +18 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +18 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin31.json +15 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json +17 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin33.json +18 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin34.json +17 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin4a.json +36 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin7.json +16 -16
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin8a.json +18 -0
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin15.json +25 -0
- package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +1018 -0
- package/test/unit/ngsi-ld/general/contextBrokerOAuthSecurityAccess-test.js +2 -2
- package/test/unit/ngsi-ld/general/deviceService-test.js +1 -1
- package/test/unit/ngsi-ld/general/https-support-test.js +2 -1
- package/test/unit/ngsi-ld/general/iotam-autoregistration-test.js +2 -1
- package/test/unit/ngsi-ld/general/startup-test.js +1 -0
- package/test/unit/ngsi-ld/lazyAndCommands/active-devices-attribute-update-test.js +3 -1
- package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +2 -1
- package/test/unit/ngsi-ld/lazyAndCommands/lazy-devices-test.js +2 -6
- package/test/unit/ngsi-ld/lazyAndCommands/polling-commands-test.js +2 -1
- package/test/unit/ngsi-ld/ngsiService/active-devices-test.js +1 -0
- package/test/unit/ngsi-ld/ngsiService/autocast-test.js +1 -0
- package/test/unit/ngsi-ld/ngsiService/geoproperties-test.js +1 -0
- package/test/unit/ngsi-ld/ngsiService/subscriptions-test.js +4 -3
- package/test/unit/ngsi-ld/plugins/alias-plugin_test.js +1 -0
- package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +3 -2
- package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +61 -0
- package/test/unit/ngsi-ld/provisioning/device-provisioning-api_test.js +2 -1
- package/test/unit/ngsi-ld/provisioning/device-registration_test.js +3 -2
- package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +1 -0
- package/test/unit/ngsi-ld/provisioning/listProvisionedDevices-test.js +42 -54
- package/test/unit/ngsi-ld/provisioning/provisionDeviceMultientity-test.js +2 -1
- package/test/unit/ngsi-ld/provisioning/removeProvisionedDevice-test.js +4 -4
- package/test/unit/ngsi-ld/provisioning/singleConfigurationMode-test.js +3 -5
- package/test/unit/ngsi-ld/provisioning/updateProvisionedDevices-test.js +12 -18
- package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin17.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin32.json +16 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin33.json +22 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin34.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin15.json +25 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin16.json +25 -0
- package/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js +4 -4
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +500 -0
- package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +3 -2
- package/test/unit/ngsiv2/general/deviceService-test.js +9 -8
- package/test/unit/ngsiv2/general/https-support-test.js +2 -1
- package/test/unit/ngsiv2/general/iotam-autoregistration-test.js +2 -1
- package/test/unit/ngsiv2/general/startup-test.js +1 -0
- package/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +3 -1
- package/test/unit/ngsiv2/lazyAndCommands/command-test.js +2 -1
- package/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +14 -18
- package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +3 -1
- package/test/unit/ngsiv2/ngsiService/active-devices-test.js +1 -0
- package/test/unit/ngsiv2/ngsiService/queryDeviceInformationInCb-test.js +0 -1
- package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +4 -3
- package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +3 -2
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +210 -0
- package/test/unit/ngsiv2/plugins/translation-inPlugins_test.js +1 -1
- package/test/unit/ngsiv2/provisioning/device-group-api-test.js +3 -2
- package/test/unit/ngsiv2/provisioning/device-group-utils-test.js +2 -1
- package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +2 -1
- package/test/unit/ngsiv2/provisioning/device-registration_test.js +3 -2
- package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +4 -3
- package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +42 -53
- package/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +2 -1
- package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +4 -4
- package/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js +3 -4
- package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +13 -19
- package/test/unit/plugins/capture-configuration-inPlugins_test.js +3 -1
- package/test/unit/plugins/capture-provision-inPlugins_test.js +2 -1
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin20.json +0 -25
|
@@ -0,0 +1,1018 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2014 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, seehttp://www.gnu.org/licenses/.
|
|
19
|
+
*
|
|
20
|
+
* For those usages not covered by the GNU Affero General Public License
|
|
21
|
+
* please contact with::[contacto@tid.es]
|
|
22
|
+
*
|
|
23
|
+
* Developed by: Federico M. Facca - Martel Innovate
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/* jshint camelcase: false */
|
|
27
|
+
|
|
28
|
+
const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
|
|
29
|
+
const utils = require('../../../tools/utils');
|
|
30
|
+
const should = require('should');
|
|
31
|
+
const logger = require('logops');
|
|
32
|
+
const nock = require('nock');
|
|
33
|
+
const timekeeper = require('timekeeper');
|
|
34
|
+
let contextBrokerMock;
|
|
35
|
+
const iotAgentConfig = {
|
|
36
|
+
logLevel: 'FATAL',
|
|
37
|
+
contextBroker: {
|
|
38
|
+
host: '192.168.1.1',
|
|
39
|
+
port: '1026',
|
|
40
|
+
ngsiVersion: 'ld',
|
|
41
|
+
jsonLdContext: 'http://context.json-ld'
|
|
42
|
+
},
|
|
43
|
+
defaultExpressionLanguage: 'jexl',
|
|
44
|
+
server: {
|
|
45
|
+
port: 4041
|
|
46
|
+
},
|
|
47
|
+
types: {
|
|
48
|
+
Light: {
|
|
49
|
+
commands: [],
|
|
50
|
+
type: 'Light',
|
|
51
|
+
lazy: [],
|
|
52
|
+
active: [
|
|
53
|
+
{
|
|
54
|
+
object_id: 'p',
|
|
55
|
+
name: 'pressure',
|
|
56
|
+
type: 'Number'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
object_id: 'e',
|
|
60
|
+
name: 'consumption',
|
|
61
|
+
type: 'Number'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
object_id: 'a',
|
|
65
|
+
name: 'alive',
|
|
66
|
+
type: 'None'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
object_id: 'u',
|
|
70
|
+
name: 'updated',
|
|
71
|
+
type: 'Boolean'
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
object_id: 'm',
|
|
75
|
+
name: 'manufacturer',
|
|
76
|
+
type: 'Object'
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
object_id: 'r',
|
|
80
|
+
name: 'revisions',
|
|
81
|
+
type: 'Array'
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
object_id: 'x',
|
|
85
|
+
name: 'consumption_x',
|
|
86
|
+
type: 'Number',
|
|
87
|
+
expression: 'pressure * 20'
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
LightError: {
|
|
92
|
+
commands: [],
|
|
93
|
+
type: 'Light',
|
|
94
|
+
lazy: [],
|
|
95
|
+
active: [
|
|
96
|
+
{
|
|
97
|
+
object_id: 'p',
|
|
98
|
+
name: 'pressure',
|
|
99
|
+
type: 'Number',
|
|
100
|
+
expression: 'pressure * / 20'
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
WeatherStation: {
|
|
105
|
+
commands: [],
|
|
106
|
+
type: 'WeatherStation',
|
|
107
|
+
lazy: [],
|
|
108
|
+
active: [
|
|
109
|
+
{
|
|
110
|
+
object_id: 'p',
|
|
111
|
+
name: 'pressure',
|
|
112
|
+
type: 'Number',
|
|
113
|
+
expression: 'pressure * 20'
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
object_id: 'e',
|
|
117
|
+
name: 'consumption',
|
|
118
|
+
type: 'Number',
|
|
119
|
+
expression: 'consumption * 20'
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
object_id: 'h',
|
|
123
|
+
name: 'humidity',
|
|
124
|
+
type: 'Percentage'
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'weather',
|
|
128
|
+
type: 'Summary',
|
|
129
|
+
expression: '"Humidity " + (humidity / 2) + " and pressure " + (pressure * 20)'
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
object_id: 'a',
|
|
133
|
+
name: 'alive',
|
|
134
|
+
type: 'None',
|
|
135
|
+
expression: 'alive * 20'
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
object_id: 'u',
|
|
139
|
+
name: 'updated',
|
|
140
|
+
type: 'Boolean',
|
|
141
|
+
expression: 'updated * 20'
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
WeatherStationUndef: {
|
|
146
|
+
commands: [],
|
|
147
|
+
type: 'WeatherStation',
|
|
148
|
+
lazy: [],
|
|
149
|
+
active: [
|
|
150
|
+
{
|
|
151
|
+
object_id: 'u',
|
|
152
|
+
name: 'undef',
|
|
153
|
+
type: 'json',
|
|
154
|
+
expression: 'u["no"]'
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
object_id: 'n',
|
|
158
|
+
name: 'nil',
|
|
159
|
+
type: 'json',
|
|
160
|
+
expression: 'u["no"]?u["no"]:null'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
object_id: 'f',
|
|
164
|
+
name: 'falsy',
|
|
165
|
+
type: 'Boolean',
|
|
166
|
+
expression: 'u["no"]?u["no"]:false'
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
object_id: 'z',
|
|
170
|
+
name: 'zero',
|
|
171
|
+
type: 'Number',
|
|
172
|
+
expression: 'u["no"]?u["no"]:0'
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
WeatherStationMultiple: {
|
|
177
|
+
commands: [],
|
|
178
|
+
type: 'WeatherStation',
|
|
179
|
+
lazy: [],
|
|
180
|
+
active: [
|
|
181
|
+
{
|
|
182
|
+
object_id: 'p',
|
|
183
|
+
name: 'pressure',
|
|
184
|
+
type: 'Number',
|
|
185
|
+
expression: 'pressure|trim'
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
object_id: 'p25',
|
|
189
|
+
name: 'pressure25',
|
|
190
|
+
type: 'Number'
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
object_id: 'e',
|
|
194
|
+
name: 'consumption',
|
|
195
|
+
type: 'Number',
|
|
196
|
+
expression: 'consumption|trim'
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
object_id: 'h',
|
|
200
|
+
name: 'humidity12',
|
|
201
|
+
type: 'Percentage'
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'weather',
|
|
205
|
+
type: 'Summary',
|
|
206
|
+
expression: '"Humidity " + (humidity12 / 2) + " and pressure " + (pressure25 * 20)'
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
object_id: 'a',
|
|
210
|
+
name: 'alive',
|
|
211
|
+
type: 'None',
|
|
212
|
+
expression: 'alive|trim'
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
object_id: 'u',
|
|
216
|
+
name: 'updated',
|
|
217
|
+
type: 'Boolean',
|
|
218
|
+
expression: 'updated|trim'
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
GPS: {
|
|
223
|
+
commands: [],
|
|
224
|
+
type: 'GPS',
|
|
225
|
+
lazy: [],
|
|
226
|
+
active: [
|
|
227
|
+
{
|
|
228
|
+
name: 'location',
|
|
229
|
+
type: 'geo:json',
|
|
230
|
+
expression: "{coordinates: [lon,lat], type: 'Point'}"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: 'TimeInstant',
|
|
234
|
+
type: 'DateTime',
|
|
235
|
+
expression: 'ts|toisodate'
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
explicitAttrs: true
|
|
239
|
+
},
|
|
240
|
+
GPS2: {
|
|
241
|
+
commands: [],
|
|
242
|
+
type: 'GPS',
|
|
243
|
+
lazy: [],
|
|
244
|
+
active: [
|
|
245
|
+
{
|
|
246
|
+
name: 'location',
|
|
247
|
+
type: 'geo:json',
|
|
248
|
+
expression: "{coordinates: [lon,lat], type: 'Point'}"
|
|
249
|
+
}
|
|
250
|
+
],
|
|
251
|
+
explicitAttrs: true
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
service: 'smartgondor',
|
|
255
|
+
subservice: 'gardens',
|
|
256
|
+
providerUrl: 'http://smartgondor.com',
|
|
257
|
+
deviceRegistrationDuration: 'P1M',
|
|
258
|
+
throttling: 'PT5S'
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const iotAgentConfigTS = {
|
|
262
|
+
logLevel: 'FATAL',
|
|
263
|
+
contextBroker: {
|
|
264
|
+
host: '192.168.1.1',
|
|
265
|
+
port: '1026',
|
|
266
|
+
ngsiVersion: 'ld',
|
|
267
|
+
jsonLdContext: 'http://context.json-ld'
|
|
268
|
+
},
|
|
269
|
+
defaultExpressionLanguage: 'jexl',
|
|
270
|
+
server: {
|
|
271
|
+
port: 4041
|
|
272
|
+
},
|
|
273
|
+
types: {
|
|
274
|
+
GPS: {
|
|
275
|
+
commands: [],
|
|
276
|
+
type: 'GPS',
|
|
277
|
+
lazy: [],
|
|
278
|
+
active: [
|
|
279
|
+
{
|
|
280
|
+
name: 'location',
|
|
281
|
+
type: 'geo:json',
|
|
282
|
+
expression: "{coordinates: [lon,lat], type: 'Point'}"
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
explicitAttrs: true
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
timestamp: true,
|
|
289
|
+
service: 'smartgondor',
|
|
290
|
+
subservice: 'gardens',
|
|
291
|
+
providerUrl: 'http://smartgondor.com'
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
describe('NGSI-LD: JEXL', function () {
|
|
295
|
+
beforeEach(function (done) {
|
|
296
|
+
logger.setLevel('FATAL');
|
|
297
|
+
|
|
298
|
+
iotAgentLib.activate(iotAgentConfig, function () {
|
|
299
|
+
iotAgentLib.clearAll(function () {
|
|
300
|
+
iotAgentLib.addUpdateMiddleware(iotAgentLib.dataPlugins.attributeAlias.update);
|
|
301
|
+
iotAgentLib.addQueryMiddleware(iotAgentLib.dataPlugins.attributeAlias.query);
|
|
302
|
+
iotAgentLib.addUpdateMiddleware(iotAgentLib.dataPlugins.expressionTransformation.update);
|
|
303
|
+
done();
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
afterEach(function (done) {
|
|
309
|
+
iotAgentLib.clearAll(function () {
|
|
310
|
+
iotAgentLib.deactivate(done);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
describe('When an update comes for expressions with syntax errors', function () {
|
|
315
|
+
// Case: Update for an attribute with bad expression
|
|
316
|
+
const values = [
|
|
317
|
+
{
|
|
318
|
+
name: 'p',
|
|
319
|
+
type: 'centigrades',
|
|
320
|
+
value: '52'
|
|
321
|
+
}
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
it('should apply the expression before sending the values', function (done) {
|
|
325
|
+
iotAgentLib.update('light1', 'LightError', '', values, function (error) {
|
|
326
|
+
should.exist(error);
|
|
327
|
+
error.name.should.equal('INVALID_EXPRESSION');
|
|
328
|
+
error.code.should.equal(400);
|
|
329
|
+
done();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
describe('When there are expression attributes that are just calculated (not sent by the device)', function () {
|
|
335
|
+
// Case: Expression which results is sent as a new attribute
|
|
336
|
+
const values = [
|
|
337
|
+
{
|
|
338
|
+
name: 'p',
|
|
339
|
+
type: 'Number',
|
|
340
|
+
value: 52
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: 'h',
|
|
344
|
+
type: 'Percentage',
|
|
345
|
+
value: '12'
|
|
346
|
+
}
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
beforeEach(function () {
|
|
350
|
+
nock.cleanAll();
|
|
351
|
+
|
|
352
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
353
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
354
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
355
|
+
.post(
|
|
356
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
357
|
+
utils.readExampleFile(
|
|
358
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json'
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
.reply(204);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should calculate them and add them to the payload', function (done) {
|
|
365
|
+
iotAgentLib.update('ws1', 'WeatherStation', '', values, function (error) {
|
|
366
|
+
should.not.exist(error);
|
|
367
|
+
contextBrokerMock.done();
|
|
368
|
+
done();
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe('When an expression with multiple variables with numbers arrive', function () {
|
|
374
|
+
// Case: Update for integer and string attributes with expression
|
|
375
|
+
|
|
376
|
+
const values = [
|
|
377
|
+
{
|
|
378
|
+
name: 'p25',
|
|
379
|
+
type: 'Number',
|
|
380
|
+
value: 52
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: 'h',
|
|
384
|
+
type: 'percentage',
|
|
385
|
+
value: '12'
|
|
386
|
+
}
|
|
387
|
+
];
|
|
388
|
+
|
|
389
|
+
beforeEach(function () {
|
|
390
|
+
nock.cleanAll();
|
|
391
|
+
|
|
392
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
393
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
394
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
395
|
+
.post(
|
|
396
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
397
|
+
utils.readExampleFile(
|
|
398
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin4a.json'
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
.reply(204);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should calculate it and add it to the payload', function (done) {
|
|
405
|
+
iotAgentLib.update('ws1', 'WeatherStationMultiple', '', values, function (error) {
|
|
406
|
+
should.not.exist(error);
|
|
407
|
+
contextBrokerMock.done();
|
|
408
|
+
done();
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
describe('When an update comes for attributes without expressions and type integer', function () {
|
|
414
|
+
// Case: Update for an integer attribute without expression
|
|
415
|
+
const values = [
|
|
416
|
+
{
|
|
417
|
+
name: 'e',
|
|
418
|
+
type: 'Number',
|
|
419
|
+
value: 52
|
|
420
|
+
}
|
|
421
|
+
];
|
|
422
|
+
|
|
423
|
+
beforeEach(function () {
|
|
424
|
+
nock.cleanAll();
|
|
425
|
+
|
|
426
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
427
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
428
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
429
|
+
.post(
|
|
430
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
431
|
+
utils.readExampleFile(
|
|
432
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin11.json'
|
|
433
|
+
)
|
|
434
|
+
)
|
|
435
|
+
.reply(204);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should apply the expression before sending the values', function (done) {
|
|
439
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
440
|
+
should.not.exist(error);
|
|
441
|
+
contextBrokerMock.done();
|
|
442
|
+
done();
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe('When an update comes for attributes with numeric expressions and type integer', function () {
|
|
448
|
+
// Case: Update for an integer attribute with arithmetic expression
|
|
449
|
+
const values = [
|
|
450
|
+
{
|
|
451
|
+
name: 'p',
|
|
452
|
+
type: 'Number',
|
|
453
|
+
value: 52
|
|
454
|
+
}
|
|
455
|
+
];
|
|
456
|
+
|
|
457
|
+
beforeEach(function () {
|
|
458
|
+
nock.cleanAll();
|
|
459
|
+
|
|
460
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
461
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
462
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
463
|
+
.post(
|
|
464
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
465
|
+
utils.readExampleFile(
|
|
466
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json'
|
|
467
|
+
)
|
|
468
|
+
)
|
|
469
|
+
.reply(204);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should apply the expression before sending the values', function (done) {
|
|
473
|
+
iotAgentLib.update('ws1', 'WeatherStation', '', values, function (error) {
|
|
474
|
+
should.not.exist(error);
|
|
475
|
+
contextBrokerMock.done();
|
|
476
|
+
done();
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
describe('When an update comes for attributes without expressions and type float', function () {
|
|
482
|
+
// Case: Update for a Float attribute without expressions
|
|
483
|
+
|
|
484
|
+
const values = [
|
|
485
|
+
{
|
|
486
|
+
name: 'e',
|
|
487
|
+
type: 'Number',
|
|
488
|
+
value: 0.44
|
|
489
|
+
}
|
|
490
|
+
];
|
|
491
|
+
|
|
492
|
+
beforeEach(function () {
|
|
493
|
+
nock.cleanAll();
|
|
494
|
+
|
|
495
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
496
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
497
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
498
|
+
.post(
|
|
499
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
500
|
+
utils.readExampleFile(
|
|
501
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin3.json'
|
|
502
|
+
)
|
|
503
|
+
)
|
|
504
|
+
.reply(204);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('should apply the expression before sending the values', function (done) {
|
|
508
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
509
|
+
should.not.exist(error);
|
|
510
|
+
contextBrokerMock.done();
|
|
511
|
+
done();
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
describe('When an update comes for attributes with numeric expressions and type float', function () {
|
|
517
|
+
// Case: Update for a Float attribute with arithmetic expression
|
|
518
|
+
|
|
519
|
+
const values = [
|
|
520
|
+
{
|
|
521
|
+
name: 'e',
|
|
522
|
+
type: 'Number',
|
|
523
|
+
value: 0.44
|
|
524
|
+
}
|
|
525
|
+
];
|
|
526
|
+
|
|
527
|
+
beforeEach(function () {
|
|
528
|
+
nock.cleanAll();
|
|
529
|
+
|
|
530
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
531
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
532
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
533
|
+
.post(
|
|
534
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
535
|
+
utils.readExampleFile(
|
|
536
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin8a.json'
|
|
537
|
+
)
|
|
538
|
+
)
|
|
539
|
+
.reply(204);
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
it('should apply the expression before sending the values', function (done) {
|
|
543
|
+
iotAgentLib.update('ws1', 'WeatherStation', '', values, function (error) {
|
|
544
|
+
should.not.exist(error);
|
|
545
|
+
contextBrokerMock.done();
|
|
546
|
+
done();
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
describe('When an update comes for attributes without expressions and NULL type', function () {
|
|
552
|
+
// Case: Update for a Null attribute without expression
|
|
553
|
+
|
|
554
|
+
const values = [
|
|
555
|
+
{
|
|
556
|
+
name: 'a',
|
|
557
|
+
type: 'None',
|
|
558
|
+
value: null
|
|
559
|
+
}
|
|
560
|
+
];
|
|
561
|
+
|
|
562
|
+
beforeEach(function () {
|
|
563
|
+
nock.cleanAll();
|
|
564
|
+
|
|
565
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
566
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
567
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
568
|
+
.post(
|
|
569
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
570
|
+
utils.readExampleFile(
|
|
571
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin5.json'
|
|
572
|
+
)
|
|
573
|
+
)
|
|
574
|
+
.reply(204);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it('should apply the expression before sending the values', function (done) {
|
|
578
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
579
|
+
should.not.exist(error);
|
|
580
|
+
contextBrokerMock.done();
|
|
581
|
+
done();
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
describe('When an update comes for attributes without expressions and Boolean type', function () {
|
|
587
|
+
// Case: Update for a Boolean attribute without expression
|
|
588
|
+
|
|
589
|
+
const values = [
|
|
590
|
+
{
|
|
591
|
+
name: 'u',
|
|
592
|
+
type: 'Boolean',
|
|
593
|
+
value: true
|
|
594
|
+
}
|
|
595
|
+
];
|
|
596
|
+
|
|
597
|
+
beforeEach(function () {
|
|
598
|
+
nock.cleanAll();
|
|
599
|
+
|
|
600
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
601
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
602
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
603
|
+
.post(
|
|
604
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
605
|
+
utils.readExampleFile(
|
|
606
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin9.json'
|
|
607
|
+
)
|
|
608
|
+
)
|
|
609
|
+
.reply(204);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it('should apply the expression before sending the values', function (done) {
|
|
613
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
614
|
+
should.not.exist(error);
|
|
615
|
+
contextBrokerMock.done();
|
|
616
|
+
done();
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
describe('When an update comes for attributes without expressions and Object type', function () {
|
|
622
|
+
// Case: Update for a JSON document attribute without expression
|
|
623
|
+
const values = [
|
|
624
|
+
{
|
|
625
|
+
name: 'm',
|
|
626
|
+
type: 'Object',
|
|
627
|
+
value: { name: 'Manufacturer1', VAT: 'U12345678' }
|
|
628
|
+
}
|
|
629
|
+
];
|
|
630
|
+
|
|
631
|
+
beforeEach(function () {
|
|
632
|
+
nock.cleanAll();
|
|
633
|
+
|
|
634
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
635
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
636
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
637
|
+
.post(
|
|
638
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
639
|
+
utils.readExampleFile(
|
|
640
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin6.json'
|
|
641
|
+
)
|
|
642
|
+
)
|
|
643
|
+
.reply(204);
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it('should apply the expression before sending the values', function (done) {
|
|
647
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
648
|
+
should.not.exist(error);
|
|
649
|
+
contextBrokerMock.done();
|
|
650
|
+
done();
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
describe('When an update comes for attributes without expressions and Object type', function () {
|
|
656
|
+
// Case: Update for a JSON array attribute without expression
|
|
657
|
+
|
|
658
|
+
const values = [
|
|
659
|
+
{
|
|
660
|
+
name: 'r',
|
|
661
|
+
type: 'Object',
|
|
662
|
+
value: ['v0.1', 'v0.2', 'v0.3']
|
|
663
|
+
}
|
|
664
|
+
];
|
|
665
|
+
|
|
666
|
+
beforeEach(function () {
|
|
667
|
+
nock.cleanAll();
|
|
668
|
+
|
|
669
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
670
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
671
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
672
|
+
.post(
|
|
673
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
674
|
+
utils.readExampleFile(
|
|
675
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin7.json'
|
|
676
|
+
)
|
|
677
|
+
)
|
|
678
|
+
.reply(204);
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
it('should apply the expression before sending the values', function (done) {
|
|
682
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
683
|
+
should.not.exist(error);
|
|
684
|
+
contextBrokerMock.done();
|
|
685
|
+
done();
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
describe('When there are expressions including other attributes and they are not updated', function () {
|
|
691
|
+
const values = [
|
|
692
|
+
{
|
|
693
|
+
name: 'x',
|
|
694
|
+
type: 'Number',
|
|
695
|
+
value: 0.44
|
|
696
|
+
}
|
|
697
|
+
];
|
|
698
|
+
|
|
699
|
+
beforeEach(function () {
|
|
700
|
+
nock.cleanAll();
|
|
701
|
+
|
|
702
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
703
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
704
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
705
|
+
.post(
|
|
706
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
707
|
+
utils.readExampleFile(
|
|
708
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin12a.json'
|
|
709
|
+
)
|
|
710
|
+
)
|
|
711
|
+
.reply(204);
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it('should apply the expression before sending the values', function (done) {
|
|
715
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
716
|
+
should.not.exist(error);
|
|
717
|
+
contextBrokerMock.done();
|
|
718
|
+
done();
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
describe('When there are expressions including other attributes and they are updated', function () {
|
|
724
|
+
const values = [
|
|
725
|
+
{
|
|
726
|
+
name: 'p',
|
|
727
|
+
type: 'Number',
|
|
728
|
+
value: 10
|
|
729
|
+
}
|
|
730
|
+
];
|
|
731
|
+
|
|
732
|
+
beforeEach(function () {
|
|
733
|
+
nock.cleanAll();
|
|
734
|
+
|
|
735
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
736
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
737
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
738
|
+
.post(
|
|
739
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
740
|
+
utils.readExampleFile(
|
|
741
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin13.json'
|
|
742
|
+
)
|
|
743
|
+
)
|
|
744
|
+
.reply(204);
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it('should apply the expression before sending the values', function (done) {
|
|
748
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
749
|
+
should.not.exist(error);
|
|
750
|
+
contextBrokerMock.done();
|
|
751
|
+
done();
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
describe('When there are expressions including other attributes and they are updated (overriding situation)', function () {
|
|
757
|
+
const values = [
|
|
758
|
+
{
|
|
759
|
+
name: 'x',
|
|
760
|
+
type: 'Number',
|
|
761
|
+
value: 0.44
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
name: 'p',
|
|
765
|
+
type: 'Number',
|
|
766
|
+
value: 10
|
|
767
|
+
}
|
|
768
|
+
];
|
|
769
|
+
|
|
770
|
+
beforeEach(function () {
|
|
771
|
+
nock.cleanAll();
|
|
772
|
+
|
|
773
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
774
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
775
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
776
|
+
.post(
|
|
777
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
778
|
+
utils.readExampleFile(
|
|
779
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin13.json'
|
|
780
|
+
)
|
|
781
|
+
)
|
|
782
|
+
.reply(204);
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
it('should apply the expression before sending the values', function (done) {
|
|
786
|
+
iotAgentLib.update('light1', 'Light', '', values, function (error) {
|
|
787
|
+
should.not.exist(error);
|
|
788
|
+
contextBrokerMock.done();
|
|
789
|
+
done();
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
describe('When a measure arrives and there is not enough information to calculate an expression', function () {
|
|
795
|
+
const values = [
|
|
796
|
+
{
|
|
797
|
+
name: 'p',
|
|
798
|
+
type: 'centigrades',
|
|
799
|
+
value: '52'
|
|
800
|
+
}
|
|
801
|
+
];
|
|
802
|
+
|
|
803
|
+
beforeEach(function () {
|
|
804
|
+
nock.cleanAll();
|
|
805
|
+
|
|
806
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
807
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
808
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
809
|
+
.post(
|
|
810
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
811
|
+
utils.readExampleFile(
|
|
812
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json'
|
|
813
|
+
)
|
|
814
|
+
)
|
|
815
|
+
.reply(204);
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
it('should not calculate the expression', function (done) {
|
|
819
|
+
iotAgentLib.update('ws1', 'WeatherStation', '', values, function (error) {
|
|
820
|
+
should.not.exist(error);
|
|
821
|
+
contextBrokerMock.done();
|
|
822
|
+
done();
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
});
|
|
826
|
+
describe('When a measure arrives and there is not enough information to calculate an expression', function () {
|
|
827
|
+
const values = [
|
|
828
|
+
{
|
|
829
|
+
name: 'u',
|
|
830
|
+
type: 'json',
|
|
831
|
+
value: '{}'
|
|
832
|
+
}
|
|
833
|
+
];
|
|
834
|
+
|
|
835
|
+
beforeEach(function () {
|
|
836
|
+
nock.cleanAll();
|
|
837
|
+
|
|
838
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
839
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
840
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
841
|
+
.post(
|
|
842
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
843
|
+
utils.readExampleFile(
|
|
844
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin31.json'
|
|
845
|
+
)
|
|
846
|
+
)
|
|
847
|
+
.reply(204);
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
it('should not calculate the expression and allow falsy values', function (done) {
|
|
851
|
+
iotAgentLib.update('ws1', 'WeatherStationUndef', '', values, function (error) {
|
|
852
|
+
should.not.exist(error);
|
|
853
|
+
contextBrokerMock.done();
|
|
854
|
+
done();
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
describe('When there are additional attributes sent by the device to be calculated and removed', function () {
|
|
860
|
+
// Case: Expression which results is sent as a new attribute
|
|
861
|
+
const values = [
|
|
862
|
+
{
|
|
863
|
+
name: 'lat',
|
|
864
|
+
type: 'Number',
|
|
865
|
+
value: 52
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
name: 'lon',
|
|
869
|
+
type: 'Number',
|
|
870
|
+
value: 13
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
name: 'ts',
|
|
874
|
+
type: 'Number',
|
|
875
|
+
value: 1
|
|
876
|
+
}
|
|
877
|
+
];
|
|
878
|
+
|
|
879
|
+
beforeEach(function () {
|
|
880
|
+
nock.cleanAll();
|
|
881
|
+
|
|
882
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
883
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
884
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
885
|
+
.post(
|
|
886
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
887
|
+
utils.readExampleFile(
|
|
888
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json'
|
|
889
|
+
)
|
|
890
|
+
)
|
|
891
|
+
.reply(204);
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
it('should calculate them and remove non-explicitAttrs from the payload', function (done) {
|
|
895
|
+
iotAgentLib.update('gps1', 'GPS', '', values, function (error) {
|
|
896
|
+
should.not.exist(error);
|
|
897
|
+
contextBrokerMock.done();
|
|
898
|
+
done();
|
|
899
|
+
});
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
describe('When there is an extra TimeInstant sent by the device to be removed', function () {
|
|
903
|
+
// Case: Expression which results is sent as a new attribute
|
|
904
|
+
const values = [
|
|
905
|
+
{
|
|
906
|
+
name: 'lat',
|
|
907
|
+
type: 'Number',
|
|
908
|
+
value: 52
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: 'lon',
|
|
912
|
+
type: 'Number',
|
|
913
|
+
value: 13
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: 'TimeInstant',
|
|
917
|
+
type: 'DateTime',
|
|
918
|
+
value: '2015-08-05T07:35:01.468+00:00'
|
|
919
|
+
}
|
|
920
|
+
];
|
|
921
|
+
|
|
922
|
+
beforeEach(function () {
|
|
923
|
+
nock.cleanAll();
|
|
924
|
+
|
|
925
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
926
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
927
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
928
|
+
.post(
|
|
929
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
930
|
+
utils.readExampleFile(
|
|
931
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin34.json'
|
|
932
|
+
)
|
|
933
|
+
)
|
|
934
|
+
.reply(204);
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
it('should calculate them and remove non-explicitAttrs from the payload', function (done) {
|
|
938
|
+
iotAgentLib.update('gps1', 'GPS2', '', values, function (error) {
|
|
939
|
+
should.not.exist(error);
|
|
940
|
+
contextBrokerMock.done();
|
|
941
|
+
done();
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
describe('NGSI-LD: JEXL - Timestamps', function () {
|
|
948
|
+
beforeEach(function (done) {
|
|
949
|
+
logger.setLevel('FATAL');
|
|
950
|
+
|
|
951
|
+
iotAgentLib.activate(iotAgentConfigTS, function () {
|
|
952
|
+
iotAgentLib.clearAll(function () {
|
|
953
|
+
iotAgentLib.addUpdateMiddleware(iotAgentLib.dataPlugins.attributeAlias.update);
|
|
954
|
+
iotAgentLib.addQueryMiddleware(iotAgentLib.dataPlugins.attributeAlias.query);
|
|
955
|
+
iotAgentLib.addUpdateMiddleware(iotAgentLib.dataPlugins.expressionTransformation.update);
|
|
956
|
+
done();
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
afterEach(function (done) {
|
|
962
|
+
iotAgentLib.clearAll(function () {
|
|
963
|
+
iotAgentLib.deactivate(done);
|
|
964
|
+
});
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
describe('When timestamps are added but are not explicitly defined', function () {
|
|
968
|
+
// Case: Expression which results is sent as a new attribute
|
|
969
|
+
const values = [
|
|
970
|
+
{
|
|
971
|
+
name: 'lat',
|
|
972
|
+
type: 'Number',
|
|
973
|
+
value: 52
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
name: 'lon',
|
|
977
|
+
type: 'Number',
|
|
978
|
+
value: 13
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
name: 'ts',
|
|
982
|
+
type: 'Number',
|
|
983
|
+
value: 1
|
|
984
|
+
}
|
|
985
|
+
];
|
|
986
|
+
|
|
987
|
+
beforeEach(function () {
|
|
988
|
+
const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00
|
|
989
|
+
|
|
990
|
+
timekeeper.freeze(time);
|
|
991
|
+
nock.cleanAll();
|
|
992
|
+
|
|
993
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
994
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
995
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
996
|
+
.post(
|
|
997
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
998
|
+
utils.readExampleFile(
|
|
999
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin33.json'
|
|
1000
|
+
)
|
|
1001
|
+
)
|
|
1002
|
+
.reply(204);
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
afterEach(function (done) {
|
|
1006
|
+
timekeeper.reset();
|
|
1007
|
+
done();
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
it('should calculate them and not remove the timestamp from the payload', function (done) {
|
|
1011
|
+
iotAgentLib.update('gps1', 'GPS', '', values, function (error) {
|
|
1012
|
+
should.not.exist(error);
|
|
1013
|
+
contextBrokerMock.done();
|
|
1014
|
+
done();
|
|
1015
|
+
});
|
|
1016
|
+
});
|
|
1017
|
+
});
|
|
1018
|
+
});
|