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
fix-thermostat-min-max-settings
Michael Zanetti 2023-01-01 19:39:43 +01:00
parent d159cdb332
commit cd09f19060
4 changed files with 487 additions and 116 deletions

View File

@ -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();

View File

@ -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"
}
```

View File

@ -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);

View File

@ -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
}
],