From e29f38f88d88b05ee39a172a3c26ec44ef49ecd8 Mon Sep 17 00:00:00 2001 From: Daniel Moran Date: Fri, 1 Jul 2016 13:28:48 +0200 Subject: [PATCH 1/3] FIX Comand error reporint errors --- CHANGES_NEXT_RELEASE | 2 +- lib/bindings/HTTPBindings.js | 40 +++++++--- lib/errors.js | 3 +- .../updateCommandWrongEndpoint.json | 19 +++++ test/contextRequests/updateStatusError.json | 22 ++++++ .../provisionCommandWrongEndpoint.json | 19 +++++ test/unit/commandsHTTP-test.js | 73 +++++++++++++++++++ test/unit/commandsHttp-test.js | 73 +++++++++++++++++++ 8 files changed, 240 insertions(+), 11 deletions(-) create mode 100644 test/contextRequests/updateCommandWrongEndpoint.json create mode 100644 test/contextRequests/updateStatusError.json create mode 100644 test/deviceProvisioning/provisionCommandWrongEndpoint.json diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 8b137891..4dce0e50 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1 +1 @@ - +- FIX Commands won't write the Error results in the Context Broker. diff --git a/lib/bindings/HTTPBindings.js b/lib/bindings/HTTPBindings.js index 7f7ebba7..5de78f4d 100644 --- a/lib/bindings/HTTPBindings.js +++ b/lib/bindings/HTTPBindings.js @@ -173,17 +173,16 @@ function handleIncomingMeasure(req, res, next) { * @param {String} apiKey API Key corresponding to the Devices configuration. * @param {Object} device Device object containing all the information about a device. * @param {String} message UL payload. + * @param {String} status End status of the command. */ -function updateCommand(apiKey, device, message, callback) { - var commandObj = ulParser.result(message); - +function updateCommand(apiKey, device, message, command, status, callback) { iotAgentLib.setCommandResult( device.name, config.getConfig().iota.defaultResource, apiKey, - commandObj.command, - commandObj.result, - constants.COMMAND_STATUS_COMPLETED, + command, + message, + status, device, function(error) { if (error) { @@ -226,10 +225,21 @@ function generateCommandExecution(apiKey, device, attribute) { return function sendUlCommandHTTP(callback) { request(options, function(error, response, body) { - if (error || response.statusCode !== 200) { - callback(new errors.HTTPCommandResponseError(response.statusCode, error)); + if (error) { + callback(new errors.HTTPCommandResponseError('', error, cmdName)); + } else if (response.statusCode !== 200) { + callback(new errors.HTTPCommandResponseError(response.statusCode, error, cmdName)); } else { - process.nextTick(updateCommand.bind(null, apiKey, device, body, callback)); + var commandObj = ulParser.result(body); + + process.nextTick(updateCommand.bind( + null, + apiKey, + device, + commandObj.result, + commandObj.command, + constants.COMMAND_STATUS_COMPLETED, + callback)); } }); }; @@ -250,6 +260,18 @@ function commandHandler(device, attributes, callback) { async.series(attributes.map(generateCommandExecution.bind(null, apiKey, device)), function(error) { if (error) { logger.error('Error handling incoming command for device [%s]', device.id); + + updateCommand( + apiKey, + device, + error.message, + error.command, + constants.COMMAND_STATUS_ERROR, + function(error) { + if (error) { + logger.error('Error updating error information for device [%s]', device.id); + } + }); } else { logger.debug('Incoming command for device [%s]', device.id); } diff --git a/lib/errors.js b/lib/errors.js index 7259ab62..3e80271b 100644 --- a/lib/errors.js +++ b/lib/errors.js @@ -54,7 +54,8 @@ module.exports = { this.message = 'Some of the mandatory params weren\'t found in the request: ' + JSON.stringify(paramList); this.code = 400; }, - HTTPCommandResponseError: function(code, error) { + HTTPCommandResponseError: function(code, error, command) { + this.command = command; this.name = 'HTTP_COMMAND_RESPONSE_ERROR'; this.message = 'There was an error in the response of a device to a command [' + code + ' ]:' + error; this.code = 400; diff --git a/test/contextRequests/updateCommandWrongEndpoint.json b/test/contextRequests/updateCommandWrongEndpoint.json new file mode 100644 index 00000000..aad963b1 --- /dev/null +++ b/test/contextRequests/updateCommandWrongEndpoint.json @@ -0,0 +1,19 @@ +{ + "updateAction": "UPDATE", + "contextElements": [ + { + "id": "Wrong MQTT Device", + "type": "AnMQTTDevice", + "isPattern": "false", + "attributes": [ + { + "name": "PING", + "type": "command", + "value": { + "data": "22" + } + } + ] + } + ] +} diff --git a/test/contextRequests/updateStatusError.json b/test/contextRequests/updateStatusError.json new file mode 100644 index 00000000..16376d40 --- /dev/null +++ b/test/contextRequests/updateStatusError.json @@ -0,0 +1,22 @@ +{ + "contextElements": [ + { + "type": "AnMQTTDevice", + "isPattern": "false", + "id": "Wrong MQTT Device", + "attributes": [ + { + "name": "PING_status", + "type": "commandStatus", + "value": "ERROR" + }, + { + "name": "PING_info", + "type": "commandResult", + "value": "There was an error in the response of a device to a command [ ]:Error: getaddrinfo ENOTFOUND unexistent.com unexistent.com:80" + } + ] + } + ], + "updateAction": "UPDATE" +} \ No newline at end of file diff --git a/test/deviceProvisioning/provisionCommandWrongEndpoint.json b/test/deviceProvisioning/provisionCommandWrongEndpoint.json new file mode 100644 index 00000000..8abf5cf4 --- /dev/null +++ b/test/deviceProvisioning/provisionCommandWrongEndpoint.json @@ -0,0 +1,19 @@ +{ + "devices": [ + { + "device_id": "MQTT_WRONG", + "entity_name": "Wrong MQTT Device", + "entity_type": "AnMQTTDevice", + "timezone": "America/Santiago", + "protocol": "HTTP_UL", + "transport": "HTTP", + "endpoint": "http://unexistent.com/command", + "commands": [ + { + "name": "PING", + "type": "command" + } + ] + } + ] +} diff --git a/test/unit/commandsHTTP-test.js b/test/unit/commandsHTTP-test.js index 64d8d23e..4cbfb132 100644 --- a/test/unit/commandsHTTP-test.js +++ b/test/unit/commandsHTTP-test.js @@ -125,4 +125,77 @@ describe('HTTP Transport binding: commands', function() { }); }); }); + + describe('When a command arrive with a wrong protocol', function() { + var commandOptions = { + url: 'http://localhost:' + config.iota.server.port + '/v1/updateContext', + method: 'POST', + json: utils.readExampleFile('./test/contextRequests/updateCommandWrongEndpoint.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }, + provisionWrongEndpoint = { + url: 'http://localhost:' + config.iota.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/deviceProvisioning/provisionCommandWrongEndpoint.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + + beforeEach(function(done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://10.11.128.16:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/NGSI9/registerContext') + .reply(200, + utils.readExampleFile('./test/contextAvailabilityResponses/registerIoTAgent1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext') + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext') + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext', utils.readExampleFile('./test/contextRequests/updateStatusError.json')) + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus2Success.json')); + + request(provisionWrongEndpoint, function(error, response, body) { + setTimeout(function() { + done(); + }, 50); + }); + }); + + it('should return a 200 OK without errors', function(done) { + request(commandOptions, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(200); + done(); + }); + }); + + it('should update the status in the Context Broker', function(done) { + request(commandOptions, function(error, response, body) { + setTimeout(function() { + contextBrokerMock.done(); + done(); + }, 100); + }); + }); + }); }); diff --git a/test/unit/commandsHttp-test.js b/test/unit/commandsHttp-test.js index 64d8d23e..4cbfb132 100644 --- a/test/unit/commandsHttp-test.js +++ b/test/unit/commandsHttp-test.js @@ -125,4 +125,77 @@ describe('HTTP Transport binding: commands', function() { }); }); }); + + describe('When a command arrive with a wrong protocol', function() { + var commandOptions = { + url: 'http://localhost:' + config.iota.server.port + '/v1/updateContext', + method: 'POST', + json: utils.readExampleFile('./test/contextRequests/updateCommandWrongEndpoint.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }, + provisionWrongEndpoint = { + url: 'http://localhost:' + config.iota.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/deviceProvisioning/provisionCommandWrongEndpoint.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + + beforeEach(function(done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://10.11.128.16:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/NGSI9/registerContext') + .reply(200, + utils.readExampleFile('./test/contextAvailabilityResponses/registerIoTAgent1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext') + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext') + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus1Success.json')); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', '/gardens') + .post('/v1/updateContext', utils.readExampleFile('./test/contextRequests/updateStatusError.json')) + .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus2Success.json')); + + request(provisionWrongEndpoint, function(error, response, body) { + setTimeout(function() { + done(); + }, 50); + }); + }); + + it('should return a 200 OK without errors', function(done) { + request(commandOptions, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(200); + done(); + }); + }); + + it('should update the status in the Context Broker', function(done) { + request(commandOptions, function(error, response, body) { + setTimeout(function() { + contextBrokerMock.done(); + done(); + }, 100); + }); + }); + }); }); From de3f625014045d3fbc644d54180267f1172f36a0 Mon Sep 17 00:00:00 2001 From: Daniel Moran Date: Fri, 1 Jul 2016 14:27:00 +0200 Subject: [PATCH 2/3] FIX Test failing in 0.10 version --- test/unit/commandsHTTP-test.js | 6 ++++-- test/unit/commandsHttp-test.js | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/unit/commandsHTTP-test.js b/test/unit/commandsHTTP-test.js index 4cbfb132..a144eff2 100644 --- a/test/unit/commandsHTTP-test.js +++ b/test/unit/commandsHTTP-test.js @@ -126,7 +126,7 @@ describe('HTTP Transport binding: commands', function() { }); }); - describe('When a command arrive with a wrong protocol', function() { + describe('When a command arrive with a wrong endpoint', function() { var commandOptions = { url: 'http://localhost:' + config.iota.server.port + '/v1/updateContext', method: 'POST', @@ -171,7 +171,9 @@ describe('HTTP Transport binding: commands', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile('./test/contextRequests/updateStatusError.json')) + .post('/v1/updateContext', function(body) { + return body.contextElements['0'].attributes['0'].value === 'ERROR'; + }) .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus2Success.json')); request(provisionWrongEndpoint, function(error, response, body) { diff --git a/test/unit/commandsHttp-test.js b/test/unit/commandsHttp-test.js index 4cbfb132..a144eff2 100644 --- a/test/unit/commandsHttp-test.js +++ b/test/unit/commandsHttp-test.js @@ -126,7 +126,7 @@ describe('HTTP Transport binding: commands', function() { }); }); - describe('When a command arrive with a wrong protocol', function() { + describe('When a command arrive with a wrong endpoint', function() { var commandOptions = { url: 'http://localhost:' + config.iota.server.port + '/v1/updateContext', method: 'POST', @@ -171,7 +171,9 @@ describe('HTTP Transport binding: commands', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile('./test/contextRequests/updateStatusError.json')) + .post('/v1/updateContext', function(body) { + return body.contextElements['0'].attributes['0'].value === 'ERROR'; + }) .reply(200, utils.readExampleFile('./test/contextResponses/updateStatus2Success.json')); request(provisionWrongEndpoint, function(error, response, body) { From a279fe551ba56cf7fbc6788546192b2514e86f1f Mon Sep 17 00:00:00 2001 From: Daniel Moran Date: Fri, 1 Jul 2016 16:10:25 +0200 Subject: [PATCH 3/3] ADD New Bugfix version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d5eca6c..f1312bae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "iotagent-ul", "description": "IoT Agent for the Ultrlight 2.0 protocol", - "version": "1.1.5", + "version": "1.1.6", "homepage": "https://github.com/dmoranj/iotagent-ul", "author": { "name": "Daniel Moran",