From 6a8fa69eafb6044b7567db23181e4c5e49b21913 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Mon, 12 Apr 2021 19:46:36 +0200 Subject: [PATCH 1/9] Revert hotfix --- doc/advanced-topics.md | 28 +- lib/services/ngsi/entities-NGSI-v2.js | 58 +- .../createBidirectionalDevice.json | 12 +- .../createGeopointProvisionedDevice.json | 12 +- .../updateContextStaticAttributes.json | 9 +- .../ngsiv2/ngsiService/geoproperties-test.js | 715 +++++++++--------- 6 files changed, 423 insertions(+), 411 deletions(-) diff --git a/doc/advanced-topics.md b/doc/advanced-topics.md index b905ff19c..569fe886d 100644 --- a/doc/advanced-topics.md +++ b/doc/advanced-topics.md @@ -46,7 +46,7 @@ curl http://${KEYSTONE_HOST}/v3/OS-TRUST/trusts \ Apart from the generation of the trust, the use of secured Context Brokers should be transparent to the user of the IoT Agent. -### GeoJSON support (this only applies for NGSI-LD, not for NGSIv1 and NGSIv2) +### GeoJSON support The defined `type` of any GeoJSON attribute can be any set to any of the standard NGSI-v2 GeoJSON types - (e.g. `geo:json`, `geo:point`). NGSI-LD formats such as `GeoProperty`, `Point` and `LineString` are also accepted `type` @@ -69,17 +69,19 @@ values. If the latitude and longitude are received as separate measures, the } ``` -For `attributes` and `static_attributes` which need to be formatted as GeoJSON values, three separate input formats are -accepted. Provided the `type` is provisioned correctly, the `value` may be defined using any of the following formats: -- a comma delimited string +For `attributes` and `static_attributes` which need to be formatted as GeoJSON values, three separate input +formats are accepted. Provided the `type` is provisioned correctly, the `value` may be defined using any of +the following formats: + +- a comma delimited string ```json { - "name": "location", - "value": "23, 12.5" + "name": "location", + "value": "23, 12.5" } -``` +```` - an array of numbers @@ -183,12 +185,11 @@ Other unrecognised `type` attributes will be passed as NGSI-LD data using the fo } ``` + ### NGSI-LD Linked Data support -`static_attributes` may be supplied with an additional `link` data element when provisioning an IoT Agent to ensure that -active attributes from the provisioned IoT Device may be maintained in parallel with a linked data entity . Take for -example a temperature gauge placed within a building. The **Device** data model literally represents the IoT device -itself, but the `temperature` attribute also needs to be shared with the **Building** entity +`static_attributes` may be supplied with an additional `link` data element when provisioning an IoT Agent to ensure that active attributes from the provisioned IoT Device may be maintained in parallel with a linked data entity . Take for example a temperature gauge placed within a building. +The **Device** data model literally represents the IoT device itself, but the `temperature` attribute also needs to be shared with the **Building** entity A `link` between them can be provisioned as shown: @@ -222,8 +223,7 @@ e.g.: } ``` -Whenever a `temperature` measure is received **Device** is updated, and entity `urn:ngsi-ld:Building:001` is also -updated as shown: +Whenever a `temperature` measure is received **Device** is updated, and entity `urn:ngsi-ld:Building:001` is also updated as shown: ```json "temperature": { @@ -292,7 +292,7 @@ The library provides some plugins out of the box, in the `dataPlugins` collectio use the `addQueryMiddleware` and `addUpdateMiddleware` functions with the selected plugin, as in the example: ```javascript -var iotaLib = require('iotagent-node-lib'); +var iotaLib = require("iotagent-node-lib"); iotaLib.addUpdateMiddleware(iotaLib.dataPlugins.compressTimestamp.update); iotaLib.addQueryMiddleware(iotaLib.dataPlugins.compressTimestamp.query); diff --git a/lib/services/ngsi/entities-NGSI-v2.js b/lib/services/ngsi/entities-NGSI-v2.js index 4e45ea0ea..7e200acda 100644 --- a/lib/services/ngsi/entities-NGSI-v2.js +++ b/lib/services/ngsi/entities-NGSI-v2.js @@ -55,39 +55,37 @@ function formatGeoAttrs(attr) { switch (attr.type.toLowerCase()) { // GeoProperties case 'geo:json': - // FIXME: #1012 - // case 'geoproperty': - // case 'point': - // case 'geo:point': + case 'geoproperty': + case 'point': + case 'geo:point': obj.type = 'geo:json'; obj.value = NGSIUtils.getLngLats('Point', attr.value); break; - // FIXME: #1012 - // case 'linestring': - // case 'geo:linestring': - // obj.type = 'geo:json'; - // obj.value = NGSIUtils.getLngLats('LineString', attr.value); - // break; - // case 'polygon': - // case 'geo:polygon': - // obj.type = 'geo:json'; - // obj.value = NGSIUtils.getLngLats('Polygon', attr.value); - // break; - // case 'multipoint': - // case 'geo:multipoint': - // obj.type = 'geo:json'; - // obj.value = NGSIUtils.getLngLats('MultiPoint', attr.value); - // break; - // case 'multilinestring': - // case 'geo:multilinestring': - // obj.type = 'geo:json'; - // obj.value = NGSIUtils.getLngLats('MultiLineString', attr.value); - // break; - // case 'multipolygon': - // case 'geo:multipolygon': - // obj.type = 'geo:json'; - // obj.value = NGSIUtils.getLngLats('MultiPolygon', attr.value); - // break; + case 'linestring': + case 'geo:linestring': + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('LineString', attr.value); + break; + case 'polygon': + case 'geo:polygon': + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('Polygon', attr.value); + break; + case 'multipoint': + case 'geo:multipoint': + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('MultiPoint', attr.value); + break; + case 'multilinestring': + case 'geo:multilinestring': + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('MultiLineString', attr.value); + break; + case 'multipolygon': + case 'geo:multipolygon': + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('MultiPolygon', attr.value); + break; } } return obj; diff --git a/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json b/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json index d29d80454..46e2330e3 100644 --- a/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +++ b/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json @@ -2,7 +2,13 @@ "id": "TheFirstLight", "type": "TheLightType", "location": { - "type": "geo:point", - "value": "0, 0" + "type": "geo:json", + "value": { + "coordinates": [ + 0, + 0 + ], + "type": "Point" + } } -} +} \ No newline at end of file diff --git a/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json b/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json index f75d2a012..a8a690119 100644 --- a/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json +++ b/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json @@ -2,7 +2,13 @@ "id": "FirstMicroLight", "type": "MicroLights", "location": { - "type": "geo:point", - "value": "0, 0" + "type": "geo:json", + "value": { + "coordinates": [ + 0, + 0 + ], + "type": "Point" + } } -} +} \ No newline at end of file diff --git a/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json b/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json index dda3c5ad0..296300997 100644 --- a/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json +++ b/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json @@ -4,7 +4,10 @@ "type": "boolean" }, "location":{ - "value": "153,523", - "type": "geo:point" + "value":{ + "type":"Point", + "coordinates":[153,523] + }, + "type": "geo:json" } -} +} \ No newline at end of file diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index 750979813..dae2ea3d6 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -66,362 +66,361 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.deactivate(done); }); - // FIXME: #1012 - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with geo:json type and String value', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'geo:json', - // value: '23,12.5' - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with geo:json type and GeoJSON object value', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'geo:json', - // value: { - // type: 'Point', - // coordinates: [23, 12.5] - // } - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe('When the IoT Agent receives new geo-information from a device. Location with Point type and Array value', function () { - // const values = [ - // { - // name: 'location', - // type: 'Point', - // value: [23, 12.5] - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // }); - - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with LineString type and Array value', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'LineString', - // value: [ - // [23, 12.5], - // [22, 12.5] - // ] - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties2.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with LineString type and Array of Strings', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'LineString', - // value: ['23,12.5', '22,12.5'] - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties2.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe('When the IoT Agent receives new geo-information from a device. Location with None type', function () { - // const values = [ - // { - // name: 'location', - // type: 'None', - // value: 'null' - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties3.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // }); - - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with Polygon type - Array of coordinates', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'Polygon', - // value: [ - // [23, 12.5], - // [22, 13.5], - // [22, 13.5] - // ] - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties4.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe( - // 'When the IoT Agent receives new geo-information from a device.' + - // 'Location with Polygon type - list of coordinates', - // function () { - // const values = [ - // { - // name: 'location', - // type: 'Polygon', - // value: '23,12.5,22,13.5,22,13.5' - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - - // contextBrokerMock = nock('http://192.168.1.1:1026') - // .matchHeader('fiware-service', 'smartGondor') - // .post( - // '/v2/entities/light1/attrs', - // utils.readExampleFile( - // './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties4.json' - // ) - // ) - // .query({ type: 'Light' }) - // .reply(204); - - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should change the value of the corresponding attribute in the context broker', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.not.exist(error); - // contextBrokerMock.done(); - // done(); - // }); - // }); - // } - // ); - - // describe('When the IoT Agent receives new geo-information from a device. Location with a missing latitude', function () { - // const values = [ - // { - // name: 'location', - // type: 'Point', - // value: '23,12.5,22,13.5,22' - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should throw a BadGeocoordinates Error', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.exist(error); - // done(); - // }); - // }); - // }); - - // describe('When the IoT Agent receives new geo-information from a device. Location invalid coordinates', function () { - // const values = [ - // { - // name: 'location', - // type: 'Point', - // value: '2016-04-30Z' - // } - // ]; - - // beforeEach(function (done) { - // nock.cleanAll(); - // iotAgentLib.activate(iotAgentConfig, done); - // }); - - // it('should throw a BadGeocoordinates Error', function (done) { - // iotAgentLib.update('light1', 'Light', '', values, function (error) { - // should.exist(error); - // done(); - // }); - // }); - // }); + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with geo:json type and String value', + function () { + const values = [ + { + name: 'location', + type: 'geo:json', + value: '23,12.5' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with geo:json type and GeoJSON object value', + function () { + const values = [ + { + name: 'location', + type: 'geo:json', + value: { + type: 'Point', + coordinates: [23, 12.5] + } + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe('When the IoT Agent receives new geo-information from a device. Location with Point type and Array value', function () { + const values = [ + { + name: 'location', + type: 'Point', + value: [23, 12.5] + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties1.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with LineString type and Array value', + function () { + const values = [ + { + name: 'location', + type: 'LineString', + value: [ + [23, 12.5], + [22, 12.5] + ] + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties2.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with LineString type and Array of Strings', + function () { + const values = [ + { + name: 'location', + type: 'LineString', + value: ['23,12.5', '22,12.5'] + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties2.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe('When the IoT Agent receives new geo-information from a device. Location with None type', function () { + const values = [ + { + name: 'location', + type: 'None', + value: 'null' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties3.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with Polygon type - Array of coordinates', + function () { + const values = [ + { + name: 'location', + type: 'Polygon', + value: [ + [23, 12.5], + [22, 13.5], + [22, 13.5] + ] + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties4.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with Polygon type - list of coordinates', + function () { + const values = [ + { + name: 'location', + type: 'Polygon', + value: '23,12.5,22,13.5,22,13.5' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeoproperties4.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe('When the IoT Agent receives new geo-information from a device. Location with a missing latitude', function () { + const values = [ + { + name: 'location', + type: 'Point', + value: '23,12.5,22,13.5,22' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should throw a BadGeocoordinates Error', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.exist(error); + done(); + }); + }); + }); + + describe('When the IoT Agent receives new geo-information from a device. Location invalid coordinates', function () { + const values = [ + { + name: 'location', + type: 'Point', + value: '2016-04-30Z' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + iotAgentLib.activate(iotAgentConfig, done); + }); + + it('should throw a BadGeocoordinates Error', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.exist(error); + done(); + }); + }); + }); }); From a8456b218c4c65a6ee39b19701a8a970cf2474e0 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Mon, 12 Apr 2021 20:31:01 +0200 Subject: [PATCH 2/9] Re-add functionality under a flag --- CHANGES_NEXT_RELEASE | 2 +- doc/advanced-topics.md | 21 ++- doc/installationguide.md | 5 +- lib/commonConfig.js | 7 + lib/services/ngsi/entities-NGSI-v2.js | 10 +- package.json | 2 +- .../updateContextGeopropertiesAsString.json | 7 + .../ngsiv2/ngsiService/geoproperties-test.js | 130 +++++++++++++----- .../plugins/bidirectional-plugin_test.js | 3 +- 9 files changed, 144 insertions(+), 43 deletions(-) create mode 100644 test/unit/ngsiv2/examples/contextRequests/updateContextGeopropertiesAsString.json diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index bb5118733..29e0a1823 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,6 +1,6 @@ - Add: add getTypeSilently for device group and use in device registration to avoid false mongo alarm - Fix: group command is not provisioned in device when entity_type is different (#1011) -- Hotfix: avoid automatic conversion from geo:xxxx ('xxxx' diferent from 'json') to geo:json (reverts the work done in PR #854) +- Hotfix: avoid automatic conversion from geo:xxxx ('xxxx' diferent from 'json') to geo:json (reverts some of the work done in PR #854) - Add: use getDeviceSilently in checkDuplicates to avoid raise a false mongo alarm. - Add: expose getConfigurationSilently to enable retrieve a configuration without raise a false mongo alarm (#1007) - Add: db uri and options in mongo connection log INFO trace diff --git a/doc/advanced-topics.md b/doc/advanced-topics.md index 569fe886d..466905a23 100644 --- a/doc/advanced-topics.md +++ b/doc/advanced-topics.md @@ -48,8 +48,8 @@ Agent. ### GeoJSON support -The defined `type` of any GeoJSON attribute can be any set to any of the standard NGSI-v2 GeoJSON types - (e.g. -`geo:json`, `geo:point`). NGSI-LD formats such as `GeoProperty`, `Point` and `LineString` are also accepted `type` +The defined `type` of any GeoJSON attribute can be any set to any of the standard **NGSI-v2** GeoJSON types - (e.g. +`geo:json`, `geo:point`). **NGSI-LD** formats such as `GeoProperty`, `Point` and `LineString` are also accepted `type` values. If the latitude and longitude are received as separate measures, the [expression language](expressionLanguage.md) can be used to concatenate them. @@ -69,7 +69,6 @@ values. If the latitude and longitude are received as separate measures, the } ``` - For `attributes` and `static_attributes` which need to be formatted as GeoJSON values, three separate input formats are accepted. Provided the `type` is provisioned correctly, the `value` may be defined using any of the following formats: @@ -81,7 +80,7 @@ the following formats: "name": "location", "value": "23, 12.5" } -```` +``` - an array of numbers @@ -104,6 +103,18 @@ the following formats: } ``` +Because GeoJSON types (e.g. `Point`, `LineString` etc.) are native types in **NGSI-LD**, automatic GeoJSON conversion is switched on for NGSI-LD by default. + +With **NGSI-v2**, for backwards compatibility reasons, automatic GeoJSON conversion for types other than `geo:json` is turned off by default. +Add the `config.autocastGeoJSON` configuration to enable GeoJSON conversion +and supply a comma delimited list of additional types to convert. + +```json +{ + "autocastGeoJSON" : "Point,LineString,Polygon" +} +``` + ### Metadata support Both `attributes` and `static_attributes` may be supplied with metadata when provisioning an IoT Agent, so that the @@ -151,7 +162,7 @@ following: - Temporal Properties (e.g. `Datetime`, `Date` , `Time`) - GeoJSON types (e.g `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`) -Most NGSI-LD attributes are sent to the Context Broker as _properties_. If a GeoJSON type or native JSON type is +Most **NGSI-LD** attributes are sent to the Context Broker as _properties_. If a GeoJSON type or native JSON type is defined, the data will be converted to the appropriate type. Temporal properties should always be expressed in UTC, using ISO 8601. This ISO 8601 conversion is applied automatically for the `observedAt` _property-of-a-property_ metadata where present. diff --git a/doc/installationguide.md b/doc/installationguide.md index 7308abd9a..ddd4b30e2 100644 --- a/doc/installationguide.md +++ b/doc/installationguide.md @@ -278,8 +278,8 @@ used for the same purpose. For instance: standard, but the final decision has yet been confirmed), take into account it could change - **explicitAttrs**: if this flag is activated, only provisioned attributes will be processed to Context Broker. This flag is overwritten by `explicitAttrs` flag in group or device provision. -- **defaultEntityNameConjunction**: the default conjunction string used to compose a default `entity_name` when is not - provided at device provisioning time; in that case `entity_name` is composed by `type` + `:` + `device_id`. +- **defaultEntityNameConjunction**: the default conjunction string used to compose a default `entity_name` when is not + provided at device provisioning time; in that case `entity_name` is composed by `type` + `:` + `device_id`. Default value is `:`. This value is overwritten by `defaultEntityNameConjunction` in group provision. - **relaxTemplateValidation**: if this flag is activated, `objectId` attributes for incoming devices are not validated, and may exceptionally include characters (such as semi-colons) which are @@ -342,6 +342,7 @@ overrides. | IOTA_POLLING_EXPIRATION | `pollingExpiration` | | IOTA_POLLING_DAEMON_FREQ | `pollingDaemonFrequency` | | IOTA_AUTOCAST | `autocast` | +| IOTA_AUTOCAST_GEOJSON | `autocastGeoJSON` | | IOTA_MULTI_CORE | `multiCore` | | IOTA_JSON_LD_CONTEXT | `jsonLdContext` | | IOTA_FALLBACK_TENANT | `fallbackTenant` | diff --git a/lib/commonConfig.js b/lib/commonConfig.js index 47c02927a..febb29426 100644 --- a/lib/commonConfig.js +++ b/lib/commonConfig.js @@ -143,6 +143,7 @@ function processEnvironmentVariables() { 'IOTA_MONGO_DB', 'IOTA_MONGO_REPLICASET', 'IOTA_AUTOCAST', + 'IOTA_AUTOCAST_GEOJSON', 'IOTA_MONGO_PASSWORD', 'IOTA_MONGO_AUTH_SOURCE', 'IOTA_MONGO_RETRIES', @@ -453,6 +454,12 @@ function processEnvironmentVariables() { config.autocast = process.env.IOTA_AUTOCAST === 'true'; } + + if (process.env.IOTA_AUTOCAST_GEOJSON) { + config.autocastGeoJSON = process.env.IOTA_AUTOCAST_GEOJSON.split(',').map((ctx) => ctx.trim()); + } + config.autocastGeoJSON = config.autocastGeoJSON || []; + if (process.env.IOTA_MULTI_CORE) { config.multiCore = process.env.IOTA_MULTI_CORE === 'true'; } else { diff --git a/lib/services/ngsi/entities-NGSI-v2.js b/lib/services/ngsi/entities-NGSI-v2.js index 7e200acda..e7cf525f1 100644 --- a/lib/services/ngsi/entities-NGSI-v2.js +++ b/lib/services/ngsi/entities-NGSI-v2.js @@ -51,10 +51,15 @@ const context = { */ function formatGeoAttrs(attr) { const obj = attr; + if (attr.type) { - switch (attr.type.toLowerCase()) { + if ( attr.type.toLowerCase() === 'geo:json'){ + // cast GeoJSON by default + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('Point', attr.value); + } else if (config.getConfig().autocastGeoJSON.includes(attr.type)){ + switch (attr.type.toLowerCase()) { // GeoProperties - case 'geo:json': case 'geoproperty': case 'point': case 'geo:point': @@ -86,6 +91,7 @@ function formatGeoAttrs(attr) { obj.type = 'geo:json'; obj.value = NGSIUtils.getLngLats('MultiPolygon', attr.value); break; + } } } return obj; diff --git a/package.json b/package.json index 954482840..17babe11c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "lint:text": "textlint '*.md' 'doc/*.md'", "prettier": "prettier --config .prettierrc.json --write '**/**/**/**/*.js' '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", "prettier:text": "prettier 'README.md' 'doc/*.md' 'doc/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", - "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 5000 --ui bdd --exit --color true", + "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 5000 --ui bdd --exit --color true -g 'NGSI-v2 - Bidirectional data plugin'", "test:debug": "mocha --recursive 'test/**/*.js' --reporter spec --inspect-brk --timeout 30000 --ui bdd --exit", "test:coverage": "nyc --reporter=lcov mocha -- --recursive 'test/**/*.js' --reporter spec --timeout 5000 --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", diff --git a/test/unit/ngsiv2/examples/contextRequests/updateContextGeopropertiesAsString.json b/test/unit/ngsiv2/examples/contextRequests/updateContextGeopropertiesAsString.json new file mode 100644 index 000000000..dfe69c606 --- /dev/null +++ b/test/unit/ngsiv2/examples/contextRequests/updateContextGeopropertiesAsString.json @@ -0,0 +1,7 @@ +{ + "location": { + "value": "23,12.5", + "type": "Point" + } +} + diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index dae2ea3d6..839053a83 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -24,38 +24,66 @@ */ const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); - // FIXME: #1012 -//const utils = require('../../../tools/utils'); -//const should = require('should'); +const utils = require('../../../tools/utils'); +const should = require('should'); const logger = require('logops'); -//const nock = require('nock'); -//let contextBrokerMock; -//const iotAgentConfig = { -// autocast: true, -// contextBroker: { -// host: '192.168.1.1', -// port: '1026', -// ngsiVersion: 'v2' -// }, -// server: { -// port: 4041 -// }, -// types: { -// Light: { -// commands: [], -// type: 'Light', -// active: [ -// { -// name: 'location', -// type: 'geo:json' -// } -// ] -// } -// }, -// service: 'smartGondor', -// subservice: 'gardens', -// providerUrl: 'http://smartGondor.com' -//}; +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + autocast: true, + autocastGeoJSON: ['Point', 'Polygon', 'LineString'], + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + active: [ + { + name: 'location', + type: 'geo:json' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; + +// No autoCast +const iotAgentConfig2 = { + autocast: true, + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + active: [ + { + name: 'location', + type: 'geo:json' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('NGSI-v2 - Geo-JSON types autocast test', function () { beforeEach(function () { @@ -105,6 +133,46 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { } ); + + describe( + 'When the IoT Agent receives new geo-information from a device.' + + 'Location with Point type and String value and Point is not autocast', + function () { + const values = [ + { + name: 'location', + type: 'Point', + value: '23,12.5' + } + ]; + + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextGeopropertiesAsString.json' + ) + ) + .query({ type: 'Light' }) + .reply(204); + + iotAgentLib.activate(iotAgentConfig2, done); + }); + + it('should not change the value of the corresponding attribute in the context broker', function (done) { + iotAgentLib.update('light1', 'Light', '', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + describe( 'When the IoT Agent receives new geo-information from a device.' + 'Location with geo:json type and GeoJSON object value', diff --git a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js index b3569e975..706ea56e9 100644 --- a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +++ b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js @@ -33,6 +33,7 @@ const nock = require('nock'); const request = require('request'); let contextBrokerMock; const iotAgentConfig = { + autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', @@ -61,7 +62,7 @@ describe('NGSI-v2 - Bidirectional data plugin', function () { }; beforeEach(function (done) { - logger.setLevel('FATAL'); + logger.setLevel('DEBUG'); iotAgentLib.activate(iotAgentConfig, function () { iotAgentLib.clearAll(function () { From 3892f4f64d733bd2dda86547694be56f52aeadae Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Mon, 12 Apr 2021 21:35:18 +0200 Subject: [PATCH 3/9] Add autocastGeoJSON --- package.json | 2 +- test/unit/ngsiv2/ngsiService/active-devices-test.js | 1 + test/unit/ngsiv2/provisioning/device-provisioning-api_test.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 17babe11c..954482840 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "lint:text": "textlint '*.md' 'doc/*.md'", "prettier": "prettier --config .prettierrc.json --write '**/**/**/**/*.js' '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", "prettier:text": "prettier 'README.md' 'doc/*.md' 'doc/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", - "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 5000 --ui bdd --exit --color true -g 'NGSI-v2 - Bidirectional data plugin'", + "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 5000 --ui bdd --exit --color true", "test:debug": "mocha --recursive 'test/**/*.js' --reporter spec --inspect-brk --timeout 30000 --ui bdd --exit", "test:coverage": "nyc --reporter=lcov mocha -- --recursive 'test/**/*.js' --reporter spec --timeout 5000 --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", diff --git a/test/unit/ngsiv2/ngsiService/active-devices-test.js b/test/unit/ngsiv2/ngsiService/active-devices-test.js index 86dd06106..a9dc2f3e7 100644 --- a/test/unit/ngsiv2/ngsiService/active-devices-test.js +++ b/test/unit/ngsiv2/ngsiService/active-devices-test.js @@ -33,6 +33,7 @@ const logger = require('logops'); const nock = require('nock'); let contextBrokerMock; const iotAgentConfig = { + autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', diff --git a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js index 221464ab1..30f33d729 100644 --- a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +++ b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js @@ -34,6 +34,7 @@ const moment = require('moment'); let contextBrokerMock; const iotAgentConfig = { logLevel: 'FATAL', + autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', From 3d6ec0bec75d74ffc46daf8c8a3930975dcfc05c Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Mon, 12 Apr 2021 21:40:48 +0200 Subject: [PATCH 4/9] Revert debug flag --- test/unit/ngsiv2/plugins/bidirectional-plugin_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js index 706ea56e9..39c7b3c8d 100644 --- a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +++ b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js @@ -62,7 +62,7 @@ describe('NGSI-v2 - Bidirectional data plugin', function () { }; beforeEach(function (done) { - logger.setLevel('DEBUG'); + logger.setLevel('FATAL'); iotAgentLib.activate(iotAgentConfig, function () { iotAgentLib.clearAll(function () { From f4795e8ac3a2336fc70a198fd77f6d2dd86ab5da Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 14 Apr 2021 15:10:54 +0200 Subject: [PATCH 5/9] Switch to parameter based approach --- lib/services/devices/devices-NGSI-v2.js | 6 ++++-- lib/services/ngsi/entities-NGSI-v2.js | 16 +++++++++++----- .../createBidirectionalDevice.json | 12 +++--------- .../createGeopointProvisionedDevice.json | 12 +++--------- .../updateContextStaticAttributes.json | 9 +++------ .../ngsiv2/ngsiService/geoproperties-test.js | 10 +++++++++- 6 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/services/devices/devices-NGSI-v2.js b/lib/services/devices/devices-NGSI-v2.js index c985de9cc..198b2c203 100644 --- a/lib/services/devices/devices-NGSI-v2.js +++ b/lib/services/devices/devices-NGSI-v2.js @@ -238,7 +238,8 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) { for (const att in options.json) { try { // Format any GeoJSON attrs properly - options.json[att] = NGSIv2.formatGeoAttrs(options.json[att]); + const attrInfo = _.findWhere(deviceData.active, {name: att}) + options.json[att] = NGSIv2.formatGeoAttrs(options.json[att], attrInfo); } catch (error) { return callback(new errors.BadGeocoordinates(JSON.stringify(options.json))); } @@ -296,7 +297,8 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { for (const att in options.json) { try { // Format any GeoJSON attrs properly - options.json[att] = NGSIv2.formatGeoAttrs(options.json[att]); + const attrInfo = _.findWhere(deviceData.active, {name: att}); + options.json[att] = NGSIv2.formatGeoAttrs(options.json[att], attrInfo); } catch (error) { return callback(new errors.BadGeocoordinates(JSON.stringify(options.json))); } diff --git a/lib/services/ngsi/entities-NGSI-v2.js b/lib/services/ngsi/entities-NGSI-v2.js index e7cf525f1..3c32a680f 100644 --- a/lib/services/ngsi/entities-NGSI-v2.js +++ b/lib/services/ngsi/entities-NGSI-v2.js @@ -27,6 +27,7 @@ /* eslint-disable consistent-return */ +const _ = require('underscore'); const request = require('request'); const statsService = require('./../stats/statsRegistry'); const async = require('async'); @@ -49,7 +50,9 @@ const context = { * @param {Object} attr Attribute to be analyzed * @return {Object} GeoJSON version of the attribute */ -function formatGeoAttrs(attr) { +function formatGeoAttrs(attr , attrInfo) { + + const obj = attr; if (attr.type) { @@ -57,8 +60,9 @@ function formatGeoAttrs(attr) { // cast GeoJSON by default obj.type = 'geo:json'; obj.value = NGSIUtils.getLngLats('Point', attr.value); - } else if (config.getConfig().autocastGeoJSON.includes(attr.type)){ - switch (attr.type.toLowerCase()) { + } else if (attr.value && attrInfo && attrInfo.autocastGeoJSON){ + + switch (attrInfo.autocastGeoJSON.toLowerCase()) { // GeoProperties case 'geoproperty': case 'point': @@ -446,7 +450,8 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca try { // Format any GeoJSON attrs properly - options.json.entities[entity][att] = formatGeoAttrs(options.json.entities[entity][att]); + const attrInfo = _.findWhere(typeInformation.active, {name: att}); + options.json.entities[entity][att] = formatGeoAttrs(options.json.entities[entity][att], attrInfo); } catch (error) { return callback(new errors.BadGeocoordinates(JSON.stringify(options.json))); } @@ -468,7 +473,8 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca try { // Format any GeoJSON attrs properly - options.json[att] = formatGeoAttrs(options.json[att]); + const attrInfo = _.findWhere(typeInformation.active, {name: att}); + options.json[att] = formatGeoAttrs(options.json[att], attrInfo); } catch (error) { return callback(new errors.BadGeocoordinates(JSON.stringify(options.json))); } diff --git a/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json b/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json index 46e2330e3..68f806f38 100644 --- a/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +++ b/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json @@ -2,13 +2,7 @@ "id": "TheFirstLight", "type": "TheLightType", "location": { - "type": "geo:json", - "value": { - "coordinates": [ - 0, - 0 - ], - "type": "Point" - } + "type": "geo:point", + "value": "0, 0" } -} \ No newline at end of file +} diff --git a/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json b/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json index a8a690119..f75d2a012 100644 --- a/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json +++ b/test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json @@ -2,13 +2,7 @@ "id": "FirstMicroLight", "type": "MicroLights", "location": { - "type": "geo:json", - "value": { - "coordinates": [ - 0, - 0 - ], - "type": "Point" - } + "type": "geo:point", + "value": "0, 0" } -} \ No newline at end of file +} diff --git a/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json b/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json index 296300997..dda3c5ad0 100644 --- a/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json +++ b/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json @@ -4,10 +4,7 @@ "type": "boolean" }, "location":{ - "value":{ - "type":"Point", - "coordinates":[153,523] - }, - "type": "geo:json" + "value": "153,523", + "type": "geo:point" } -} \ No newline at end of file +} diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index 839053a83..f183737b2 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -31,7 +31,6 @@ const nock = require('nock'); let contextBrokerMock; const iotAgentConfig = { autocast: true, - autocastGeoJSON: ['Point', 'Polygon', 'LineString'], contextBroker: { host: '192.168.1.1', port: '1026', @@ -202,6 +201,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -238,6 +238,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -279,6 +280,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'LineString'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -318,6 +320,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'LineString'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -354,6 +357,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -396,6 +400,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Polygon'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -435,6 +440,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Polygon'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -459,6 +465,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { beforeEach(function (done) { nock.cleanAll(); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -481,6 +488,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { beforeEach(function (done) { nock.cleanAll(); + iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; iotAgentLib.activate(iotAgentConfig, done); }); From d8506fda0c6c27da241aa7f30a1107d456d883a4 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 14 Apr 2021 15:34:04 +0200 Subject: [PATCH 6/9] Add an attribute flag --- doc/advanced-topics.md | 17 ++++++++++---- doc/installationguide.md | 1 - lib/commonConfig.js | 7 ------ lib/services/ngsi/entities-NGSI-v2.js | 13 +++++------ .../ngsiv2/ngsiService/active-devices-test.js | 1 - .../ngsiv2/ngsiService/geoproperties-test.js | 22 ++++++++----------- .../plugins/bidirectional-plugin_test.js | 1 - .../device-provisioning-api_test.js | 1 - 8 files changed, 28 insertions(+), 35 deletions(-) diff --git a/doc/advanced-topics.md b/doc/advanced-topics.md index 466905a23..3652fd070 100644 --- a/doc/advanced-topics.md +++ b/doc/advanced-topics.md @@ -106,12 +106,21 @@ the following formats: Because GeoJSON types (e.g. `Point`, `LineString` etc.) are native types in **NGSI-LD**, automatic GeoJSON conversion is switched on for NGSI-LD by default. With **NGSI-v2**, for backwards compatibility reasons, automatic GeoJSON conversion for types other than `geo:json` is turned off by default. -Add the `config.autocastGeoJSON` configuration to enable GeoJSON conversion -and supply a comma delimited list of additional types to convert. +Add the `autocastGeoJSON` configuration to the attribute to enable GeoJSON conversion. Each GeoJSON attribute can be provisioned as shown: ```json { - "autocastGeoJSON" : "Point,LineString,Polygon" + "entity_type": "GPS", + "resource": "/iot/d", + "protocol": "PDI-IoTA-JSON", +..etc + "attributes": [ + { + "name": "observationSpace", + "type": "Polygon", + "autocastGeoJSON" : "true" + } + ] } ``` @@ -313,7 +322,7 @@ iotaLib.addQueryMiddleware(iotaLib.dataPlugins.compressTimestamp.query); This plugins change all the timestamp attributes found in the entity, and all the timestamp metadata found in any attribute, from the basic complete calendar timestamp of the ISO8601 (e.g.: 20071103T131805) to the extended complete -calendar timestamp (e.g.: +002007-11-03T13:18). The middleware expects to receive the basic format in updates and return +calendar timestamp (e.g.: `+002007-11-03T13:18`). The middleware expects to receive the basic format in updates and return it in queries (and viceversa, receive the extended one in queries and return it in updates). ##### Attribute Alias plugin (attributeAlias) diff --git a/doc/installationguide.md b/doc/installationguide.md index ddd4b30e2..977ee0a0c 100644 --- a/doc/installationguide.md +++ b/doc/installationguide.md @@ -342,7 +342,6 @@ overrides. | IOTA_POLLING_EXPIRATION | `pollingExpiration` | | IOTA_POLLING_DAEMON_FREQ | `pollingDaemonFrequency` | | IOTA_AUTOCAST | `autocast` | -| IOTA_AUTOCAST_GEOJSON | `autocastGeoJSON` | | IOTA_MULTI_CORE | `multiCore` | | IOTA_JSON_LD_CONTEXT | `jsonLdContext` | | IOTA_FALLBACK_TENANT | `fallbackTenant` | diff --git a/lib/commonConfig.js b/lib/commonConfig.js index febb29426..47c02927a 100644 --- a/lib/commonConfig.js +++ b/lib/commonConfig.js @@ -143,7 +143,6 @@ function processEnvironmentVariables() { 'IOTA_MONGO_DB', 'IOTA_MONGO_REPLICASET', 'IOTA_AUTOCAST', - 'IOTA_AUTOCAST_GEOJSON', 'IOTA_MONGO_PASSWORD', 'IOTA_MONGO_AUTH_SOURCE', 'IOTA_MONGO_RETRIES', @@ -454,12 +453,6 @@ function processEnvironmentVariables() { config.autocast = process.env.IOTA_AUTOCAST === 'true'; } - - if (process.env.IOTA_AUTOCAST_GEOJSON) { - config.autocastGeoJSON = process.env.IOTA_AUTOCAST_GEOJSON.split(',').map((ctx) => ctx.trim()); - } - config.autocastGeoJSON = config.autocastGeoJSON || []; - if (process.env.IOTA_MULTI_CORE) { config.multiCore = process.env.IOTA_MULTI_CORE === 'true'; } else { diff --git a/lib/services/ngsi/entities-NGSI-v2.js b/lib/services/ngsi/entities-NGSI-v2.js index 3c32a680f..5565a0605 100644 --- a/lib/services/ngsi/entities-NGSI-v2.js +++ b/lib/services/ngsi/entities-NGSI-v2.js @@ -56,13 +56,8 @@ function formatGeoAttrs(attr , attrInfo) { const obj = attr; if (attr.type) { - if ( attr.type.toLowerCase() === 'geo:json'){ - // cast GeoJSON by default - obj.type = 'geo:json'; - obj.value = NGSIUtils.getLngLats('Point', attr.value); - } else if (attr.value && attrInfo && attrInfo.autocastGeoJSON){ - - switch (attrInfo.autocastGeoJSON.toLowerCase()) { + if (attr.value && attrInfo && attrInfo.autocastGeoJSON){ + switch (attr.type.toLowerCase()) { // GeoProperties case 'geoproperty': case 'point': @@ -96,6 +91,10 @@ function formatGeoAttrs(attr , attrInfo) { obj.value = NGSIUtils.getLngLats('MultiPolygon', attr.value); break; } + } else if ( attr.type.toLowerCase() === 'geo:json'){ + // cast GeoJSON by default + obj.type = 'geo:json'; + obj.value = NGSIUtils.getLngLats('Point', attr.value); } } return obj; diff --git a/test/unit/ngsiv2/ngsiService/active-devices-test.js b/test/unit/ngsiv2/ngsiService/active-devices-test.js index a9dc2f3e7..86dd06106 100644 --- a/test/unit/ngsiv2/ngsiService/active-devices-test.js +++ b/test/unit/ngsiv2/ngsiService/active-devices-test.js @@ -33,7 +33,6 @@ const logger = require('logops'); const nock = require('nock'); let contextBrokerMock; const iotAgentConfig = { - autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index f183737b2..08198c666 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -200,8 +200,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -237,8 +236,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -280,7 +278,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'LineString'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -356,8 +354,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -400,7 +397,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Polygon'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -439,8 +436,8 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Polygon'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -464,8 +461,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ]; beforeEach(function (done) { - nock.cleanAll(); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -488,7 +484,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { beforeEach(function (done) { nock.cleanAll(); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'Point'; + iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; iotAgentLib.activate(iotAgentConfig, done); }); diff --git a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js index 39c7b3c8d..b3569e975 100644 --- a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +++ b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js @@ -33,7 +33,6 @@ const nock = require('nock'); const request = require('request'); let contextBrokerMock; const iotAgentConfig = { - autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', diff --git a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js index 30f33d729..221464ab1 100644 --- a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +++ b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js @@ -34,7 +34,6 @@ const moment = require('moment'); let contextBrokerMock; const iotAgentConfig = { logLevel: 'FATAL', - autocastGeoJSON: ['geo:point'], contextBroker: { host: '192.168.1.1', port: '1026', From 5d82f8e0bb4a00358695481d1a5eff32ad897f17 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 14 Apr 2021 16:35:41 +0200 Subject: [PATCH 7/9] Update templates --- lib/templates/createDevice.json | 5 +++++ lib/templates/createDeviceLax.json | 9 +++++++-- lib/templates/updateDevice.json | 5 +++++ lib/templates/updateDeviceLax.json | 7 ++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/templates/createDevice.json b/lib/templates/createDevice.json index 26fe72e72..c7e2eca98 100644 --- a/lib/templates/createDevice.json +++ b/lib/templates/createDevice.json @@ -99,6 +99,11 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, + "autocastGeoJSON": { + "required": false, + "description": "Whether to autocast this value as a GeoJSON type", + "type": "boolean" + }, "expression": { "description": "Optional expression for measurement transformation", "type": "string" diff --git a/lib/templates/createDeviceLax.json b/lib/templates/createDeviceLax.json index 64d25efda..3852a7285 100644 --- a/lib/templates/createDeviceLax.json +++ b/lib/templates/createDeviceLax.json @@ -97,6 +97,11 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, + "autocastGeoJSON": { + "required": false, + "description": "Whether to autocast this value as a GeoJSON type", + "type": "boolean" + }, "expression": { "description": "Optional expression for measurement transformation", "type": "string", @@ -121,7 +126,7 @@ "properties": { "object_id": { "description": "ID of the attribute in the device", - "type": "string" + "type": "string" }, "type": { "description": "Type of the attribute in the target entity", @@ -181,4 +186,4 @@ } } } -} \ No newline at end of file +} diff --git a/lib/templates/updateDevice.json b/lib/templates/updateDevice.json index a8d360a00..7abe9bbae 100644 --- a/lib/templates/updateDevice.json +++ b/lib/templates/updateDevice.json @@ -84,6 +84,11 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, + "autocastGeoJSON": { + "required": false, + "description": "Whether to autocast this value as a GeoJSON type", + "type": "boolean" + }, "expression": { "description": "Optional expression for measurement transformation", "type": "string" diff --git a/lib/templates/updateDeviceLax.json b/lib/templates/updateDeviceLax.json index 133f6999d..7d4f3ff9b 100644 --- a/lib/templates/updateDeviceLax.json +++ b/lib/templates/updateDeviceLax.json @@ -77,6 +77,11 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, + "autocastGeoJSON": { + "required": false, + "description": "Whether to autocast this value as a GeoJSON type", + "type": "boolean" + }, "expression": { "description": "Optional expression for measurement transformation", "type": "string", @@ -154,4 +159,4 @@ "type": "array" } } -} \ No newline at end of file +} From 41333d50ce02ff2838264a6b3ce1b71a8795951f Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 14 Apr 2021 16:43:59 +0200 Subject: [PATCH 8/9] Update descriptions --- .../ngsiv2/ngsiService/geoproperties-test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index 08198c666..11136adb3 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -122,7 +122,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON Point in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -162,7 +162,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig2, done); }); - it('should not change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a String in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -204,7 +204,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON Point in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -240,7 +240,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON Point in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -282,7 +282,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON LineString in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -322,7 +322,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON LineString in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -358,7 +358,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a None type in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -401,7 +401,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON Polygon in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); @@ -441,7 +441,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { iotAgentLib.activate(iotAgentConfig, done); }); - it('should change the value of the corresponding attribute in the context broker', function (done) { + it('should change the value of the corresponding attribute as a GeoJSON Polygon in the context broker', function (done) { iotAgentLib.update('light1', 'Light', '', values, function (error) { should.not.exist(error); contextBrokerMock.done(); From 9417381000470868894e4cb077448620f7e4430f Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Tue, 27 Apr 2021 12:59:38 +0200 Subject: [PATCH 9/9] autocastGeoJSON to autocast --- doc/advanced-topics.md | 4 ++-- lib/services/ngsi/entities-NGSI-v2.js | 2 +- lib/templates/createDevice.json | 2 +- lib/templates/createDeviceLax.json | 2 +- lib/templates/updateDevice.json | 2 +- lib/templates/updateDeviceLax.json | 2 +- .../ngsiv2/ngsiService/geoproperties-test.js | 20 +++++++++---------- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/advanced-topics.md b/doc/advanced-topics.md index 3652fd070..066538373 100644 --- a/doc/advanced-topics.md +++ b/doc/advanced-topics.md @@ -106,7 +106,7 @@ the following formats: Because GeoJSON types (e.g. `Point`, `LineString` etc.) are native types in **NGSI-LD**, automatic GeoJSON conversion is switched on for NGSI-LD by default. With **NGSI-v2**, for backwards compatibility reasons, automatic GeoJSON conversion for types other than `geo:json` is turned off by default. -Add the `autocastGeoJSON` configuration to the attribute to enable GeoJSON conversion. Each GeoJSON attribute can be provisioned as shown: +Add the `autocast` configuration to the attribute to enable GeoJSON conversion. Each GeoJSON attribute can be provisioned as shown: ```json { @@ -118,7 +118,7 @@ Add the `autocastGeoJSON` configuration to the attribute to enable GeoJSON conve { "name": "observationSpace", "type": "Polygon", - "autocastGeoJSON" : "true" + "autocast" : "true" } ] } diff --git a/lib/services/ngsi/entities-NGSI-v2.js b/lib/services/ngsi/entities-NGSI-v2.js index 5565a0605..9945472d6 100644 --- a/lib/services/ngsi/entities-NGSI-v2.js +++ b/lib/services/ngsi/entities-NGSI-v2.js @@ -56,7 +56,7 @@ function formatGeoAttrs(attr , attrInfo) { const obj = attr; if (attr.type) { - if (attr.value && attrInfo && attrInfo.autocastGeoJSON){ + if (attr.value && attrInfo && attrInfo.autocast){ switch (attr.type.toLowerCase()) { // GeoProperties case 'geoproperty': diff --git a/lib/templates/createDevice.json b/lib/templates/createDevice.json index c7e2eca98..0f02d5e4f 100644 --- a/lib/templates/createDevice.json +++ b/lib/templates/createDevice.json @@ -99,7 +99,7 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, - "autocastGeoJSON": { + "autocast": { "required": false, "description": "Whether to autocast this value as a GeoJSON type", "type": "boolean" diff --git a/lib/templates/createDeviceLax.json b/lib/templates/createDeviceLax.json index 3852a7285..3937bb205 100644 --- a/lib/templates/createDeviceLax.json +++ b/lib/templates/createDeviceLax.json @@ -97,7 +97,7 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, - "autocastGeoJSON": { + "autocast": { "required": false, "description": "Whether to autocast this value as a GeoJSON type", "type": "boolean" diff --git a/lib/templates/updateDevice.json b/lib/templates/updateDevice.json index 7abe9bbae..4dba99c8c 100644 --- a/lib/templates/updateDevice.json +++ b/lib/templates/updateDevice.json @@ -84,7 +84,7 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, - "autocastGeoJSON": { + "autocast": { "required": false, "description": "Whether to autocast this value as a GeoJSON type", "type": "boolean" diff --git a/lib/templates/updateDeviceLax.json b/lib/templates/updateDeviceLax.json index 7d4f3ff9b..5974c6717 100644 --- a/lib/templates/updateDeviceLax.json +++ b/lib/templates/updateDeviceLax.json @@ -77,7 +77,7 @@ "type": "string", "pattern": "^([^<>();'=\"]+)+$" }, - "autocastGeoJSON": { + "autocast": { "required": false, "description": "Whether to autocast this value as a GeoJSON type", "type": "boolean" diff --git a/test/unit/ngsiv2/ngsiService/geoproperties-test.js b/test/unit/ngsiv2/ngsiService/geoproperties-test.js index 11136adb3..fadc556bb 100644 --- a/test/unit/ngsiv2/ngsiService/geoproperties-test.js +++ b/test/unit/ngsiv2/ngsiService/geoproperties-test.js @@ -200,7 +200,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -236,7 +236,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -278,7 +278,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -318,7 +318,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = 'LineString'; + iotAgentConfig.types.Light.active[0].autocast = 'LineString'; iotAgentLib.activate(iotAgentConfig, done); }); @@ -354,7 +354,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -397,7 +397,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -436,8 +436,8 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ) .query({ type: 'Light' }) .reply(204); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -461,7 +461,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { ]; beforeEach(function (done) { - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); }); @@ -484,7 +484,7 @@ describe('NGSI-v2 - Geo-JSON types autocast test', function () { beforeEach(function (done) { nock.cleanAll(); - iotAgentConfig.types.Light.active[0].autocastGeoJSON = true; + iotAgentConfig.types.Light.active[0].autocast = true; iotAgentLib.activate(iotAgentConfig, done); });