diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index af77a18..ecb657c 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -3,4 +3,6 @@ - Add esLint using standard tamia presets - Replace var with let/const - Fix or disable eslint errors -Set Nodejs 10 as minimum version in packages.json (effectively removing Nodev8 from supported versions) +- Set Nodejs 10 as minimum version in packages.json (effectively removing Nodev8 from supported versions) +- Allow to configure id field in received callbacks from Sigfox + diff --git a/config.js b/config.js index 3b5b69a..c88fbea 100644 --- a/config.js +++ b/config.js @@ -248,6 +248,12 @@ config.iota = { defaultType: 'Thing' }; +/** + * Name of the field containing the id in the Sigfox callback payload. It can also be overriden by the + * IOTA_SIGFOX_ID_FIELD_NAME environment variable. + */ +//config.idFieldName = 'id'; + /** * Default API Key, to use with device that have been provisioned without a Configuration Group. */ diff --git a/docker/README.md b/docker/README.md index d9f9ae1..0138305 100644 --- a/docker/README.md +++ b/docker/README.md @@ -52,6 +52,7 @@ services: - "IOTA_MONGO_PORT=27017" - "IOTA_MONGO_DB=iotasigfox" - "IOTA_SIGFOX_PORT=17428" + - "IOTA_SIGFOX_ID_FIELD_NAME=id" - "IOTA_PROVIDER_URL=http://iot-agent:4041" mongodb: @@ -90,6 +91,7 @@ environment variables such as those shown below: - `IOTA_MONGO_PORT` - The port that MongoDB is listening on - `IOTA_MONGO_DB` - The name of the database used in MongoDB - `IOTA_SIGFOX_PORT` - The port where the IoT Agent listens for IoT device traffic +- `IOTA_SIGFOX_ID_FIELD_NAME` - The name od the id fields in received Sigfox callbacks (defaults to id) - `IOTA_PROVIDER_URL` - URL passed to the Context Broker when commands are registered, used as a forwarding URL location when the Context Broker issues a command to a device @@ -225,10 +227,10 @@ refer to the [Installation Guide](https://iotagent-sigfox.readthedocs.io/en/late ### Set-up appropriate Database Indexes If using Mongo-DB as a data persistence mechanism (i.e. if `IOTA_REGISTRY_TYPE=mongodb`) the device and service group -details are retrieved from a database. The default name of the IoT Agent database is `iotasigfox`. Database access can be -optimized by creating appropriate indices. +details are retrieved from a database. The default name of the IoT Agent database is `iotasigfox`. Database access can +be optimized by creating appropriate indices. -For example: +For example: ```console docker exec mongo --eval ' @@ -236,12 +238,12 @@ docker exec mongo --eval ' db = conn.getDB("iotasigfox"); db.createCollection("devices"); db.devices.createIndex({"_id.service": 1, "_id.id": 1, "_id.type": 1}); - db.devices.createIndex({"_id.type": 1}); + db.devices.createIndex({"_id.type": 1}); db.devices.createIndex({"_id.id": 1}); db.createCollection("groups"); db.groups.createIndex({"_id.resource": 1, "_id.apikey": 1, "_id.service": 1}); db.groups.createIndex({"_id.type": 1});' > /dev/null ``` -The name of the database can be altered using the `IOTA_MONGO_DB` environment variable. Alter the `conn.getDB()` +The name of the database can be altered using the `IOTA_MONGO_DB` environment variable. Alter the `conn.getDB()` statement above if an alternative database is being used. diff --git a/lib/configService.js b/lib/configService.js index 318cc29..b9b9fbe 100644 --- a/lib/configService.js +++ b/lib/configService.js @@ -35,7 +35,7 @@ function anyIsSet(variableSet) { } function processEnvironmentVariables() { - const environmentVariables = ['IOTA_SIGFOX_PORT']; + const environmentVariables = ['IOTA_SIGFOX_PORT', 'IOTA_SIGFOX_ID_FIELD_NAME']; const sigfoxVariables = ['IOTA_SIGFOX_PORT']; for (let i = 0; i < environmentVariables.length; i++) { @@ -54,6 +54,10 @@ function processEnvironmentVariables() { if (process.env.IOTA_SIGFOX_PORT) { config.sigfox.port = process.env.IOTA_SIGFOX_PORT; } + + if (process.env.IOTA_SIGFOX_ID_FIELD_NAME) { + config.idFieldName = process.env.IOTA_SIGFOX_ID_FIELD_NAME; + } } function setConfig(newConfig) { diff --git a/lib/sigfoxHandlers.js b/lib/sigfoxHandlers.js index cbff27a..cac10d7 100644 --- a/lib/sigfoxHandlers.js +++ b/lib/sigfoxHandlers.js @@ -34,12 +34,17 @@ const context = { op: 'IoTAgentSIGFOX.SigfoxHandlers' }; +function getIdField() { + return config.getConfig().idFieldName || 'id'; +} + function requiredFields(req, res, next) { - if (!req.query.id || !req.query.data) { + const idField = getIdField(); + if (!req.query[idField] || !req.query.data) { const notFoundParams = []; - if (!req.query.id) { - notFoundParams.push('id'); + if (!req.query[idField]) { + notFoundParams.push(idField); } if (!req.query.data) { @@ -61,8 +66,9 @@ function generatePayload(queryParams, device, callback) { function createPayload(data, callback) { const attributes = []; + const idField = getIdField(); for (const i in queryParams) { - if (queryParams.hasOwnProperty(i) && i !== 'data' && i !== 'id') { + if (queryParams.hasOwnProperty(i) && i !== 'data' && i !== idField) { attributes.push({ name: i, type: 'String', @@ -142,7 +148,7 @@ function handleMeasure(req, res, next) { // config.getConfig().defaultKey), apply( iotAgentLib.getDevice, - req.query.id, + req.query[getIdField()], config.getConfig().iota.service, config.getConfig().iota.subservice ), diff --git a/test/unit/requiredFields-test.js b/test/unit/requiredFields-test.js index 39c9ddd..d7530db 100644 --- a/test/unit/requiredFields-test.js +++ b/test/unit/requiredFields-test.js @@ -24,6 +24,7 @@ const sigfoxHandlers = require('../../lib/sigfoxHandlers'); const expect = require('chai').expect; const http = require('http'); +const proxyquire = require('proxyquire'); describe('Checking mandatory query fields', function() { describe('When a query without any fields is requested', function() { @@ -115,4 +116,40 @@ describe('Checking mandatory query fields', function() { }); }); }); + + describe('When a iotagent is deployed with an id field name equal to device', function() { + var configStub = {}; + configStub.getConfig = function() { + return { idFieldName: 'device' }; + }; + var sigfoxHandlers = proxyquire('../../lib/sigfoxHandlers', { './configService': configStub }); + + it('should validate required fields with device in the query', function(done) { + const req = new http.IncomingMessage(undefined), + res = new http.ServerResponse(req); + req.query = { device: 'device', data: '000000020000000000230c6f' }; + + sigfoxHandlers.requiredFields(req, res, function(data) { + expect(data).to.equal(undefined); + done(); + }); + }); + + it('should reject required fields without device in the query', function(done) { + const req = new http.IncomingMessage(undefined), + res = new http.ServerResponse(req); + req.query = { id: 'device', data: '000000020000000000230c6f' }; + + sigfoxHandlers.requiredFields(req, res, function(data) { + expect(data.code).to.equal(400); + + expect(data.name).to.equal('MANDATORY_FIELDS_NOT_FOUND'); + + expect(data.message).to.equal( + 'Some of the mandatory fields for the request were not found: ["device"]' + ); + done(); + }); + }); + }); });