From 6a7c5985b1d5270e2897d9efdbd11eb2be1bb1ff Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 20 Dec 2023 10:45:51 +0100 Subject: [PATCH 1/5] usage group endpoint and transport if applies --- lib/bindings/HTTPBindings.js | 9 ++- lib/commonBindings.js | 8 +- lib/iotaUtils.js | 140 +++++++++++++++++------------------ lib/iotagent-ul.js | 24 ++++-- 4 files changed, 97 insertions(+), 84 deletions(-) diff --git a/lib/bindings/HTTPBindings.js b/lib/bindings/HTTPBindings.js index 826b9b4b..ce2ab4d4 100644 --- a/lib/bindings/HTTPBindings.js +++ b/lib/bindings/HTTPBindings.js @@ -264,7 +264,7 @@ function handleIncomingMeasure(req, res, next) { } } - utils.retrieveDevice(req.deviceId, req.apiKey, transport, processDeviceMeasure); + utils.retrieveDevice(req.deviceId, req.apiKey, /*transport,*/ processDeviceMeasure); } /** @@ -403,16 +403,17 @@ function addDefaultHeader(req, res, next) { * * @param {Object} device Device object containing all the information about the provisioned device. */ -function setPollingAndDefaultTransport(device, callback) { +function setPollingAndDefaultTransport(device, group, callback) { + config.getLogger().debug(context, 'httpbinding.setPollingAndDefaultTransport device %j group %j', device, group); if (!device.transport) { - device.transport = 'HTTP'; + device.transport = group && group.transport ? group.transport : 'HTTP'; } if (device.transport === 'HTTP') { if (device.endpoint) { device.polling = false; } else { - device.polling = true; + device.polling = !(group && group.endpoint); } } diff --git a/lib/commonBindings.js b/lib/commonBindings.js index 67947f99..a36e883e 100644 --- a/lib/commonBindings.js +++ b/lib/commonBindings.js @@ -254,7 +254,7 @@ function singleMeasure(apiKey, attribute, device, messageStr, message) { * @param {String} topic Topic of the form: '//deviceId/attributes[/]'. * @param {Object} message message body (Object or Buffer, depending on the value). */ -function messageHandler(topic, message, protocol) { +function messageHandler(topic, message /*, protocol*/) { if (topic[0] !== '/') { topic = '/' + topic; } @@ -321,7 +321,7 @@ function messageHandler(topic, message, protocol) { } } - utils.retrieveDevice(deviceId, apiKey, protocol, processDeviceMeasure); + utils.retrieveDevice(deviceId, apiKey, /*protocol,*/ processDeviceMeasure); } /** @@ -333,7 +333,7 @@ function messageHandler(topic, message, protocol) { */ function amqpMessageHandler(topic, message) { regenerateTransid(topic); - messageHandler(topic, message, 'AMQP'); + messageHandler(topic, message /*, 'AMQP'*/); } /** @@ -346,7 +346,7 @@ function amqpMessageHandler(topic, message) { function mqttMessageHandler(topic, message) { regenerateTransid(topic); config.getLogger().debug(context, 'message topic: %s', topic); - messageHandler(topic, message, 'MQTT'); + messageHandler(topic, message /*, 'MQTT'*/); } exports.amqpMessageHandler = amqpMessageHandler; diff --git a/lib/iotaUtils.js b/lib/iotaUtils.js index 6e82d9b3..f20d229a 100644 --- a/lib/iotaUtils.js +++ b/lib/iotaUtils.js @@ -62,75 +62,75 @@ function getEffectiveApiKey(service, subservice, device, callback) { } } -function findOrCreate(deviceId, transport, apikey, group, callback) { - iotAgentLib.getDeviceSilently(deviceId, apikey, group.service, group.subservice, function (error, device) { - if (!error && device) { - if ( - (!('apikey' in device) || device.apikey === undefined) && - 'apikey' in group && - group.apikey !== undefined - ) { - config - .getLogger() - .info(context, 'Update provisioned device %j with measure/group apikey %j', device, group.apikey); - device.apikey = group.apikey; // group apikey is the same of current measure apikey - iotAgentLib.updateDevice(device, function (error) { - callback(error, device, group); - }); - } else { - callback(null, device, group); - } - } else if (error.name === 'DEVICE_NOT_FOUND') { - const newDevice = { - id: deviceId, - service: group.service, - subservice: group.subservice, - type: group.type - }; +// function findOrCreate(deviceId, transport, apikey, group, callback) { +// iotAgentLib.getDeviceSilently(deviceId, apikey, group.service, group.subservice, function (error, device) { +// if (!error && device) { +// if ( +// (!('apikey' in device) || device.apikey === undefined) && +// 'apikey' in group && +// group.apikey !== undefined +// ) { +// config +// .getLogger() +// .info(context, 'Update provisioned device %j with measure/group apikey %j', device, group.apikey); +// device.apikey = group.apikey; // group apikey is the same of current measure apikey +// iotAgentLib.updateDevice(device, function (error) { +// callback(error, device, group); +// }); +// } else { +// callback(null, device, group); +// } +// } else if (error.name === 'DEVICE_NOT_FOUND') { +// const newDevice = { +// id: deviceId, +// service: group.service, +// subservice: group.subservice, +// type: group.type +// }; - if ( - config.getConfig().iota && - config.getConfig().iota.iotManager && - config.getConfig().iota.iotManager.protocol - ) { - newDevice.protocol = config.getConfig().iota.iotManager.protocol; - } +// if ( +// config.getConfig().iota && +// config.getConfig().iota.iotManager && +// config.getConfig().iota.iotManager.protocol +// ) { +// newDevice.protocol = config.getConfig().iota.iotManager.protocol; +// } - // Fix transport depending on binding - if (!newDevice.transport) { - newDevice.transport = transport; - } - if ('ngsiVersion' in group && group.ngsiVersion !== undefined) { - newDevice.ngsiVersion = group.ngsiVersion; - } - if ( - (!('apikey' in newDevice) || newDevice.apikey === undefined) && - 'apikey' in group && - group.apikey !== undefined - ) { - newDevice.apikey = group.apikey; - } - // Check autoprovision flag in order to register or not device - if (group.autoprovision === undefined || group.autoprovision === true) { - iotAgentLib.register(newDevice, function (error, device) { - callback(error, device, group); - }); - } else { - config - .getLogger() - .info( - context, - 'Device %j not provisioned due autoprovision is disabled by its conf %j', - newDevice, - group - ); - callback(new errors.DeviceNotFound(deviceId)); - } - } else { - callback(error); - } - }); -} +// // Fix transport depending on binding +// if (!newDevice.transport) { +// newDevice.transport = transport; +// } +// if ('ngsiVersion' in group && group.ngsiVersion !== undefined) { +// newDevice.ngsiVersion = group.ngsiVersion; +// } +// if ( +// (!('apikey' in newDevice) || newDevice.apikey === undefined) && +// 'apikey' in group && +// group.apikey !== undefined +// ) { +// newDevice.apikey = group.apikey; +// } +// // Check autoprovision flag in order to register or not device +// if (group.autoprovision === undefined || group.autoprovision === true) { +// iotAgentLib.register(newDevice, function (error, device) { +// callback(error, device, group); +// }); +// } else { +// config +// .getLogger() +// .info( +// context, +// 'Device %j not provisioned due autoprovision is disabled by its conf %j', +// newDevice, +// group +// ); +// callback(new errors.DeviceNotFound(deviceId)); +// } +// } else { +// callback(error); +// } +// }); +// } /** * Retrieve a device from the device repository based on the given APIKey and DeviceID, creating one if none is @@ -139,7 +139,7 @@ function findOrCreate(deviceId, transport, apikey, group, callback) { * @param {String} deviceId Device ID of the device that wants to be retrieved or created. * @param {String} apiKey APIKey of the Device Group (or default APIKey). */ -function retrieveDevice(deviceId, apiKey, transport, callback) { +function retrieveDevice(deviceId, apiKey, /*transport,*/ callback) { if (apiKey === config.getConfig().defaultKey) { iotAgentLib.getDevicesByAttribute('id', deviceId, undefined, undefined, function (error, devices) { if (error) { @@ -163,7 +163,7 @@ function retrieveDevice(deviceId, apiKey, transport, callback) { async.waterfall( [ apply(iotAgentLib.getConfigurationSilently, config.getConfig().iota.defaultResource, apiKey), - apply(findOrCreate, deviceId, transport, apiKey), // group.apikey and apikey are the same + apply(iotAgentLib.findOrCreate, deviceId, /* transport,*/ apiKey), // group.apikey and apikey are the same apply( iotAgentLib.mergeDeviceWithConfiguration, ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], @@ -246,7 +246,7 @@ function manageConfiguration(apiKey, deviceId, device, objMessage, sendFunction, async.waterfall( [ apply(iotAgentLib.query, device.name, device.type, '', objMessage.attributes, device), - apply(sendFunction, apiKey, deviceId) + apply(sendFunction, apiKey, {}, deviceId) ], handleSendConfigurationError ); diff --git a/lib/iotagent-ul.js b/lib/iotagent-ul.js index d1f07b27..bf93a3aa 100644 --- a/lib/iotagent-ul.js +++ b/lib/iotagent-ul.js @@ -40,12 +40,24 @@ const transportSelector = require('./transportSelector'); */ function configurationNotificationHandler(device, updates, callback) { function invokeConfiguration(apiKey, callback) { - transportSelector.applyFunctionFromBinding( - [apiKey, device.id, updates], - 'sendConfigurationToDevice', - device.transport || config.getConfig().defaultTransport, - callback - ); + let group = {}; + iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', apiKey, function ( + error, + foundGroup + ) { + if (!error) { + group = foundGroup; + } + + transportSelector.applyFunctionFromBinding( + [apiKey, group, device.id, updates], + 'sendConfigurationToDevice', + device.transport || + (group && group.transport ? group.transport : undefined) || + config.getConfig().defaultTransport, + callback + ); + }); } async.waterfall( From 214e8b21f555aadd86a679875c9dcd34a6a9a54b Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 20 Dec 2023 11:03:58 +0100 Subject: [PATCH 2/5] update test --- lib/bindings/HTTPBindings.js | 24 ++++++++++++++++++++++-- lib/bindings/MQTTBinding.js | 2 +- lib/commonBindings.js | 22 +++++++++++++++------- test/unit/ngsiv2/httpBindings-test.js | 5 ++--- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/bindings/HTTPBindings.js b/lib/bindings/HTTPBindings.js index ce2ab4d4..13e1a079 100644 --- a/lib/bindings/HTTPBindings.js +++ b/lib/bindings/HTTPBindings.js @@ -427,7 +427,17 @@ function setPollingAndDefaultTransport(device, group, callback) { */ function deviceProvisioningHandler(device, callback) { config.getLogger().debug(context, 'httpbinding.deviceProvisioningHandler %j', device); - setPollingAndDefaultTransport(device, callback); + let group = {}; + iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', device.apikey, function ( + error, + foundGroup + ) { + if (!error) { + group = foundGroup; + } + config.getLogger().debug(context, 'httpbinding.deviceProvisioningHandler group %j', group); + setPollingAndDefaultTransport(device, group, callback); + }); } /** @@ -437,7 +447,17 @@ function deviceProvisioningHandler(device, callback) { */ function deviceUpdatingHandler(device, callback) { config.getLogger().debug(context, 'httpbinding.deviceUpdatingHandler %j', device); - setPollingAndDefaultTransport(device, callback); + let group = {}; + iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', device.apikey, function ( + error, + foundGroup + ) { + if (!error) { + group = foundGroup; + } + config.getLogger().debug(context, 'httpbinding.deviceUpdatingHandler group %j', group); + setPollingAndDefaultTransport(device, group, callback); + }); } function start(callback) { diff --git a/lib/bindings/MQTTBinding.js b/lib/bindings/MQTTBinding.js index 12c50e64..cf79aada 100644 --- a/lib/bindings/MQTTBinding.js +++ b/lib/bindings/MQTTBinding.js @@ -238,7 +238,7 @@ function commandHandler(device, attributes, callback) { * @param {String} deviceId ID of the Device. * @param {Object} results Context Broker response. */ -function sendConfigurationToDevice(apiKey, deviceId, results, callback) { +function sendConfigurationToDevice(apiKey, group, deviceId, results, callback) { const configurations = utils.createConfigurationNotification(results); const options = {}; context = fillService(context, { service: 'n/a', subservice: 'n/a' }); diff --git a/lib/commonBindings.js b/lib/commonBindings.js index a36e883e..d40a9502 100644 --- a/lib/commonBindings.js +++ b/lib/commonBindings.js @@ -64,13 +64,21 @@ function guessType(attribute, device) { return constants.DEFAULT_ATTRIBUTE_TYPE; } -function sendConfigurationToDevice(device, apiKey, deviceId, results, callback) { - transportSelector.applyFunctionFromBinding( - [apiKey, deviceId, results], - 'sendConfigurationToDevice', - device.transport || config.getConfig().defaultTransport, - callback - ); +function sendConfigurationToDevice(device, apiKey, group, deviceId, results, callback) { + iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', apiKey, function ( + error, + foundGroup + ) { + if (!error) { + group = foundGroup; + } + transportSelector.applyFunctionFromBinding( + [apiKey, group, deviceId, results], + 'sendConfigurationToDevice', + device.transport || group.transport || config.getConfig().defaultTransport, + callback + ); + }); } /** diff --git a/test/unit/ngsiv2/httpBindings-test.js b/test/unit/ngsiv2/httpBindings-test.js index f6dfa1bf..6bdc3b79 100644 --- a/test/unit/ngsiv2/httpBindings-test.js +++ b/test/unit/ngsiv2/httpBindings-test.js @@ -237,7 +237,7 @@ describe('HTTP Transport binding: measures', function () { }); }); }); - it('should add a transport to the registered devices', function (done) { + it('should not add a transport to the registered devices', function (done) { const getDeviceOptions = { url: 'http://localhost:' + config.iota.server.port + '/iot/devices/UL_UNPROVISIONED', method: 'GET', @@ -251,8 +251,7 @@ describe('HTTP Transport binding: measures', function () { request(getDeviceOptions, function (error, response, body) { should.not.exist(error); response.statusCode.should.equal(200); - should.exist(body.transport); - body.transport.should.equal('HTTP'); + should.not.exist(body.transport); done(); }); }); From 26dd0bc4ca5388d0d6a75441413552392047e6e2 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 20 Dec 2023 12:02:23 +0100 Subject: [PATCH 3/5] update doc --- CHANGES_NEXT_RELEASE | 3 +- docs/usermanual.md | 111 +++++++++++++++++------------------ lib/bindings/HTTPBindings.js | 10 +++- lib/commonBindings.js | 8 +-- lib/iotaUtils.js | 74 +---------------------- lib/iotagent-ul.js | 30 ++++++++-- 6 files changed, 92 insertions(+), 144 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 139597f9..9873dae3 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,2 +1 @@ - - +- ADD: check and usage endpoint and transport from Group level when commands diff --git a/docs/usermanual.md b/docs/usermanual.md index 8371cec3..51ea32a3 100644 --- a/docs/usermanual.md +++ b/docs/usermanual.md @@ -149,60 +149,59 @@ then the NGSI v2 update uses `10`(number), `true` (boolean) and `78.8` (number) (string) and "78.8" (string). This functionality relies on string measures casting feature implemented in the iotagent library. This functionality -uses native JavaScript [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) -function to cast data coming from measures (as text) to JSON native types. This functionality does not change the attribute type, -using the type specified in the config group or device provision, even if it is not consistent with the measures that are coming. - +uses native JavaScript +[`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) function +to cast data coming from measures (as text) to JSON native types. This functionality does not change the attribute type, +using the type specified in the config group or device provision, even if it is not consistent with the measures that +are coming. As an example, for a given measure: - + ``` -a|1|b|1.01|c|true|d|null|e|[1,2,3]|f|['a','b','c']|g|{a:1,b:2,c:3}|h|I'm a string +a|1|b|1.01|c|true|d|null|e|[1,2,3]|f|['a','b','c']|g|{a:1,b:2,c:3}|h|I'm a string ``` The resulting entity would be something like: ```json { - "id": "entityid:001", - "type": "entitytype", - "a": { - "type": "provisionedType", - "value": 1 - }, - "b": { - "type": "provisionedType", - "value": 1.01 - }, - "c": { - "type": "provisionedType", - "value": true - }, - "d": { - "type": "provisionedType", - "value": null - }, - "e": { - "type": "provisionedType", - "value": [1,2,3] - }, - "f": { - "type": "provisionedType", - "value": ["a","b","c"] - }, - "g": { - "type": "provisionedType", - "value": {"a":1,"b":2,"c":3} - }, - "h": { - "type": "provisionedType", - "value": "I'm a string" - } + "id": "entityid:001", + "type": "entitytype", + "a": { + "type": "provisionedType", + "value": 1 + }, + "b": { + "type": "provisionedType", + "value": 1.01 + }, + "c": { + "type": "provisionedType", + "value": true + }, + "d": { + "type": "provisionedType", + "value": null + }, + "e": { + "type": "provisionedType", + "value": [1, 2, 3] + }, + "f": { + "type": "provisionedType", + "value": ["a", "b", "c"] + }, + "g": { + "type": "provisionedType", + "value": { "a": 1, "b": 2, "c": 3 } + }, + "h": { + "type": "provisionedType", + "value": "I'm a string" + } } ``` - -Note that `provisionedType` is the type included in the device provision or config group, and it is not changed. - +Note that `provisionedType` is the type included in the device provision or config group, and it is not changed. ### Transport Protocol @@ -247,8 +246,8 @@ and [Practice: Scenario 3: commands - error](https://github.com/telefonicaid/iotagent-node-lib/blob/master/doc/northboundinteractions.md#scenario-3-commands-error). MQTT devices commands are always push. For HTTP Devices commands to be push they **must** be provisioned with the -`endpoint` attribute, that will contain the URL where the IoT Agent will send the received commands. Otherwise the -command will be poll. When using the HTTP transport, the command handling have two flavours: +`endpoint` attribute, from device or group device, that will contain the URL where the IoT Agent will send the received +commands. Otherwise the command will be poll. When using the HTTP transport, the command handling have two flavours: - **Push commands**: The request payload format will be the one described in the UL Protocol description. The device will reply with a 200OK response containing the result of the command in the UL2.0 result format. Example of the @@ -315,19 +314,16 @@ by the protocol, in this case '/ul', just include apikey and deviceid (e.g: `/FF > **Note** Measures and commands are sent over different MQTT topics: > -> * _Measures_ are sent on the `////attrs` topic, -> * _Commands_ are sent on the `///cmd` topic, +> - _Measures_ are sent on the `////attrs` topic, +> - _Commands_ are sent on the `///cmd` topic, > -> The reasoning behind this is that when sending measures northbound from device to IoT Agent, -> it is necessary to explicitly identify which IoT Agent is needed to parse the data. This -> is done by prefixing the relevant MQTT topic with a protocol, otherwise there is no way to -> define which agent is processing the measure. This mechanism allows smart systems to connect -> different devices to different IoT Agents according to need. +> The reasoning behind this is that when sending measures northbound from device to IoT Agent, it is necessary to +> explicitly identify which IoT Agent is needed to parse the data. This is done by prefixing the relevant MQTT topic +> with a protocol, otherwise there is no way to define which agent is processing the measure. This mechanism allows +> smart systems to connect different devices to different IoT Agents according to need. > -> For southbound commands, this distinction is unnecessary since the correct IoT Agent has already -> registered itself for the command during the device provisioning step and the device will always -> receive commands in an appropriate format. - +> For southbound commands, this distinction is unnecessary since the correct IoT Agent has already registered itself for +> the command during the device provisioning step and the device will always receive commands in an appropriate format. This transport protocol binding is still under development. @@ -375,7 +371,8 @@ commands and a topic to receive configuration information. This mechanism can be configuration flag, `configRetrieval`. In case of MQTT to retrieve configuration parameters from the Context Broker, it is required that the device should be -provisioned using "MQTT" as transport key. By default it will be considered "HTTP" as transport. +provisioned using "MQTT" as transport key, at device or group level. By default it will be considered "HTTP" as +transport. The parameter will be given as follows: diff --git a/lib/bindings/HTTPBindings.js b/lib/bindings/HTTPBindings.js index 13e1a079..115df2a8 100644 --- a/lib/bindings/HTTPBindings.js +++ b/lib/bindings/HTTPBindings.js @@ -45,7 +45,6 @@ const config = require('../configService'); let context = { op: 'IOTAUL.HTTP.Binding' }; -const transport = 'HTTP'; /* eslint-disable-next-line no-unused-vars */ function handleError(error, req, res, next) { @@ -67,7 +66,7 @@ function parseData(req, res, next) { let data; let error; let payload; - + context = fillService(context, { service: 'n/a', subservice: 'n/a' }); if (req.body) { payload = req.body; } else { @@ -264,7 +263,7 @@ function handleIncomingMeasure(req, res, next) { } } - utils.retrieveDevice(req.deviceId, req.apiKey, /*transport,*/ processDeviceMeasure); + utils.retrieveDevice(req.deviceId, req.apiKey, processDeviceMeasure); } /** @@ -278,6 +277,7 @@ function handleIncomingMeasure(req, res, next) { function generateCommandExecution(apiKey, device, attribute) { const cmdName = attribute.name; const cmdAttributes = attribute.value; + context = fillService(context, device); const options = { url: device.endpoint, method: 'POST', @@ -360,6 +360,7 @@ function generateCommandExecution(apiKey, device, attribute) { * @param {String} attributes Command attributes (in NGSIv1 format). */ function commandHandler(device, attributes, callback) { + context = fillService(context, device); utils.getEffectiveApiKey(device.service, device.subservice, device, function (error, apiKey) { async.series(attributes.map(generateCommandExecution.bind(null, apiKey, device)), function (error) { if (error) { @@ -404,6 +405,7 @@ function addDefaultHeader(req, res, next) { * @param {Object} device Device object containing all the information about the provisioned device. */ function setPollingAndDefaultTransport(device, group, callback) { + context = fillService(context, device); config.getLogger().debug(context, 'httpbinding.setPollingAndDefaultTransport device %j group %j', device, group); if (!device.transport) { device.transport = group && group.transport ? group.transport : 'HTTP'; @@ -426,6 +428,7 @@ function setPollingAndDefaultTransport(device, group, callback) { * @param {Object} device Device object containing all the information about the provisioned device. */ function deviceProvisioningHandler(device, callback) { + context = fillService(context, device); config.getLogger().debug(context, 'httpbinding.deviceProvisioningHandler %j', device); let group = {}; iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', device.apikey, function ( @@ -446,6 +449,7 @@ function deviceProvisioningHandler(device, callback) { * @param {Object} device Device object containing all the information about the updated device. */ function deviceUpdatingHandler(device, callback) { + context = fillService(context, device); config.getLogger().debug(context, 'httpbinding.deviceUpdatingHandler %j', device); let group = {}; iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', device.apikey, function ( diff --git a/lib/commonBindings.js b/lib/commonBindings.js index d40a9502..23fffa28 100644 --- a/lib/commonBindings.js +++ b/lib/commonBindings.js @@ -262,7 +262,7 @@ function singleMeasure(apiKey, attribute, device, messageStr, message) { * @param {String} topic Topic of the form: '//deviceId/attributes[/]'. * @param {Object} message message body (Object or Buffer, depending on the value). */ -function messageHandler(topic, message /*, protocol*/) { +function messageHandler(topic, message) { if (topic[0] !== '/') { topic = '/' + topic; } @@ -329,7 +329,7 @@ function messageHandler(topic, message /*, protocol*/) { } } - utils.retrieveDevice(deviceId, apiKey, /*protocol,*/ processDeviceMeasure); + utils.retrieveDevice(deviceId, apiKey, processDeviceMeasure); } /** @@ -341,7 +341,7 @@ function messageHandler(topic, message /*, protocol*/) { */ function amqpMessageHandler(topic, message) { regenerateTransid(topic); - messageHandler(topic, message /*, 'AMQP'*/); + messageHandler(topic, message); } /** @@ -354,7 +354,7 @@ function amqpMessageHandler(topic, message) { function mqttMessageHandler(topic, message) { regenerateTransid(topic); config.getLogger().debug(context, 'message topic: %s', topic); - messageHandler(topic, message /*, 'MQTT'*/); + messageHandler(topic, message); } exports.amqpMessageHandler = amqpMessageHandler; diff --git a/lib/iotaUtils.js b/lib/iotaUtils.js index f20d229a..38d2490a 100644 --- a/lib/iotaUtils.js +++ b/lib/iotaUtils.js @@ -62,76 +62,6 @@ function getEffectiveApiKey(service, subservice, device, callback) { } } -// function findOrCreate(deviceId, transport, apikey, group, callback) { -// iotAgentLib.getDeviceSilently(deviceId, apikey, group.service, group.subservice, function (error, device) { -// if (!error && device) { -// if ( -// (!('apikey' in device) || device.apikey === undefined) && -// 'apikey' in group && -// group.apikey !== undefined -// ) { -// config -// .getLogger() -// .info(context, 'Update provisioned device %j with measure/group apikey %j', device, group.apikey); -// device.apikey = group.apikey; // group apikey is the same of current measure apikey -// iotAgentLib.updateDevice(device, function (error) { -// callback(error, device, group); -// }); -// } else { -// callback(null, device, group); -// } -// } else if (error.name === 'DEVICE_NOT_FOUND') { -// const newDevice = { -// id: deviceId, -// service: group.service, -// subservice: group.subservice, -// type: group.type -// }; - -// if ( -// config.getConfig().iota && -// config.getConfig().iota.iotManager && -// config.getConfig().iota.iotManager.protocol -// ) { -// newDevice.protocol = config.getConfig().iota.iotManager.protocol; -// } - -// // Fix transport depending on binding -// if (!newDevice.transport) { -// newDevice.transport = transport; -// } -// if ('ngsiVersion' in group && group.ngsiVersion !== undefined) { -// newDevice.ngsiVersion = group.ngsiVersion; -// } -// if ( -// (!('apikey' in newDevice) || newDevice.apikey === undefined) && -// 'apikey' in group && -// group.apikey !== undefined -// ) { -// newDevice.apikey = group.apikey; -// } -// // Check autoprovision flag in order to register or not device -// if (group.autoprovision === undefined || group.autoprovision === true) { -// iotAgentLib.register(newDevice, function (error, device) { -// callback(error, device, group); -// }); -// } else { -// config -// .getLogger() -// .info( -// context, -// 'Device %j not provisioned due autoprovision is disabled by its conf %j', -// newDevice, -// group -// ); -// callback(new errors.DeviceNotFound(deviceId)); -// } -// } else { -// callback(error); -// } -// }); -// } - /** * Retrieve a device from the device repository based on the given APIKey and DeviceID, creating one if none is * found for the given data. @@ -139,7 +69,7 @@ function getEffectiveApiKey(service, subservice, device, callback) { * @param {String} deviceId Device ID of the device that wants to be retrieved or created. * @param {String} apiKey APIKey of the Device Group (or default APIKey). */ -function retrieveDevice(deviceId, apiKey, /*transport,*/ callback) { +function retrieveDevice(deviceId, apiKey, callback) { if (apiKey === config.getConfig().defaultKey) { iotAgentLib.getDevicesByAttribute('id', deviceId, undefined, undefined, function (error, devices) { if (error) { @@ -163,7 +93,7 @@ function retrieveDevice(deviceId, apiKey, /*transport,*/ callback) { async.waterfall( [ apply(iotAgentLib.getConfigurationSilently, config.getConfig().iota.defaultResource, apiKey), - apply(iotAgentLib.findOrCreate, deviceId, /* transport,*/ apiKey), // group.apikey and apikey are the same + apply(iotAgentLib.findOrCreate, deviceId, apiKey), // group.apikey and apikey are the same apply( iotAgentLib.mergeDeviceWithConfiguration, ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], diff --git a/lib/iotagent-ul.js b/lib/iotagent-ul.js index bf93a3aa..baa363cd 100644 --- a/lib/iotagent-ul.js +++ b/lib/iotagent-ul.js @@ -97,12 +97,30 @@ function commandHandler(id, type, service, subservice, attributes, callback) { ); callback(error); } else { - transportSelector.applyFunctionFromBinding( - [device, attributes], - 'commandHandler', - device.transport || config.getConfig().defaultTransport, - callback - ); + iotaUtils.getEffectiveApiKey(device.service, device.subservice, device, function (error, apiKey) { + if (error) { + callback(error); + } else { + let group = {}; + iotAgentLib.getConfigurationSilently( + config.getConfig().iota.defaultResource || '', + apiKey, + function (error, foundGroup) { + if (!error) { + group = foundGroup; + } + transportSelector.applyFunctionFromBinding( + [device, attributes], + 'commandHandler', + device.transport || + (group && group.transport ? group.transport : undefined) || + config.getConfig().defaultTransport, + callback + ); + } + ); + } + }); } }); } From da343eefc909a39cec9789fce6d55577802d41b4 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 20 Dec 2023 12:05:55 +0100 Subject: [PATCH 4/5] fix linter --- docs/usermanual.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/usermanual.md b/docs/usermanual.md index 51ea32a3..0cb8de8a 100644 --- a/docs/usermanual.md +++ b/docs/usermanual.md @@ -153,8 +153,7 @@ uses native JavaScript [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) function to cast data coming from measures (as text) to JSON native types. This functionality does not change the attribute type, using the type specified in the config group or device provision, even if it is not consistent with the measures that -are coming. -As an example, for a given measure: +are coming. As an example, for a given measure: ``` a|1|b|1.01|c|true|d|null|e|[1,2,3]|f|['a','b','c']|g|{a:1,b:2,c:3}|h|I'm a string From 9b2ca5086d763827d4789567b2ea440e7e74c8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 20 Dec 2023 12:33:38 +0100 Subject: [PATCH 5/5] Update CHANGES_NEXT_RELEASE --- CHANGES_NEXT_RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 9873dae3..9c8aed57 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1 +1 @@ -- ADD: check and usage endpoint and transport from Group level when commands +- Add: check and usage endpoint and transport from Group level when commands