iotagent-node-lib 2.24.0 → 2.26.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 +6 -7
- package/config.js +6 -1
- package/doc/advanced-topics.md +23 -1
- package/doc/apiary/iotagent.apib +5 -5
- package/doc/deprecated.md +13 -7
- package/doc/expressionLanguage.md +44 -34
- package/doc/getting-started.md +1 -1
- package/doc/howto.md +8 -0
- package/doc/installationguide.md +18 -0
- package/doc/usermanual.md +77 -0
- package/examples/TTOpen-service.json +1 -1
- package/lib/commonConfig.js +15 -1
- package/lib/constants.js +1 -0
- package/lib/fiware-iotagent-lib.js +3 -1
- package/lib/jexlTranformsMap.js +12 -1
- package/lib/plugins/jexlParser.js +2 -2
- package/lib/services/devices/deviceService.js +20 -1
- package/lib/services/devices/devices-NGSI-v2.js +3 -1
- package/lib/services/devices/registrationUtils.js +21 -1
- package/lib/services/northBound/contextServer-NGSI-LD.js +221 -38
- package/lib/services/northBound/contextServer.js +14 -1
- package/lib/services/northBound/northboundServer.js +1 -0
- package/lib/services/northBound/restUtils.js +3 -5
- package/lib/templates/deviceGroup.json +1 -1
- package/package.json +2 -2
- package/test/unit/examples/deviceProvisioningRequests/provisionNewDeviceEmpty.json +43 -0
- package/test/unit/examples/mongoCollections/configurations.json +3 -3
- package/test/unit/expressions/jexlExpression-test.js +29 -8
- package/test/unit/general/deviceService-test.js +31 -29
- package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +26 -25
- package/test/unit/mongodb/mongodb-group-registry-test.js +3 -3
- package/test/unit/mongodb/mongodb-registry-test.js +30 -21
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgent1.json +24 -14
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgent2.json +25 -15
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgent4.json +15 -5
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgentCommands.json +9 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgentCommandsAndLazy.json +32 -0
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerProvisionedDevice.json +12 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerProvisionedDevice2.json +9 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup.json +12 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup2.json +12 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup3.json +9 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/updateCommands1.json +10 -2
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/updateIoTAgent1.json +11 -1
- package/test/unit/ngsi-ld/examples/contextAvailabilityRequests/updateIoTAgent2.json +12 -1
- package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin30.json +11 -0
- package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +18 -4
- package/test/unit/ngsi-ld/general/deviceService-test.js +31 -29
- package/test/unit/ngsi-ld/general/startup-test.js +17 -2
- package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +1 -12
- package/test/unit/ngsi-ld/lazyAndCommands/merge-patch-test.js +249 -0
- package/test/unit/ngsi-ld/ngsiService/unsupported-endpoints-test.js +171 -0
- package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +0 -3
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityJexlExpressionPlugin1.json +22 -0
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +21 -6
- package/test/unit/ngsiv2/general/deviceService-test.js +25 -23
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +58 -0
- package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +25 -6
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@context": "http://context.json-ld",
|
|
3
3
|
"endpoint": "http://smartgondor.com",
|
|
4
|
+
"contextSourceInfo":[
|
|
5
|
+
{
|
|
6
|
+
"key": "jsonldContext",
|
|
7
|
+
"value": "http://context.json-ld"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
4
10
|
"information": [
|
|
5
11
|
{
|
|
6
12
|
"entities": [
|
|
@@ -9,10 +15,14 @@
|
|
|
9
15
|
"type": "Light"
|
|
10
16
|
}
|
|
11
17
|
],
|
|
12
|
-
"
|
|
18
|
+
"propertyNames": [
|
|
13
19
|
"pressure"
|
|
14
20
|
]
|
|
15
21
|
}
|
|
16
22
|
],
|
|
23
|
+
"mode": "exclusive",
|
|
24
|
+
"operations": [
|
|
25
|
+
"retrieveOps"
|
|
26
|
+
],
|
|
17
27
|
"type": "ContextSourceRegistration"
|
|
18
28
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@context": "http://context.json-ld",
|
|
3
3
|
"endpoint": "http://smartgondor.com",
|
|
4
|
+
"contextSourceInfo":[
|
|
5
|
+
{
|
|
6
|
+
"key": "jsonldContext",
|
|
7
|
+
"value": "http://context.json-ld"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
4
10
|
"information": [
|
|
5
11
|
{
|
|
6
12
|
"entities": [
|
|
@@ -9,11 +15,16 @@
|
|
|
9
15
|
"type": "TheLightType"
|
|
10
16
|
}
|
|
11
17
|
],
|
|
12
|
-
"
|
|
18
|
+
"propertyNames": [
|
|
13
19
|
"luminance",
|
|
14
20
|
"commandAttr"
|
|
15
21
|
]
|
|
16
22
|
}
|
|
17
23
|
],
|
|
24
|
+
"mode": "exclusive",
|
|
25
|
+
"operations" : [
|
|
26
|
+
"retrieveOps",
|
|
27
|
+
"updateOps"
|
|
28
|
+
],
|
|
18
29
|
"type": "ContextSourceRegistration"
|
|
19
30
|
}
|
|
@@ -321,11 +321,25 @@ describe('NGSI-LD: JEXL', function () {
|
|
|
321
321
|
}
|
|
322
322
|
];
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
beforeEach(function () {
|
|
325
|
+
nock.cleanAll();
|
|
326
|
+
|
|
327
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
328
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
329
|
+
.matchHeader('fiware-servicepath', 'gardens')
|
|
330
|
+
.post(
|
|
331
|
+
'/ngsi-ld/v1/entityOperations/upsert/?options=update',
|
|
332
|
+
utils.readExampleFile(
|
|
333
|
+
'./test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin30.json'
|
|
334
|
+
)
|
|
335
|
+
)
|
|
336
|
+
.reply(204);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('should ignore the expression before sending the values', function (done) {
|
|
325
340
|
iotAgentLib.update('light1', 'LightError', '', values, function (error) {
|
|
326
|
-
should.exist(error);
|
|
327
|
-
|
|
328
|
-
error.code.should.equal(400);
|
|
341
|
+
should.not.exist(error);
|
|
342
|
+
contextBrokerMock.done();
|
|
329
343
|
done();
|
|
330
344
|
});
|
|
331
345
|
});
|
|
@@ -137,7 +137,7 @@ const groupCreation = {
|
|
|
137
137
|
apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
|
|
138
138
|
entity_type: 'TheLightType',
|
|
139
139
|
trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
|
|
140
|
-
cbHost: 'http://
|
|
140
|
+
cbHost: 'http://192.168.1.1:1026',
|
|
141
141
|
commands: [],
|
|
142
142
|
lazy: [],
|
|
143
143
|
attributes: [
|
|
@@ -187,17 +187,17 @@ describe('NGSI-LD - Device Service: utils', function () {
|
|
|
187
187
|
// This mock does not check the payload since the aim of the test is not to verify
|
|
188
188
|
// device provisioning functionality. Appropriate verification is done in tests under
|
|
189
189
|
// provisioning folder
|
|
190
|
-
contextBrokerMock = nock('http://
|
|
190
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
191
191
|
.matchHeader('fiware-service', 'testservice')
|
|
192
192
|
.post('/ngsi-ld/v1/entityOperations/upsert/')
|
|
193
193
|
.reply(204);
|
|
194
194
|
|
|
195
|
-
async.series(
|
|
196
|
-
|
|
197
|
-
results
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
async.series(
|
|
196
|
+
[request.bind(request, groupCreation), request.bind(request, deviceCreation)],
|
|
197
|
+
function (error, results) {
|
|
198
|
+
done();
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
it('should return the existing device', function (done) {
|
|
@@ -216,7 +216,7 @@ describe('NGSI-LD - Device Service: utils', function () {
|
|
|
216
216
|
// This mock does not check the payload since the aim of the test is not to verify
|
|
217
217
|
// device provisioning functionality. Appropriate verification is done in tests under
|
|
218
218
|
// provisioning folder
|
|
219
|
-
contextBrokerMock = nock('http://
|
|
219
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
220
220
|
.matchHeader('fiware-service', 'testservice')
|
|
221
221
|
.post('/ngsi-ld/v1/entityOperations/upsert/')
|
|
222
222
|
.reply(204);
|
|
@@ -227,32 +227,34 @@ describe('NGSI-LD - Device Service: utils', function () {
|
|
|
227
227
|
});
|
|
228
228
|
|
|
229
229
|
it('should register the device and return it', function (done) {
|
|
230
|
-
iotAgentLib.retrieveDevice(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
230
|
+
iotAgentLib.retrieveDevice(
|
|
231
|
+
'UNEXISTENT_DEV',
|
|
232
|
+
'801230BJKL23Y9090DSFL123HJK09H324HV8732',
|
|
233
|
+
function (error, device) {
|
|
234
|
+
should.not.exist(error);
|
|
235
|
+
should.exist(device);
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
device.id.should.equal('UNEXISTENT_DEV');
|
|
238
|
+
should.exist(device.protocol);
|
|
239
|
+
device.protocol.should.equal('MQTT_UL');
|
|
240
|
+
done();
|
|
241
|
+
}
|
|
242
|
+
);
|
|
242
243
|
});
|
|
243
244
|
});
|
|
244
245
|
|
|
245
246
|
describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function () {
|
|
246
247
|
it('should raise an error', function (done) {
|
|
247
|
-
iotAgentLib.retrieveDevice(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
248
|
+
iotAgentLib.retrieveDevice(
|
|
249
|
+
'UNEXISTENT_DEV_AND_GROUP',
|
|
250
|
+
'H2332Y909DSF3H346yh20JK092',
|
|
251
|
+
function (error, device) {
|
|
252
|
+
should.exist(error);
|
|
253
|
+
error.name.should.equal('DEVICE_GROUP_NOT_FOUND');
|
|
254
|
+
should.not.exist(device);
|
|
255
|
+
done();
|
|
256
|
+
}
|
|
257
|
+
);
|
|
256
258
|
});
|
|
257
259
|
});
|
|
258
260
|
});
|
|
@@ -66,7 +66,7 @@ describe('NGSI-LD - Startup tests', function () {
|
|
|
66
66
|
beforeEach(function () {
|
|
67
67
|
process.env.IOTA_CB_HOST = 'cbhost';
|
|
68
68
|
process.env.IOTA_CB_PORT = '1111';
|
|
69
|
-
process.env.IOTA_CB_NGSI_VERSION = '
|
|
69
|
+
process.env.IOTA_CB_NGSI_VERSION = 'ld';
|
|
70
70
|
process.env.IOTA_NORTH_HOST = 'localhost';
|
|
71
71
|
process.env.IOTA_NORTH_PORT = '2222';
|
|
72
72
|
process.env.IOTA_PROVIDER_URL = 'provider:3333';
|
|
@@ -83,6 +83,11 @@ describe('NGSI-LD - Startup tests', function () {
|
|
|
83
83
|
process.env.IOTA_MONGO_DB = 'themongodb';
|
|
84
84
|
process.env.IOTA_MONGO_REPLICASET = 'customReplica';
|
|
85
85
|
process.env.IOTA_DEFAULT_RESOURCE = '/iot/custom';
|
|
86
|
+
process.env.IOTA_JSON_LD_CONTEXT = 'http://context.jsonld';
|
|
87
|
+
process.env.IOTA_FALLBACK_TENANT = 'openiot';
|
|
88
|
+
process.env.IOTA_FALLBACK_PATH = 'smartgondor';
|
|
89
|
+
process.env.IOTA_LD_SUPPORT_NULL = 'false';
|
|
90
|
+
process.env.IOTA_LD_SUPPORT_DATASET_ID = 'false';
|
|
86
91
|
|
|
87
92
|
nock.cleanAll();
|
|
88
93
|
|
|
@@ -114,6 +119,11 @@ describe('NGSI-LD - Startup tests', function () {
|
|
|
114
119
|
delete process.env.IOTA_MONGO_DB;
|
|
115
120
|
delete process.env.IOTA_MONGO_REPLICASET;
|
|
116
121
|
delete process.env.IOTA_DEFAULT_RESOURCE;
|
|
122
|
+
delete process.env.IOTA_JSON_LD_CONTEXT;
|
|
123
|
+
delete process.env.IOTA_FALLBACK_TENANT;
|
|
124
|
+
delete process.env.IOTA_FALLBACK_PATH;
|
|
125
|
+
delete process.env.IOTA_LD_SUPPORT_NULL;
|
|
126
|
+
delete process.env.IOTA_LD_SUPPORT_DATASET_ID;
|
|
117
127
|
});
|
|
118
128
|
|
|
119
129
|
afterEach(function (done) {
|
|
@@ -123,7 +133,12 @@ describe('NGSI-LD - Startup tests', function () {
|
|
|
123
133
|
it('should load the correct configuration parameters', function (done) {
|
|
124
134
|
iotAgentLib.activate(iotAgentConfig, function (error) {
|
|
125
135
|
config.getConfig().contextBroker.url.should.equal('http://cbhost:1111');
|
|
126
|
-
config.getConfig().contextBroker.ngsiVersion.should.equal('
|
|
136
|
+
config.getConfig().contextBroker.ngsiVersion.should.equal('ld');
|
|
137
|
+
config.getConfig().contextBroker.jsonLdContext.should.equal('http://context.jsonld');
|
|
138
|
+
config.getConfig().contextBroker.fallbackTenant.should.equal( 'openiot');
|
|
139
|
+
config.getConfig().contextBroker.fallbackPath.should.equal('smartgondor');
|
|
140
|
+
config.getConfig().server.ldSupport.null.should.equal(false);
|
|
141
|
+
config.getConfig().server.ldSupport.datasetId.should.equal(false);
|
|
127
142
|
config.getConfig().server.host.should.equal('localhost');
|
|
128
143
|
config.getConfig().server.port.should.equal('2222');
|
|
129
144
|
config.getConfig().providerUrl.should.equal('provider:3333');
|
|
@@ -184,7 +184,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
beforeEach(function (done) {
|
|
187
|
-
logger.setLevel('ERROR');
|
|
188
187
|
iotAgentLib.register(device3, function (error) {
|
|
189
188
|
done();
|
|
190
189
|
});
|
|
@@ -287,7 +286,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
287
286
|
};
|
|
288
287
|
|
|
289
288
|
beforeEach(function (done) {
|
|
290
|
-
logger.setLevel('ERROR');
|
|
291
289
|
iotAgentLib.register(device3, function (error) {
|
|
292
290
|
done();
|
|
293
291
|
});
|
|
@@ -368,7 +366,7 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
368
366
|
describe('When a sequential command with datasetId updates via PATCH /attrs/attr-name arrives to the IoT Agent', function () {
|
|
369
367
|
const options = {
|
|
370
368
|
url: 'http://localhost:' + iotAgentConfig.server.port + '/ngsi-ld/v1/entities/urn:ngsi-ld:Robot:r2d2/attrs',
|
|
371
|
-
method: '
|
|
369
|
+
method: 'PATCH',
|
|
372
370
|
json: {
|
|
373
371
|
position: [
|
|
374
372
|
{
|
|
@@ -390,7 +388,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
390
388
|
};
|
|
391
389
|
|
|
392
390
|
beforeEach(function (done) {
|
|
393
|
-
logger.setLevel('ERROR');
|
|
394
391
|
iotAgentLib.register(device3, function (error) {
|
|
395
392
|
done();
|
|
396
393
|
});
|
|
@@ -496,7 +493,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
496
493
|
};
|
|
497
494
|
|
|
498
495
|
beforeEach(function (done) {
|
|
499
|
-
logger.setLevel('ERROR');
|
|
500
496
|
iotAgentLib.register(device3, function (error) {
|
|
501
497
|
done();
|
|
502
498
|
});
|
|
@@ -594,7 +590,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
594
590
|
};
|
|
595
591
|
|
|
596
592
|
beforeEach(function (done) {
|
|
597
|
-
logger.setLevel('ERROR');
|
|
598
593
|
iotAgentLib.register(device3, function (error) {
|
|
599
594
|
done();
|
|
600
595
|
});
|
|
@@ -691,7 +686,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
691
686
|
};
|
|
692
687
|
|
|
693
688
|
beforeEach(function (done) {
|
|
694
|
-
logger.setLevel('ERROR');
|
|
695
689
|
iotAgentLib.register(device3, function (error) {
|
|
696
690
|
done();
|
|
697
691
|
});
|
|
@@ -794,7 +788,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
794
788
|
};
|
|
795
789
|
|
|
796
790
|
beforeEach(function (done) {
|
|
797
|
-
logger.setLevel('ERROR');
|
|
798
791
|
iotAgentLib.register(device3, function (error) {
|
|
799
792
|
done();
|
|
800
793
|
});
|
|
@@ -902,7 +895,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
902
895
|
};
|
|
903
896
|
|
|
904
897
|
beforeEach(function (done) {
|
|
905
|
-
logger.setLevel('ERROR');
|
|
906
898
|
iotAgentLib.register(device3, function (error) {
|
|
907
899
|
done();
|
|
908
900
|
});
|
|
@@ -1006,7 +998,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
1006
998
|
};
|
|
1007
999
|
|
|
1008
1000
|
beforeEach(function (done) {
|
|
1009
|
-
logger.setLevel('ERROR');
|
|
1010
1001
|
iotAgentLib.register(device3, function (error) {
|
|
1011
1002
|
done();
|
|
1012
1003
|
});
|
|
@@ -1104,7 +1095,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
1104
1095
|
};
|
|
1105
1096
|
|
|
1106
1097
|
beforeEach(function (done) {
|
|
1107
|
-
logger.setLevel('ERROR');
|
|
1108
1098
|
iotAgentLib.register(device3, function (error) {
|
|
1109
1099
|
done();
|
|
1110
1100
|
});
|
|
@@ -1246,7 +1236,6 @@ describe('NGSI-LD - Command functionalities', function () {
|
|
|
1246
1236
|
};
|
|
1247
1237
|
|
|
1248
1238
|
beforeEach(function (done) {
|
|
1249
|
-
logger.setLevel('ERROR');
|
|
1250
1239
|
iotAgentLib.register(device3, function (error) {
|
|
1251
1240
|
done();
|
|
1252
1241
|
});
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2020 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
|
+
* Modified by: Jason Fox - FIWARE Foundation
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/* eslint-disable no-unused-vars */
|
|
27
|
+
|
|
28
|
+
const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
|
|
29
|
+
const utils = require('../../../tools/utils');
|
|
30
|
+
const request = utils.request;
|
|
31
|
+
const should = require('should');
|
|
32
|
+
const logger = require('logops');
|
|
33
|
+
const nock = require('nock');
|
|
34
|
+
const mongoUtils = require('../../mongodb/mongoDBUtils');
|
|
35
|
+
|
|
36
|
+
const timekeeper = require('timekeeper');
|
|
37
|
+
let contextBrokerMock;
|
|
38
|
+
let statusAttributeMock;
|
|
39
|
+
const iotAgentConfig = {
|
|
40
|
+
contextBroker: {
|
|
41
|
+
host: '192.168.1.1',
|
|
42
|
+
port: '1026',
|
|
43
|
+
ngsiVersion: 'ld',
|
|
44
|
+
jsonLdContext: 'http://context.json-ld'
|
|
45
|
+
},
|
|
46
|
+
server: {
|
|
47
|
+
port: 4041,
|
|
48
|
+
ldSupport: {
|
|
49
|
+
null: true,
|
|
50
|
+
datasetId: false,
|
|
51
|
+
merge: true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
types: {
|
|
55
|
+
Robot: {
|
|
56
|
+
internalAttributes:[],
|
|
57
|
+
commands:[
|
|
58
|
+
{
|
|
59
|
+
name: 'position',
|
|
60
|
+
object_id: 'pos',
|
|
61
|
+
type: 'Object'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'orientation',
|
|
65
|
+
type: 'Object'
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
lazy: [
|
|
69
|
+
{
|
|
70
|
+
name: 'batteryLevel',
|
|
71
|
+
type: 'Object'
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
staticAttributes: [],
|
|
75
|
+
active: []
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
service: 'smartgondor',
|
|
79
|
+
providerUrl: 'http://smartgondor.com'
|
|
80
|
+
};
|
|
81
|
+
const device3 = {
|
|
82
|
+
id: 'r2d2',
|
|
83
|
+
type: 'Robot',
|
|
84
|
+
service: 'smartgondor'
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
describe('NGSI-LD - Merge-Patch functionalities', function () {
|
|
88
|
+
beforeEach(function (done) {
|
|
89
|
+
const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00
|
|
90
|
+
timekeeper.freeze(time);
|
|
91
|
+
nock.cleanAll();
|
|
92
|
+
|
|
93
|
+
contextBrokerMock = nock('http://192.168.1.1:1026')
|
|
94
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
95
|
+
.post(
|
|
96
|
+
'/ngsi-ld/v1/csourceRegistrations/',
|
|
97
|
+
utils.readExampleFile(
|
|
98
|
+
'./test/unit/ngsi-ld/examples/contextAvailabilityRequests/registerIoTAgentCommandsAndLazy.json'
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
.reply(201, null, { Location: '/ngsi-ld/v1/csourceRegistrations/6319a7f5254b05844116584d' });
|
|
102
|
+
|
|
103
|
+
contextBrokerMock
|
|
104
|
+
.matchHeader('fiware-service', 'smartgondor')
|
|
105
|
+
.post('/ngsi-ld/v1/entityOperations/upsert/')
|
|
106
|
+
.reply(204);
|
|
107
|
+
|
|
108
|
+
iotAgentLib.activate(iotAgentConfig, done);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
afterEach(function (done) {
|
|
112
|
+
timekeeper.reset();
|
|
113
|
+
delete device3.registrationId;
|
|
114
|
+
iotAgentLib.clearAll(function () {
|
|
115
|
+
iotAgentLib.deactivate(function () {
|
|
116
|
+
mongoUtils.cleanDbs(function () {
|
|
117
|
+
nock.cleanAll();
|
|
118
|
+
iotAgentLib.setDataUpdateHandler();
|
|
119
|
+
iotAgentLib.setCommandHandler();
|
|
120
|
+
done();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('When a merge-patch PATCH arrives to the IoT Agent as Context Provider', function () {
|
|
127
|
+
const options = {
|
|
128
|
+
url:
|
|
129
|
+
'http://localhost:' +
|
|
130
|
+
iotAgentConfig.server.port +
|
|
131
|
+
'/ngsi-ld/v1/entities/urn:ngsi-ld:Robot:r2d2',
|
|
132
|
+
method: 'PATCH',
|
|
133
|
+
json: {
|
|
134
|
+
"position": {
|
|
135
|
+
"type": "Property",
|
|
136
|
+
"value": {
|
|
137
|
+
"moveTo" : [12,34],
|
|
138
|
+
"observedAt": "urn:ngsi-ld:null",
|
|
139
|
+
"precision": {
|
|
140
|
+
"value": 0.95,
|
|
141
|
+
"unitCode": "C62"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"orientation" : "urn:ngsi-ld:null"
|
|
146
|
+
},
|
|
147
|
+
headers: {
|
|
148
|
+
'fiware-service': 'smartgondor',
|
|
149
|
+
'content-type': 'application/ld+json'
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
beforeEach(function (done) {
|
|
154
|
+
iotAgentLib.register(device3, function (error) {
|
|
155
|
+
done();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should call the client handler once', function (done) {
|
|
160
|
+
let handlerCalled = 0;
|
|
161
|
+
|
|
162
|
+
iotAgentLib.setMergePatchHandler(function (id, type, service, subservice, attributes, callback) {
|
|
163
|
+
id.should.equal('urn:ngsi-ld:' + device3.type + ':' + device3.id);
|
|
164
|
+
type.should.equal(device3.type);
|
|
165
|
+
attributes[0].name.should.equal('position');
|
|
166
|
+
attributes[1].name.should.equal('orientation');
|
|
167
|
+
should.equal(attributes[1].value, null);
|
|
168
|
+
handlerCalled++;
|
|
169
|
+
callback(null, {
|
|
170
|
+
id,
|
|
171
|
+
type,
|
|
172
|
+
attributes: [
|
|
173
|
+
{
|
|
174
|
+
name: 'position',
|
|
175
|
+
type: 'Array',
|
|
176
|
+
value: '[28, -104, 23]'
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
request(options, function (error, response, body) {
|
|
183
|
+
should.not.exist(error);
|
|
184
|
+
response.statusCode.should.equal(200);
|
|
185
|
+
handlerCalled.should.equal(1);
|
|
186
|
+
done();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
xdescribe('When a partial update PATCH with an NGSI-LD Null arrives to the IoT Agent as Context Provider', function () {
|
|
193
|
+
const options = {
|
|
194
|
+
url:
|
|
195
|
+
'http://localhost:' +
|
|
196
|
+
iotAgentConfig.server.port +
|
|
197
|
+
'/ngsi-ld/v1/entities/urn:ngsi-ld:Robot:r2d2/attrs/position',
|
|
198
|
+
method: 'PATCH',
|
|
199
|
+
json: {
|
|
200
|
+
"type": "Property",
|
|
201
|
+
"value": "urn:ngsi-ld:null"
|
|
202
|
+
},
|
|
203
|
+
headers: {
|
|
204
|
+
'fiware-service': 'smartgondor',
|
|
205
|
+
'content-type': 'application/ld+json'
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
beforeEach(function (done) {
|
|
210
|
+
logger.setLevel('FATAL');
|
|
211
|
+
iotAgentLib.register(device3, function (error) {
|
|
212
|
+
done();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should call the client handler once', function (done) {
|
|
217
|
+
let handlerCalled = 0;
|
|
218
|
+
|
|
219
|
+
iotAgentLib.setCommandHandler(function (id, type, service, subservice, attributes, callback) {
|
|
220
|
+
id.should.equal('urn:ngsi-ld:' + device3.type + ':' + device3.id);
|
|
221
|
+
type.should.equal(device3.type);
|
|
222
|
+
attributes[0].name.should.equal('position');
|
|
223
|
+
should.equal(attributes[0].value, null);
|
|
224
|
+
handlerCalled++;
|
|
225
|
+
callback(null, {
|
|
226
|
+
id,
|
|
227
|
+
type,
|
|
228
|
+
attributes: [
|
|
229
|
+
{
|
|
230
|
+
name: 'position',
|
|
231
|
+
type: 'Array',
|
|
232
|
+
value: null
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
request(options, function (error, response, body) {
|
|
239
|
+
console.error(error)
|
|
240
|
+
should.not.exist(error);
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
response.statusCode.should.equal(204);
|
|
244
|
+
handlerCalled.should.equal(1);
|
|
245
|
+
done();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|