From cd09f19060f61f9aa711638abc4e5541911565eb Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 1 Jan 2023 19:39:43 +0100 Subject: [PATCH] Sensors: Improve generic sensors * Makes the main states of the sensors writable to ease up scripting by not having to go through the scaling input state * Adds min/max settings for all input states to ease up calibration with various input devices * For sensors that have a main state min/max setting, actually write those min/max settings to the dynamic min/max values of the state --- ...integrationplugingenericheatingcooling.cpp | 6 + genericsensors/README.md | 60 +++- .../integrationplugingenericsensors.cpp | 222 +++++++++--- .../integrationplugingenericsensors.json | 315 ++++++++++++++---- 4 files changed, 487 insertions(+), 116 deletions(-) diff --git a/genericheatingcooling/integrationplugingenericheatingcooling.cpp b/genericheatingcooling/integrationplugingenericheatingcooling.cpp index 8e7e153..3b5d15d 100644 --- a/genericheatingcooling/integrationplugingenericheatingcooling.cpp +++ b/genericheatingcooling/integrationplugingenericheatingcooling.cpp @@ -51,6 +51,12 @@ void IntegrationPluginGenericHeatingCooling::setupThing(ThingSetupInfo *info) if (paramTypeId == thermostatSettingsTemperatureDifferenceParamTypeId) { thermostatCheckPowerOutputState(thing); } + if (paramTypeId == thermostatSettingsMinTargetTemperatureParamTypeId) { + thing->setStateMinValue(thermostatTargetTemperatureStateTypeId, value); + } + if (paramTypeId == thermostatSettingsMaxTargetTemperatureParamTypeId) { + thing->setStateMaxValue(thermostatTargetTemperatureStateTypeId, value); + } }); } else if (thing->thingClassId() == sgReadyThingClassId) { bool relay1 = thing->stateValue(sgReadyRelay1StateTypeId).toBool(); diff --git a/genericsensors/README.md b/genericsensors/README.md index 1dee656..62c2522 100644 --- a/genericsensors/README.md +++ b/genericsensors/README.md @@ -4,13 +4,23 @@ This plugin allows to create generic sensors in nymea. Such things don't have an functionality on their own, but allow to create a visually appealing experience when using general purpose input and outputs, such as GPIOs or MQTT. -## Set-up +## Set-up by connecting Generic inputs -First, set up a sensor with generic inputs or outputs. For instance from the GPIO plugin -or the MQTT plugin. When done, set up the desired generic thing and use the things settings to connect -the inputs and/or outputs or use nymea scripts to process MQTT messages and fill in the states accordingly. +* Set up a sensor with generic inputs. For instance from a GPIO or an I2C device. +* Set up the desired generc thing +* Use the generic things settings to connect it to the device in the Generic Input/Outputs section. +* Use the min/max settings to calibrate the sensor. -### Example: A soil moisture sensor on an analog input GPIO +## Set-up by using scripting + +* Set up a thing that obtains sensor data in one way or another. For example via the +mqtt client , the HTTP client or the Modbus commander plugin. +* Set up the desired generic thing. +* Create a script obtaining the input value and writing it to the generic sensor thing. + +## Examples + +### A soil moisture sensor on an analog input GPIO First, set up the GPIO to receive the analog GPIO values from the sensor. Normally such an analog input GPIO will dispatch values from 0V to e.g. 3.3V, depending on the @@ -18,12 +28,48 @@ hardware. An input value of 0V normally refers to a soil moisture value of 0%, w an input value of 3.3V would refer to the maximum, that is 100% soil moisture. Once those input values are received in nymea, set up a generic soil moisture thing and go to its settings. In there you'll find the Input/Output connections section which -allows to map this generic soil moisture sensure to the according GPIO input. Once +allows to map this generic soil moisture sensor to the according GPIO input. Once this connection has been made, the generic soil moisture thing will represent the input from the GPIO in a nice sensor view. -Some sensors might not support the full range from 0% to 100% and might output +Some sensors might require calibration in order to display correct values. For instance +a sensor may not support the full range from 0% to 100% and might output a value of 0V on a minimum soil moisture of e.g. 10% or might only be able to measure the soil moisture up to, say, 90%. Normally the sensor hardware would give that information in the data sheet or user guide. If this is the case, the appropriate input range can also be defined in the generic moisture sensor page. + + +### A temperature sensor from MQTT +First decide on the MQTT broker to be used. The possibility is to use the nymea +integrated MQTT broker or an external one. + +If using the nymea internal mqtt broker, make sure it is enabled in the System Settings +and, if authentication is enabled for the server, a valid client policy is in place. +Then configure the device to publish values to nymea. Then create an "Internal mqtt client" +thing and subscribe to an appropriate topic filter for the device's publishing topic. + +If instead the device publishes values to another mqtt broker, create a new "MQTT client" +thing in nymea and provide connection information to the external MQTT broker. + +Once a MQTT client thing is set up, create the desired generic sensor thing. + +Then create a nymea script which parses the MQTT message and writes the value to the generic +sensor. + +``` +ThingEvent { + thingId: "..." // the mqtt client's id + eventName": "triggered" + onTriggered: { + console.log("Publish received from MQTT", JSON.stringify(params)) + temperatureState.value = JSON.parse(params["data"])["temperature"] + } +} + +ThingState { + id: temperatureState + thingId: "..." // the generic temperature sensor + stateName": "temperature" +} +``` diff --git a/genericsensors/integrationplugingenericsensors.cpp b/genericsensors/integrationplugingenericsensors.cpp index d6006b5..78c5b26 100644 --- a/genericsensors/integrationplugingenericsensors.cpp +++ b/genericsensors/integrationplugingenericsensors.cpp @@ -44,6 +44,76 @@ void IntegrationPluginGenericSensors::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); + if (thing->thingClassId() == temperatureSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == temperatureSensorSettingsMinTempParamTypeId) { + thing->setStateMinValue(temperatureSensorTemperatureStateTypeId, value); + } + if (settingTypeId == temperatureSensorSettingsMaxTempParamTypeId) { + thing->setStateMaxValue(temperatureSensorTemperatureStateTypeId, value); + } + }); + } + if (thing->thingClassId() == orpSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == orpSensorSettingsMinORPParamTypeId) { + thing->setStateMinValue(orpSensorOrpStateTypeId, value); + } + if (settingTypeId == orpSensorSettingsMaxORPParamTypeId) { + thing->setStateMaxValue(orpSensorOrpStateTypeId, value); + } + }); + } + if (thing->thingClassId() == pressureSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == pressureSensorSettingsMinPressureParamTypeId) { + thing->setStateMinValue(pressureSensorPressureStateTypeId, value); + } + if (settingTypeId == pressureSensorSettingsMaxPressureParamTypeId) { + thing->setStateMaxValue(pressureSensorPressureStateTypeId, value); + } + }); + } + if (thing->thingClassId() == coSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == coSensorSettingsMinCOParamTypeId) { + thing->setStateMinValue(coSensorCoStateTypeId, value); + } + if (settingTypeId == coSensorSettingsMaxCOParamTypeId) { + thing->setStateMaxValue(coSensorCoStateTypeId, value); + } + }); + } + if (thing->thingClassId() == co2SensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == co2SensorSettingsMinCO2ParamTypeId) { + thing->setStateMinValue(co2SensorCo2StateTypeId, value); + } + if (settingTypeId == co2SensorSettingsMaxCO2ParamTypeId) { + thing->setStateMaxValue(co2SensorCo2StateTypeId, value); + } + }); + } + if (thing->thingClassId() == gasSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == gasSensorSettingsMinValueParamTypeId) { + thing->setStateMinValue(gasSensorGasLevelStateTypeId, value); + } + if (settingTypeId == gasSensorSettingsMaxValueParamTypeId) { + thing->setStateMaxValue(gasSensorGasLevelStateTypeId, value); + } + }); + } + if (thing->thingClassId() == lightSensorThingClassId) { + connect(thing, &Thing::settingChanged, thing, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ + if (settingTypeId == lightSensorSettingsMinLuxParamTypeId) { + thing->setStateMinValue(lightSensorLightIntensityStateTypeId, value); + } + if (settingTypeId == lightSensorSettingsMaxLuxParamTypeId) { + thing->setStateMaxValue(lightSensorLightIntensityStateTypeId, value); + } + }); + } if (thing->thingClassId() == waterLevelSensorThingClassId) { connect(thing, &Thing::settingChanged, thing, [ thing](const ParamTypeId &settingTypeId, const QVariant &value){ if (settingTypeId == waterLevelSensorSettingsCapacityParamTypeId) { @@ -68,12 +138,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Action action = info->action(); if (thing->thingClassId() == temperatureSensorThingClassId) { - if (action.actionTypeId() == temperatureSensorInputActionTypeId) { + if (action.actionTypeId() == temperatureSensorTemperatureActionTypeId) { + double value = info->action().param(temperatureSensorTemperatureActionTemperatureParamTypeId).value().toDouble(); + thing->setStateValue(temperatureSensorTemperatureStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == temperatureSensorInputActionTypeId) { double value = info->action().param(temperatureSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(temperatureSensorInputStateTypeId, value); - double min = info->thing()->setting(temperatureSensorSettingsMinTempParamTypeId).toDouble(); - double max = info->thing()->setting(temperatureSensorSettingsMaxTempParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 1, min, max); + double inputMin = info->thing()->setting(temperatureSensorSettingsMinInputParamTypeId).toDouble(); + double inputMax = info->thing()->setting(temperatureSensorSettingsMaxInputParamTypeId).toDouble(); + double tempMin = info->thing()->setting(temperatureSensorSettingsMinTempParamTypeId).toDouble(); + double tempMax = info->thing()->setting(temperatureSensorSettingsMaxTempParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, inputMin, inputMax, tempMin, tempMax); double roundingFactor = qPow(10, info->thing()->setting(temperatureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(temperatureSensorTemperatureStateTypeId, newValue); @@ -83,12 +160,17 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == humiditySensorThingClassId) { - if (action.actionTypeId() == humiditySensorInputActionTypeId) { + if (action.actionTypeId() == humiditySensorHumidityActionTypeId) { + double value = info->action().param(humiditySensorHumidityActionHumidityParamTypeId).value().toDouble(); + thing->setStateValue(humiditySensorHumidityStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == humiditySensorInputActionTypeId) { double value = info->action().param(humiditySensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(humiditySensorInputStateTypeId, value); - double min = info->thing()->setting(humiditySensorSettingsMinHumidityParamTypeId).toDouble(); - double max = info->thing()->setting(humiditySensorSettingsMaxHumidityParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double inputMin = info->thing()->setting(humiditySensorSettingsMinInputParamTypeId).toDouble(); + double inputMax = info->thing()->setting(humiditySensorSettingsMaxInputParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, inputMin, inputMax, 0, 100); double roundingFactor = qPow(10, info->thing()->setting(humiditySensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(humiditySensorHumidityStateTypeId, newValue); @@ -98,12 +180,17 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == moistureSensorThingClassId) { - if (action.actionTypeId() == moistureSensorInputActionTypeId) { + if (action.actionTypeId() == moistureSensorMoistureActionTypeId) { + double value = info->action().param(moistureSensorInputActionInputParamTypeId).value().toDouble(); + thing->setStateValue(moistureSensorMoistureStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == moistureSensorInputActionTypeId) { double value = info->action().param(moistureSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(moistureSensorInputStateTypeId, value); - double min = info->thing()->setting(moistureSensorSettingsMinMoistureParamTypeId).toDouble(); - double max = info->thing()->setting(moistureSensorSettingsMaxMoistureParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double inputMin = info->thing()->setting(moistureSensorSettingsMinInputParamTypeId).toDouble(); + double inputMax = info->thing()->setting(moistureSensorSettingsMaxInputParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, inputMin, inputMax, 0, 100); double roundingFactor = qPow(10, info->thing()->setting(moistureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(moistureSensorMoistureStateTypeId, newValue); @@ -113,7 +200,12 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == phSensorThingClassId) { - if (action.actionTypeId() == phSensorInputActionTypeId) { + if (action.actionTypeId() == phSensorPhActionTypeId) { + double value = info->action().paramValue(phSensorInputActionInputParamTypeId).toDouble(); + thing->setStateValue(phSensorPhStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == phSensorInputActionTypeId) { double value = info->action().paramValue(phSensorInputActionInputParamTypeId).toDouble(); thing->setStateValue(phSensorInputStateTypeId, value); double min = info->thing()->setting(phSensorSettingsMinInputParamTypeId).toDouble(); @@ -125,13 +217,21 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) info->finish(Thing::ThingErrorNoError); return; } + } else if (thing->thingClassId() == orpSensorThingClassId) { - if (action.actionTypeId() == orpSensorInputActionTypeId) { + if (action.actionTypeId() == orpSensorOrpActionTypeId) { + double value = info->action().paramValue(orpSensorInputActionInputParamTypeId).toDouble(); + thing->setStateValue(orpSensorOrpStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == orpSensorInputActionTypeId) { double value = info->action().paramValue(orpSensorInputActionInputParamTypeId).toDouble(); thing->setStateValue(orpSensorInputStateTypeId, value); - double min = info->thing()->setting(orpSensorSettingsMinORPParamTypeId).toDouble(); - double max = info->thing()->setting(orpSensorSettingsMaxORPParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(orpSensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(orpSensorSettingsMaxInputParamTypeId).toDouble(); + double minOrp = info->thing()->setting(orpSensorSettingsMinORPParamTypeId).toDouble(); + double maxOrp = info->thing()->setting(orpSensorSettingsMaxORPParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minOrp, maxOrp); double roundingFactor = qPow(10, info->thing()->setting(orpSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(orpSensorOrpStateTypeId, newValue); @@ -139,12 +239,17 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) return; } } else if (thing->thingClassId() == o2SensorThingClassId) { - if (action.actionTypeId() == o2SensorInputActionTypeId) { + if (action.actionTypeId() == o2SensorO2saturationActionTypeId) { + double value = info->action().paramValue(o2SensorO2saturationActionO2saturationParamTypeId).toDouble(); + thing->setStateValue(o2SensorO2saturationStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == o2SensorInputActionTypeId) { double value = info->action().paramValue(o2SensorInputActionInputParamTypeId).toDouble(); thing->setStateValue(o2SensorInputStateTypeId, value); - double min = info->thing()->setting(o2SensorSettingsMinInputParamTypeId).toDouble(); - double max = info->thing()->setting(o2SensorSettingsMaxInputParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, min, max, 0, 100); + double minInput = info->thing()->setting(o2SensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(o2SensorSettingsMaxInputParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, 0, 100); double roundingFactor = qPow(10, info->thing()->setting(o2SensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(o2SensorO2saturationStateTypeId, newValue); @@ -152,12 +257,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) return; } } else if (thing->thingClassId() == pressureSensorThingClassId) { - if (action.actionTypeId() == pressureSensorInputActionTypeId) { + if (action.actionTypeId() == pressureSensorPressureActionTypeId) { + double value = info->action().param(pressureSensorPressureActionPressureParamTypeId).value().toDouble(); + thing->setStateValue(pressureSensorPressureStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == pressureSensorInputActionTypeId) { double value = info->action().param(pressureSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(pressureSensorInputStateTypeId, value); - double min = info->thing()->setting(pressureSensorSettingsMinPressureParamTypeId).toDouble(); - double max = info->thing()->setting(pressureSensorSettingsMaxPressureParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(pressureSensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(pressureSensorSettingsMaxInputParamTypeId).toDouble(); + double minPressure = info->thing()->setting(pressureSensorSettingsMinPressureParamTypeId).toDouble(); + double maxPressure = info->thing()->setting(pressureSensorSettingsMaxPressureParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minPressure, maxPressure); double roundingFactor = qPow(10, info->thing()->setting(pressureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(pressureSensorPressureStateTypeId, newValue); @@ -167,12 +279,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == coSensorThingClassId) { - if (action.actionTypeId() == coSensorInputActionTypeId) { + if (action.actionTypeId() == coSensorCoActionTypeId) { + double value = info->action().param(coSensorCoActionCoParamTypeId).value().toDouble(); + thing->setStateValue(coSensorCoStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == coSensorInputActionTypeId) { double value = info->action().param(coSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(coSensorInputStateTypeId, value); - double min = info->thing()->setting(coSensorSettingsMinCOParamTypeId).toDouble(); - double max = info->thing()->setting(coSensorSettingsMaxCOParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(coSensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(coSensorSettingsMaxInputParamTypeId).toDouble(); + double minCo = info->thing()->setting(coSensorSettingsMinCOParamTypeId).toDouble(); + double maxCo = info->thing()->setting(coSensorSettingsMaxCOParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minCo, maxCo); double roundingFactor = qPow(10, info->thing()->setting(coSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(coSensorCoStateTypeId, newValue); @@ -182,12 +301,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == co2SensorThingClassId) { - if (action.actionTypeId() == co2SensorInputActionTypeId) { + if (action.actionTypeId() == co2SensorCo2ActionTypeId) { + double value = info->action().param(co2SensorCo2ActionCo2ParamTypeId).value().toDouble(); + thing->setStateValue(co2SensorCo2StateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == co2SensorInputActionTypeId) { double value = info->action().param(co2SensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(co2SensorInputStateTypeId, value); - double min = info->thing()->setting(co2SensorSettingsMinCO2ParamTypeId).toDouble(); - double max = info->thing()->setting(co2SensorSettingsMaxCO2ParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(co2SensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(co2SensorSettingsMaxInputParamTypeId).toDouble(); + double minCo2 = info->thing()->setting(co2SensorSettingsMinCO2ParamTypeId).toDouble(); + double maxCo2 = info->thing()->setting(co2SensorSettingsMaxCO2ParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minCo2, maxCo2); double roundingFactor = qPow(10, info->thing()->setting(co2SensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(co2SensorCo2StateTypeId, newValue); @@ -197,12 +323,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == gasSensorThingClassId) { - if (action.actionTypeId() == gasSensorInputActionTypeId) { + if (action.actionTypeId() == gasSensorGasLevelActionTypeId) { + double value = info->action().param(gasSensorGasLevelActionGasLevelParamTypeId).value().toDouble(); + thing->setStateValue(gasSensorGasLevelStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == gasSensorInputActionTypeId) { double value = info->action().param(gasSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(gasSensorInputStateTypeId, value); - double min = info->thing()->setting(gasSensorSettingsMinValueParamTypeId).toDouble(); - double max = info->thing()->setting(gasSensorSettingsMaxValueParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(gasSensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(gasSensorSettingsMaxInputParamTypeId).toDouble(); + double minValue = info->thing()->setting(gasSensorSettingsMinValueParamTypeId).toDouble(); + double maxValue = info->thing()->setting(gasSensorSettingsMaxValueParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minValue, maxValue); double roundingFactor = qPow(10, info->thing()->setting(gasSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(gasSensorGasLevelStateTypeId, newValue); @@ -212,12 +345,19 @@ void IntegrationPluginGenericSensors::executeAction(ThingActionInfo *info) Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == lightSensorThingClassId) { - if (action.actionTypeId() == lightSensorInputActionTypeId) { + if (action.actionTypeId() == lightSensorLightIntensityStateTypeId) { + double value = info->action().param(lightSensorLightIntensityStateTypeId).value().toDouble(); + thing->setStateValue(lightSensorLightIntensityStateTypeId, value); + info->finish(Thing::ThingErrorNoError); + return; + } else if (action.actionTypeId() == lightSensorInputActionTypeId) { double value = info->action().param(lightSensorInputActionInputParamTypeId).value().toDouble(); thing->setStateValue(lightSensorInputStateTypeId, value); - double min = info->thing()->setting(lightSensorSettingsMinLuxParamTypeId).toDouble(); - double max = info->thing()->setting(lightSensorSettingsMaxLuxParamTypeId).toDouble(); - double newValue = mapDoubleValue(value, 0, 100, min, max); + double minInput = info->thing()->setting(lightSensorSettingsMinInputParamTypeId).toDouble(); + double maxInput = info->thing()->setting(lightSensorSettingsMaxInputParamTypeId).toDouble(); + double minValue = info->thing()->setting(lightSensorSettingsMinLuxParamTypeId).toDouble(); + double maxValue = info->thing()->setting(lightSensorSettingsMaxLuxParamTypeId).toDouble(); + double newValue = mapDoubleValue(value, minInput, maxInput, minValue, maxValue); double roundingFactor = qPow(10, info->thing()->setting(lightSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(lightSensorLightIntensityStateTypeId, newValue); diff --git a/genericsensors/integrationplugingenericsensors.json b/genericsensors/integrationplugingenericsensors.json index 4e1aeb6..851b7f7 100644 --- a/genericsensors/integrationplugingenericsensors.json +++ b/genericsensors/integrationplugingenericsensors.json @@ -20,16 +20,34 @@ "name": "minTemp", "displayName": "Minimum temperature", "type": "double", - "defaultValue": -20, - "unit": "DegreeCelsius" + "unit": "DegreeCelsius", + "defaultValue": -20 }, { "id": "8b5947ab-127f-4995-853b-eeeb628811e3", "name": "maxTemp", "displayName": "Maximum temperature", "type": "double", - "defaultValue": 50, - "unit": "DegreeCelsius" + "unit": "DegreeCelsius", + "defaultValue": 50 + }, + { + "id": "603e0c4e-4757-4ac0-8345-ba7a1aaf5503", + "name": "minInput", + "displayName": "Minimum input (0 - 1)", + "type": "double", + "minValue": -1, + "maxValue": 1, + "defaultValue": 0 + }, + { + "id": "1ea78589-f787-4aa5-bb1a-90cd73a14386", + "name": "maxInput", + "displayName": "Maximum input (0 - 1)", + "type": "double", + "minValue": 0, + "maxValue": 2, + "defaultValue": 1 }, { "id": "3b543c3a-1fc0-45b5-8c07-600a6045f82e", @@ -46,16 +64,18 @@ "id": "d0b6c4be-339e-4b0f-a234-0611b7565395", "name": "temperature", "displayName": "Temperature", - "displayNameEvent": "Temperature changed", + "displayNameAction": "Set temperature", "type": "double", "unit": "DegreeCelsius", - "defaultValue": 0 + "minValue": -20, + "maxValue": 50, + "defaultValue": 0, + "writable": true }, { "id": "fed37466-1264-4ac1-84fd-aff3a1f7ff04", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", "defaultValue": 0, @@ -75,19 +95,23 @@ "settingsTypes": [ { "id": "0218ffa9-3d49-4b25-a59f-c8831f190432", - "name": "minHumidity", - "displayName": "Minimum humidity", + "name": "minInput", + "displayName": "Minimum input", "type": "double", - "defaultValue": 0, - "unit": "Percentage" + "unit": "Percentage", + "minValue": -100, + "maxValue": 100, + "defaultValue": 0 }, { "id": "10afc387-68d1-47ea-a816-0d1acad47b3c", - "name": "maxHumidity", - "displayName": "Maximum humidity", + "name": "maxInput", + "displayName": "Maximum input", "type": "double", - "defaultValue": 100, - "unit": "Percentage" + "unit": "Percentage", + "minValue": 0, + "maxValue": 200, + "defaultValue": 100 }, { "id": "38064841-6121-4862-a639-08fb0b778511", @@ -104,18 +128,18 @@ "id": "925225d9-2965-444a-9c42-63c2873700fb", "name": "humidity", "displayName": "Humidity", - "displayNameEvent": "Humidity changed", + "displayNameAction": "Set humidity", "type": "double", "unit": "Percentage", "defaultValue": 0, "minValue": 0, - "maxValue": 100 + "maxValue": 100, + "writable": true }, { "id": "a8223e65-e704-4f84-9bbe-d8fc42597047", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", "defaultValue": 0, @@ -135,19 +159,23 @@ "settingsTypes": [ { "id": "32153786-f1ae-4aa4-a84c-b9054102eb92", - "name": "minMoisture", - "displayName": "Minimum moisture", + "name": "minInput", + "displayName": "Minimum input", "type": "double", - "defaultValue": 0, - "unit": "Percentage" + "unit": "Percentage", + "minValue": -100, + "maxValue": 100, + "defaultValue": 0 }, { "id": "3426817d-065e-4cfc-aa21-bb434de684d6", - "name": "maxMoisture", - "displayName": "Maximum moisture", + "name": "maxInput", + "displayName": "Maximum input", "type": "double", - "defaultValue": 100, - "unit": "Percentage" + "unit": "Percentage", + "minValue": 0, + "maxValue": 200, + "defaultValue": 100 }, { "id": "3c967a68-9951-4c9a-b019-79b913e762b6", @@ -164,12 +192,13 @@ "id": "7a62e1d2-92f2-424c-876c-870478a4b2bd", "name": "moisture", "displayName": "Soil moisture", - "displayNameEvent": "Soil moisture changed", + "displayNameAction": "Set soil moisture", "type": "double", "unit": "Percentage", "minValue": 0, "maxValue": 100, - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "ce64a425-d990-4fc1-966b-be6de445792b", @@ -196,15 +225,21 @@ { "id": "a8ff2e16-e06c-4b1e-839a-a06691a12d64", "name": "minInput", - "displayName": "Minimum input value", + "displayName": "Minimum input", "type": "double", + "unit": "Percentage", + "minValue": -100, + "maxValue": 100, "defaultValue": 0 }, { "id": "a8889e45-59e5-4cc4-b228-611f8f19f531", "name": "maxInput", - "displayName": "Maximum input value", + "displayName": "Maximum input", "type": "double", + "unit": "Percentage", + "minValue": 0, + "maxValue": 200, "defaultValue": 100 }, { @@ -222,22 +257,23 @@ "id": "743514b1-8018-4525-b87a-c5f414146ff2", "name": "ph", "displayName": "PH", - "displayNameEvent": "PH changed", + "displayNameAction": "Set PH", "type": "double", "defaultValue": 7, "minValue": 0, - "maxValue": 14 + "maxValue": 14, + "writable": true }, { "id": "614a039b-9ed9-4b62-9c74-01ba4ac42f16", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", + "unit": "Percentage", "minValue": 0, - "defaultValue": 50, "maxValue": 100, + "defaultValue": 50, "ioType": "analogOutput", "writable": true } @@ -253,17 +289,37 @@ { "id": "396bf3f9-a3fc-44c3-90f8-b316670116a7", "name": "minORP", - "displayName": "Minimum input value", + "displayName": "Minimum ORP value", "type": "double", "defaultValue": -1500 }, { "id": "bd0774c9-1b89-49ce-b0f8-66ff26ca10db", "name": "maxORP", - "displayName": "Maximum input ORP value", + "displayName": "Maximum ORP value", "type": "double", "defaultValue": 1500 }, + { + "id": "a4776e88-80e1-4ab0-8140-2c00a79b406b", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 0 + }, + { + "id": "4a78f063-3b3a-423e-bd73-f3c85de1b511", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", + "defaultValue": 100 + }, { "id": "1f218ad8-652a-4bda-987d-3e183ff040b2", "name": "accuracy", @@ -279,18 +335,18 @@ "id": "e5ed3535-2e5d-412e-85f8-782cbccd7731", "name": "orp", "displayName": "ORP", - "displayNameEvent": "ORP changed", + "displayNameAction": "Set ORP", "type": "double", "unit": "MilliVolt", "defaultValue": 0, "minValue": -1500, - "maxValue": 1500 + "maxValue": 1500, + "writable": true }, { "id": "020ff04f-a157-4925-9c55-2b45389208fc", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", "minValue": 0, @@ -311,15 +367,21 @@ { "id": "58e84041-d451-44a2-972e-13a79b449b58", "name": "minInput", - "displayName": "Minimum input value", + "displayName": "Minimum input", "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", "defaultValue": 0 }, { "id": "198847f6-a188-42b0-9e0b-15587eaabbed", "name": "maxInput", - "displayName": "Maximum input value", + "displayName": "Maximum input", "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", "defaultValue": 100 }, { @@ -337,23 +399,24 @@ "id": "a3ff7641-87d9-4b07-b8e5-e6aa92b90088", "name": "o2saturation", "displayName": "O2 saturation", - "displayNameEvent": "O2 saturation changed", + "displayNameAction": "Set O2 saturation", "type": "double", "unit": "Percentage", "defaultValue": 0, "minValue": 0, - "maxValue": 100 + "maxValue": 100, + "writable": true }, { "id": "7e74fca7-84d0-4f3e-9f26-4232b7b9f507", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", "minValue": 0, - "defaultValue": 0, "maxValue": 100, + "defaultValue": 0, + "unit": "Percentage", "ioType": "analogOutput", "writable": true } @@ -371,16 +434,36 @@ "name": "minPressure", "displayName": "Minimum pressure", "type": "double", - "defaultValue": 0, - "unit": "MilliBar" + "unit": "MilliBar", + "defaultValue": 0 }, { "id": "06e21251-8b4f-44a1-8504-6b51f8526bd0", "name": "maxPressure", "displayName": "Maximum pressure", "type": "double", - "defaultValue": 2000, - "unit": "MilliBar" + "unit": "MilliBar", + "defaultValue": 2000 + }, + { + "id": "58487871-e128-4f09-9412-3433574fb62d", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "unit": "Percentage", + "minValue": 0, + "maxValue": 100, + "defaultValue": 0 + }, + { + "id": "21109465-d53c-4c69-b9a8-7f1c41e823b2", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "unit": "Percentage", + "minValue": 0, + "maxValue": 100, + "defaultValue": 100 }, { "id": "021a17d8-9e5e-4dd6-835d-1a3e1ffd6b23", @@ -397,10 +480,13 @@ "id": "e645a979-1465-4592-b8b0-f4c123db0800", "name": "pressure", "displayName": "Pressure", - "displayNameEvent": "Pressure changed", + "displayNameAction": "Set pressure", "type": "double", + "minValue": 0, + "maxValue": 2000, "unit": "MilliBar", - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "c320577c-371a-442b-ac80-b692ff2064c9", @@ -430,16 +516,37 @@ "name": "minCO", "displayName": "Minimum CO", "type": "double", - "defaultValue": 0, - "unit": "PartsPerMillion" + "unit": "PartsPerMillion", + "minValue": 0, + "defaultValue": 0 }, { "id": "e9def195-1b67-4a1b-8030-cbbc6209d52e", "name": "maxCO", "displayName": "Maximum CO", "type": "double", - "defaultValue": 255, - "unit": "PartsPerMillion" + "unit": "PartsPerMillion", + "defaultValue": 255 + }, + { + "id": "d4784dde-aa9a-4be4-a16c-592373760dc8", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 0 + }, + { + "id": "c6d9d5f4-d3d0-4284-ab82-e93cc2c30e21", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", + "defaultValue": 100 }, { "id": "9c8a9553-7b68-4b58-a8f1-3c6b591998c0", @@ -456,20 +563,21 @@ "id": "9eebe9d2-b34b-4847-bc25-109e2b8cab24", "name": "co", "displayName": "CO level", - "displayNameEvent": "CO level changed", + "displayNameAction": "Set CO level", "type": "double", "minValue": 0, "maxValue": "255", "unit": "PartsPerMillion", - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "cf3ec5ec-7098-47c5-9666-b3c52eba1b1d", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", + "unit": "Percentage", "defaultValue": 0, "minValue": 0, "maxValue": 100, @@ -490,16 +598,36 @@ "name": "minCO2", "displayName": "Minimum CO2", "type": "double", - "defaultValue": 0, - "unit": "PartsPerMillion" + "unit": "PartsPerMillion", + "defaultValue": 0 }, { "id": "a3029bee-8b13-4aed-8ebd-eaceb603f8ef", "name": "maxCO2", "displayName": "Maximum CO2", "type": "double", - "defaultValue": 2000, - "unit": "PartsPerMillion" + "unit": "PartsPerMillion", + "defaultValue": 2000 + }, + { + "id": "67e6b107-826a-48bc-9bd9-144d9b73a778", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 0 + }, + { + "id": "b79dca8c-cd73-4429-8a01-c194b2c43ea2", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", + "defaultValue": 100 }, { "id": "236831a8-a455-4e38-a9cd-eabbebaa3f67", @@ -516,11 +644,13 @@ "id": "755c4c7f-093e-41dd-a38d-9ee18c9890d6", "name": "co2", "displayName": "CO2", + "displayNameAction": "Set CO2", "type": "double", "unit": "PartsPerMillion", "minValue": 0, "maxValue": 2000, - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "7dc765f8-fa9b-4199-8f21-49ed452f226d", @@ -528,6 +658,7 @@ "displayName": "Input value", "displayNameAction": "Set input value", "type": "double", + "unit": "Percentage", "defaultValue": 0, "minValue": 0, "maxValue": 100, @@ -559,6 +690,26 @@ "defaultValue": 10000, "unit": "PartsPerMillion" }, + { + "id": "6fbb8fe6-4ac1-4ad5-9621-7a786b632225", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 0 + }, + { + "id": "93827b27-8dba-40d9-b3fa-dde42bfcbcbc", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", + "defaultValue": 100 + }, { "id": "1c7465b1-490d-43db-bb67-a179a6923a57", "name": "accuracy", @@ -574,18 +725,21 @@ "id": "5135648f-57b7-44b0-b9d0-c5accad09356", "name": "gasLevel", "displayName": "Gas level", - "displayNameEvent": "Gas level changed", + "displayNameAction": "Set gas level", "type": "double", + "minValue": 0, + "maxValue": 10000, "unit": "PartsPerMillion", - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "e3eb500a-ac00-426c-932a-dee4fd6fbcf5", "name": "input", "displayName": "Input value", - "displayNameEvent": "Input value changed", "displayNameAction": "Set input value", "type": "double", + "unit": "Percentage", "defaultValue": 0, "minValue": 0, "maxValue": 100, @@ -617,6 +771,26 @@ "defaultValue": 120000, "unit": "Lux" }, + { + "id": "72e0244a-97e0-473b-94ac-94014c488c08", + "name": "minInput", + "displayName": "Minimum input", + "type": "double", + "minValue": -100, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 0 + }, + { + "id": "265bf736-7d60-4361-98fb-83b11c277d87", + "name": "maxInput", + "displayName": "Maximum input", + "type": "double", + "minValue": 0, + "maxValue": 200, + "unit": "Percentage", + "defaultValue": 100 + }, { "id": "f800988f-1ad5-4ffb-9aa8-70ef17614966", "name": "accuracy", @@ -632,10 +806,11 @@ "id": "fe12ef32-9f2f-41cd-acb7-6b8e4acffa3b", "name": "lightIntensity", "displayName": "Light intensity", - "displayNameEvent": "Light intensity changed", + "displayNameAction": "Set light intensity", "type": "double", "unit": "Lux", - "defaultValue": 0 + "defaultValue": 0, + "writable": true }, { "id": "520e5d27-7d15-4d79-94cf-5d01f5a09ea8", @@ -714,6 +889,8 @@ "name": "minInputValue", "displayName": "Minimum input value", "type": "double", + "minValue": -1, + "maxValue": 1, "defaultValue": 0 }, { @@ -721,6 +898,8 @@ "name": "maxInputValue", "displayName": "Maximum input value", "type": "double", + "minValue": 0, + "maxValue": 2, "defaultValue": 1 } ],