/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2020, nymea GmbH * Contact: contact@nymea.io * This file is part of nymea. * This project including source code and documentation is protected by * copyright law, and remains the property of nymea GmbH. All rights, including * reproduction, publication, editing and translation, are reserved. The use of * this project is subject to the terms of a license agreement to be concluded * with nymea GmbH in accordance with the terms of use of nymea GmbH, available * under https://nymea.io/license * * GNU Lesser General Public License Usage * Alternatively, this project may be redistributed and/or modified under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; version 3. This project is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this project. If not, see . * * For any further details and any questions please contact us under * contact@nymea.io or see our FAQ/Licensing Information on * https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "integrationplugingenericthings.h" #include "plugininfo.h" #include #include IntegrationPluginGenericThings::IntegrationPluginGenericThings() { } void IntegrationPluginGenericThings::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); if (thing->thingClassId() == extendedBlindThingClassId) { uint closingDuration = thing->setting(extendedBlindSettingsClosingDurationParamTypeId).toUInt(); QTimer* timer = new QTimer(this); timer->setInterval(closingDuration/100.00); // closing timer / 100 to update on every percent m_extendedBlindPercentageTimer.insert(thing, timer); connect(thing, &Thing::settingChanged, thing, [timer] (const ParamTypeId ¶mTypeId, const QVariant &value) { if (paramTypeId == extendedBlindSettingsClosingDurationParamTypeId) { timer->setInterval(value.toUInt()/100.00); } }); connect(timer, &QTimer::timeout, this, [thing, this] { uint currentPercentage = thing->stateValue(extendedBlindPercentageStateTypeId).toUInt(); if (thing->stateValue(extendedBlindStatusStateTypeId).toString() == "Closing") { if (currentPercentage == 100) { setBlindState(BlindStateStopped, thing); qCDebug(dcGenericThings()) << "Extended blind is closed, stopping timer"; } else { currentPercentage++; thing->setStateValue(extendedBlindPercentageStateTypeId, currentPercentage); } } else if (thing->stateValue(extendedBlindStatusStateTypeId).toString() == "Opening") { if (currentPercentage == 0) { setBlindState(BlindStateStopped, thing); qCDebug(dcGenericThings()) << "Extended blind is opened, stopping timer"; } else { currentPercentage--; thing->setStateValue(extendedBlindPercentageStateTypeId, currentPercentage); } } else { setBlindState(BlindStateStopped, thing); } if (m_extendedBlindPercentageTimer.contains(thing)) { uint targetPercentage = m_extendedBlindTargetPercentage.value(thing); if (targetPercentage == currentPercentage) { qCDebug(dcGenericThings()) << "Extended blind has reached target percentage, stopping timer"; setBlindState(BlindStateStopped, thing); } } }); } else if (info->thing()->thingClassId() == venetianBlindThingClassId) { uint closingTime = thing->setting(venetianBlindSettingsClosingDurationParamTypeId).toUInt(); uint angleTime = thing->setting(venetianBlindSettingsAngleTimeParamTypeId).toUInt(); if (closingTime < angleTime) { return info->finish(Thing::ThingErrorSetupFailed, tr("Invalid closing or angle time")); } QTimer* closingTimer = new QTimer(this); closingTimer->setInterval(closingTime/100.00); // closing timer / 100 to update on every percent m_extendedBlindPercentageTimer.insert(thing, closingTimer); connect(closingTimer, &QTimer::timeout, thing, [thing, this] { uint currentPercentage = thing->stateValue(venetianBlindPercentageStateTypeId).toUInt(); if (thing->stateValue(venetianBlindStatusStateTypeId).toString() == "Closing") { if (currentPercentage == 100) { setBlindState(BlindStateStopped, thing); qCDebug(dcGenericThings()) << "Venetian blind is closed, stopping timer"; } else if (currentPercentage > 100) { currentPercentage = 100; setBlindState(BlindStateStopped, thing); qCWarning(dcGenericThings()) << "Venetian blind overshoot 100 percent"; } else { currentPercentage++; thing->setStateValue(venetianBlindPercentageStateTypeId, currentPercentage); } } else if (thing->stateValue(venetianBlindStatusStateTypeId).toString() == "Opening") { if (currentPercentage == 0) { setBlindState(BlindStateStopped, thing); qCDebug(dcGenericThings()) << "Venetian blind is opened, stopping timer"; } else { currentPercentage--; thing->setStateValue(venetianBlindPercentageStateTypeId, currentPercentage); } } else { setBlindState(BlindStateStopped, thing); } if (m_extendedBlindPercentageTimer.contains(thing)) { uint targetPercentage = m_extendedBlindTargetPercentage.value(thing); if (targetPercentage == currentPercentage) { qCDebug(dcGenericThings()) << "Venetian blind has reached target percentage, stopping timer"; setBlindState(BlindStateStopped, thing); } } }); QTimer* angleTimer = new QTimer(this); angleTimer->setInterval(angleTime/180.00); // -90 to 90 degree -> 180 degree total m_venetianBlindAngleTimer.insert(thing, angleTimer); connect(thing, &Thing::settingChanged, thing, [closingTimer, angleTimer] (const ParamTypeId ¶mTypeId, const QVariant &value) { if (paramTypeId == venetianBlindSettingsClosingDurationParamTypeId) { closingTimer->setInterval(value.toUInt()/100.00); } else if (paramTypeId == venetianBlindSettingsAngleTimeParamTypeId) { angleTimer->setInterval(value.toUInt()/180.00); } }); connect(angleTimer, &QTimer::timeout, thing, [thing, this] { int currentAngle = thing->stateValue(venetianBlindAngleStateTypeId).toInt(); if (thing->stateValue(venetianBlindStatusStateTypeId).toString() == "Closing") { if (currentAngle < 90) { currentAngle++; } else if (currentAngle == 90) { m_venetianBlindAngleTimer.value(thing)->stop(); } else if (currentAngle > 90) { currentAngle = 90; m_venetianBlindAngleTimer.value(thing)->stop(); qCWarning(dcGenericThings()) << "Venetian blind overshoot angle boundaries"; } thing->setStateValue(venetianBlindAngleStateTypeId, currentAngle); } else if (thing->stateValue(venetianBlindStatusStateTypeId).toString() == "Opening") { if (currentAngle > -90) { currentAngle--; } else if (currentAngle == -90) { m_venetianBlindAngleTimer.value(thing)->stop(); } else if (currentAngle < -90) { currentAngle = -90; m_venetianBlindAngleTimer.value(thing)->stop(); qCWarning(dcGenericThings()) << "Venetian blind overshoot angle boundaries"; } thing->setStateValue(venetianBlindAngleStateTypeId, currentAngle); } if (m_venetianBlindTargetAngle.contains(thing)) { int targetAngle = m_venetianBlindTargetAngle.value(thing); if (targetAngle == currentAngle) { qCDebug(dcGenericThings()) << "Venetian blind has reached target angle, stopping timer"; setBlindState(BlindStateStopped, thing); } } }); } else if (thing->thingClassId() == smartMeterThingClassId) { QTimer* smartMeterTimer = new QTimer(this); int timeframe = thing->setting(smartMeterSettingsImpulseTimeframeParamTypeId).toInt(); smartMeterTimer->setInterval(timeframe * 1000); m_smartMeterTimer.insert(thing, smartMeterTimer); smartMeterTimer->start(); connect(thing, &Thing::settingChanged, smartMeterTimer, [smartMeterTimer] (const ParamTypeId ¶mTypeId, const QVariant &value) { if (paramTypeId == smartMeterSettingsImpulseTimeframeParamTypeId) { smartMeterTimer->setInterval(value.toInt() * 1000); } }); connect(smartMeterTimer, &QTimer::timeout, thing, [this, smartMeterTimer, thing] { double impulsePerKwh = thing->setting(smartMeterSettingsImpulsePerKwhParamTypeId).toDouble(); int interval = smartMeterTimer->interval()/1000; double power = (m_pulsesPerTimeframe.value(thing)/impulsePerKwh)/(interval/3600.00); // Power = Energy/Time; Energy = Impulses/ImpPerkWh thing->setStateValue(smartMeterCurrentPowerStateTypeId, power*1000); m_pulsesPerTimeframe.insert(thing, 0); }); } else if (thing->thingClassId() == extendedStatefulGaragedoorThingClassId) { uint openingDuration = thing->setting(extendedStatefulGaragedoorSettingsOpeningDurationParamTypeId).toUInt(); QTimer* timer = new QTimer(this); timer->setInterval(openingDuration/100.00); // closing timer / 100 to update on every percent m_statefulGaragePercentageTimer.insert(thing, timer); connect(thing, &Thing::settingChanged, thing, [timer] (const ParamTypeId ¶mTypeId, const QVariant &value) { if (paramTypeId == extendedStatefulGaragedoorSettingsOpeningDurationParamTypeId) { timer->setInterval(value.toUInt()/100.00); } }); connect(timer, &QTimer::timeout, this, [thing, timer, this] { uint currentPercentage = thing->stateValue(extendedStatefulGaragedoorPercentageStateTypeId).toUInt(); uint targetPercentage = m_statefulGarageTargetPercentage.value(thing); if (currentPercentage < targetPercentage) { currentPercentage++; thing->setStateValue(extendedStatefulGaragedoorPercentageStateTypeId, currentPercentage); thing->setStateValue(extendedStatefulGaragedoorStateStateTypeId, "closing"); thing->setStateValue(extendedStatefulGaragedoorMovingStateTypeId, true); thing->setStateValue(extendedStatefulGaragedoorOpeningOutputStateTypeId, false); thing->setStateValue(extendedStatefulGaragedoorClosingOutputStateTypeId, true); } else if (currentPercentage > targetPercentage) { currentPercentage--; thing->setStateValue(extendedStatefulGaragedoorPercentageStateTypeId, currentPercentage); thing->setStateValue(extendedStatefulGaragedoorStateStateTypeId, "opening"); thing->setStateValue(extendedStatefulGaragedoorMovingStateTypeId, true); thing->setStateValue(extendedStatefulGaragedoorOpeningOutputStateTypeId, true); thing->setStateValue(extendedStatefulGaragedoorClosingOutputStateTypeId, false); } if (currentPercentage == targetPercentage){ QString state = currentPercentage == 100 ? "open" : currentPercentage == 0 ? "closed" : "intermediate"; thing->setStateValue(extendedStatefulGaragedoorStateStateTypeId, state); thing->setStateValue(extendedStatefulGaragedoorMovingStateTypeId, false); thing->setStateValue(extendedStatefulGaragedoorOpeningOutputStateTypeId, false); thing->setStateValue(extendedStatefulGaragedoorClosingOutputStateTypeId, false); qCDebug(dcGenericThings()) << "Stopping garage timer"; timer->stop(); } }); } else if (thing->thingClassId() == thermostatThingClassId) { thermostatCheckPowerOutputState(thing); // check the initial values connect(thing, &Thing::settingChanged, thing, [this, thing] (const ParamTypeId ¶mTypeId, const QVariant &value) { Q_UNUSED(value) if (paramTypeId == thermostatSettingsTemperatureDifferenceParamTypeId) { thermostatCheckPowerOutputState(thing); } }); } else if (thing->thingClassId() == sgReadyThingClassId) { bool relay1 = thing->stateValue(sgReadyRelay1StateTypeId).toBool(); bool relay2 = thing->stateValue(sgReadyRelay2StateTypeId).toBool(); int operatingMode = sgReadyOperatingMode(relay1, relay2); thing->setStateValue(sgReadyOperatingModeStateTypeId, operatingMode); thing->setStateValue(sgReadyOperatingModeDescriptionStateTypeId, sgReadyOperatingModeDescription(operatingMode)); } else if (thing->thingClassId() == batteryThingClassId) { connect(thing, &Thing::settingChanged, [thing](const ParamTypeId &settingTypeId, const QVariant &value){ if (settingTypeId == batterySettingsCriticalLevelParamTypeId) { int currentBatteryLevel = thing->stateValue(batteryBatteryLevelStateTypeId).toInt(); thing->setStateValue(batteryBatteryCriticalStateTypeId, currentBatteryLevel <= value.toInt()); } }); } info->finish(Thing::ThingErrorNoError); } void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info) { Thing *thing = info->thing(); Action action = info->action(); if (thing->thingClassId() == genericThingClassId) { if (action.actionTypeId() == genericAnalogInputActionTypeId) { thing->setStateValue(genericAnalogInputStateTypeId, action.paramValue(genericAnalogInputActionAnalogInputParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == genericAnalogOutputActionTypeId) { thing->setStateValue(genericAnalogOutputStateTypeId, action.paramValue(genericAnalogOutputActionAnalogOutputParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == genericDigitalInputActionTypeId) { thing->setStateValue(genericDigitalInputStateTypeId, action.paramValue(genericDigitalInputActionDigitalInputParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == genericDigitalOutputActionTypeId) { thing->setStateValue(genericDigitalOutputStateTypeId, action.paramValue(genericDigitalOutputActionDigitalOutputParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == genericStringStateActionTypeId) { thing->setStateValue(genericStringStateStateTypeId, action.paramValue(genericStringStateActionStringStateParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } } if (thing->thingClassId() == awningThingClassId) { if (action.actionTypeId() == awningOpenActionTypeId) { thing->setStateValue(awningStatusStateTypeId, "Opening"); thing->setStateValue(awningClosingOutputStateTypeId, false); thing->setStateValue(awningOpeningOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == awningStopActionTypeId) { thing->setStateValue(awningStatusStateTypeId, "Stopped"); thing->setStateValue(awningOpeningOutputStateTypeId, false); thing->setStateValue(awningClosingOutputStateTypeId, false); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == awningCloseActionTypeId) { thing->setStateValue(awningStatusStateTypeId, "Closing"); thing->setStateValue(awningOpeningOutputStateTypeId, false); thing->setStateValue(awningClosingOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == awningOpeningOutputActionTypeId) { bool on = action.param(awningOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); thing->setStateValue(awningOpeningOutputStateTypeId, on); if (on) { thing->setStateValue(awningStatusStateTypeId, "Opening"); thing->setStateValue(awningClosingOutputStateTypeId, false); } else { thing->setStateValue(awningStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == awningClosingOutputActionTypeId) { bool on = action.param(awningClosingOutputActionClosingOutputParamTypeId).value().toBool(); thing->setStateValue(awningClosingOutputStateTypeId, on); if (on) { thing->setStateValue(awningStatusStateTypeId, "Closing"); thing->setStateValue(awningOpeningOutputStateTypeId, false); } else { thing->setStateValue(awningStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == blindThingClassId ) { if (action.actionTypeId() == blindOpenActionTypeId) { thing->setStateValue(blindStatusStateTypeId, "Opening"); thing->setStateValue(blindClosingOutputStateTypeId, false); thing->setStateValue(blindOpeningOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == blindStopActionTypeId) { thing->setStateValue(blindStatusStateTypeId, "Stopped"); thing->setStateValue(blindOpeningOutputStateTypeId, false); thing->setStateValue(blindClosingOutputStateTypeId, false); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == blindCloseActionTypeId) { thing->setStateValue(blindStatusStateTypeId, "Closing"); thing->setStateValue(blindOpeningOutputStateTypeId, false); thing->setStateValue(blindClosingOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == blindOpeningOutputActionTypeId) { bool on = action.param(blindOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); thing->setStateValue(blindOpeningOutputStateTypeId, on); if (on) { thing->setStateValue(blindStatusStateTypeId, "Opening"); thing->setStateValue(blindClosingOutputStateTypeId, false); } else { thing->setStateValue(blindStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == blindClosingOutputActionTypeId) { bool on = action.param(blindClosingOutputActionClosingOutputParamTypeId).value().toBool(); thing->setStateValue(blindClosingOutputStateTypeId, on); if (on) { thing->setStateValue(blindStatusStateTypeId, "Closing"); thing->setStateValue(blindOpeningOutputStateTypeId, false); } else { thing->setStateValue(blindStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == extendedBlindThingClassId) { if (action.actionTypeId() == extendedBlindOpenActionTypeId) { setBlindState(BlindStateOpening, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindStopActionTypeId) { setBlindState(BlindStateStopped, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindCloseActionTypeId) { setBlindState(BlindStateClosing, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindOpeningOutputActionTypeId) { bool on = action.param(extendedBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); thing->setStateValue(extendedBlindOpeningOutputStateTypeId, on); if (on) { setBlindState(BlindStateOpening, thing); } else { setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindClosingOutputActionTypeId) { bool on = action.param(extendedBlindClosingOutputActionClosingOutputParamTypeId).value().toBool(); thing->setStateValue(extendedBlindClosingOutputStateTypeId, on); if (on) { setBlindState(BlindStateClosing, thing); } else { setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindPercentageActionTypeId) { moveBlindToPercentage(action, thing); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == venetianBlindThingClassId) { if (action.actionTypeId() == venetianBlindOpenActionTypeId) { setBlindState(BlindStateOpening, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindStopActionTypeId) { setBlindState(BlindStateStopped, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindCloseActionTypeId) { setBlindState(BlindStateClosing, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindOpeningOutputActionTypeId) { bool on = action.param(venetianBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); thing->setStateValue(venetianBlindOpeningOutputStateTypeId, on); if (on) { setBlindState(BlindStateOpening, thing); } else { setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindClosingOutputActionTypeId) { bool on = action.param(venetianBlindClosingOutputActionClosingOutputParamTypeId).value().toBool(); thing->setStateValue(venetianBlindClosingOutputStateTypeId, on); if (on) { setBlindState(BlindStateClosing, thing); } else { setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindPercentageActionTypeId) { moveBlindToPercentage(action, thing); info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindAngleActionTypeId) { moveBlindToAngle(action, thing); info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == shutterThingClassId) { if (action.actionTypeId() == shutterOpenActionTypeId) { thing->setStateValue(shutterStatusStateTypeId, "Opening"); thing->setStateValue(shutterClosingOutputStateTypeId, false); thing->setStateValue(shutterOpeningOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == shutterStopActionTypeId) { thing->setStateValue(shutterStatusStateTypeId, "Stopped"); thing->setStateValue(shutterOpeningOutputStateTypeId, false); thing->setStateValue(shutterClosingOutputStateTypeId, false); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == shutterCloseActionTypeId) { thing->setStateValue(shutterStatusStateTypeId, "Closing"); thing->setStateValue(shutterOpeningOutputStateTypeId, false); thing->setStateValue(shutterClosingOutputStateTypeId, true); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == shutterOpeningOutputActionTypeId) { bool on = action.param(shutterOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); thing->setStateValue(shutterOpeningOutputStateTypeId, on); if (on) { thing->setStateValue(shutterStatusStateTypeId, "Opening"); thing->setStateValue(shutterClosingOutputStateTypeId, false); } else { thing->setStateValue(shutterStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == shutterClosingOutputActionTypeId) { bool on = action.param(shutterClosingOutputActionClosingOutputParamTypeId).value().toBool(); thing->setStateValue(shutterClosingOutputStateTypeId, on); if (on) { thing->setStateValue(shutterStatusStateTypeId, "Closing"); thing->setStateValue(shutterOpeningOutputStateTypeId, false); } else { thing->setStateValue(shutterStatusStateTypeId, "Stopped"); } info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == socketThingClassId) { if (action.actionTypeId() == socketPowerActionTypeId) { thing->setStateValue(socketPowerStateTypeId, action.param(socketPowerActionPowerParamTypeId).value()); return info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == lightThingClassId) { if (action.actionTypeId() == lightPowerActionTypeId) { thing->setStateValue(lightPowerStateTypeId, action.param(lightPowerActionPowerParamTypeId).value()); return info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == heatingThingClassId) { if (action.actionTypeId() == heatingPowerActionTypeId) { thing->setStateValue(heatingPowerStateTypeId, action.param(heatingPowerActionPowerParamTypeId).value()); return info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == powerSwitchThingClassId) { if (action.actionTypeId() == powerSwitchPowerActionTypeId) { thing->setStateValue(powerSwitchPowerStateTypeId, action.param(powerSwitchPowerActionPowerParamTypeId).value()); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == irrigationThingClassId) { if (action.actionTypeId() == irrigationPowerActionTypeId) { thing->setStateValue(irrigationPowerStateTypeId, action.param(irrigationPowerActionPowerParamTypeId).value()); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == ventilationThingClassId) { if (action.actionTypeId() == ventilationPowerActionTypeId) { thing->setStateValue(ventilationPowerStateTypeId, action.param(ventilationPowerActionPowerParamTypeId).value()); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == ventilationFlowThingClassId) { if (action.actionTypeId() == ventilationFlowPowerActionTypeId) { thing->setStateValue(ventilationFlowPowerStateTypeId, action.param(ventilationFlowPowerActionPowerParamTypeId).value()); info->finish(Thing::ThingErrorNoError); return; } else if (action.actionTypeId() == ventilationFlowFlowRateActionTypeId) { thing->setStateValue(ventilationFlowFlowRateStateTypeId, action.param(ventilationFlowFlowRateActionFlowRateParamTypeId).value()); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == temperatureSensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(temperatureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(temperatureSensorTemperatureStateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == humiditySensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(humiditySensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(humiditySensorHumidityStateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == moistureSensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(moistureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(moistureSensorMoistureStateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == pressureSensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(pressureSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(pressureSensorPressureStateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == co2SensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(co2SensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(co2SensorCo2StateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == lightSensorThingClassId) { 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 roundingFactor = qPow(10, info->thing()->setting(lightSensorSettingsAccuracyParamTypeId).toInt()); newValue = qRound(newValue * roundingFactor) / roundingFactor; thing->setStateValue(lightSensorLightIntensityStateTypeId, newValue); info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == smartMeterThingClassId) { if (action.actionTypeId() == smartMeterImpulseInputActionTypeId) { bool value = info->action().param(smartMeterImpulseInputActionImpulseInputParamTypeId).value().toBool(); thing->setStateValue(smartMeterImpulseInputStateTypeId, value); int impulsePerKwh = info->thing()->setting(smartMeterSettingsImpulsePerKwhParamTypeId).toInt(); if (value) { double currentEnergy = thing->stateValue(smartMeterTotalEnergyConsumedStateTypeId).toDouble(); thing->setStateValue(smartMeterTotalEnergyConsumedStateTypeId ,currentEnergy + (1.00/impulsePerKwh)); m_pulsesPerTimeframe[thing]++; } info->finish(Thing::ThingErrorNoError); return; } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } } else if (thing->thingClassId() == impulseGaragedooorThingClassId) { if (action.actionTypeId() == impulseGaragedooorTriggerImpulseActionTypeId) { uint duration = thing->setting(impulseGaragedooorSettingsImpulseDurationParamTypeId).toUInt(); thing->setStateValue(impulseGaragedooorImpulseStateTypeId, true); QTimer::singleShot(duration, thing, [thing](){ thing->setStateValue(impulseGaragedooorImpulseStateTypeId, false); }); info->finish(Thing::ThingErrorNoError); return; } Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } else if (thing->thingClassId() == simpleGaragedoorThingClassId) { if (action.actionTypeId() == simpleGaragedoorOpenActionTypeId) { thing->setStateValue(simpleGaragedoorClosingOutputStateTypeId, false); thing->setStateValue(simpleGaragedoorOpeningOutputStateTypeId, true); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == simpleGaragedoorCloseActionTypeId) { thing->setStateValue(simpleGaragedoorOpeningOutputStateTypeId, false); thing->setStateValue(simpleGaragedoorClosingOutputStateTypeId, true); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == simpleGaragedoorStopActionTypeId) { thing->setStateValue(simpleGaragedoorClosingOutputStateTypeId, false); thing->setStateValue(simpleGaragedoorOpeningOutputStateTypeId, false); info->finish(Thing::ThingErrorNoError); return; } Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } else if (thing->thingClassId() == extendedStatefulGaragedoorThingClassId) { if (action.actionTypeId() == extendedStatefulGaragedoorOpenActionTypeId) { m_statefulGarageTargetPercentage[thing] = 0; m_statefulGaragePercentageTimer[thing]->start(); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == extendedStatefulGaragedoorCloseActionTypeId) { m_statefulGarageTargetPercentage[thing] = 100; m_statefulGaragePercentageTimer[thing]->start(); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == extendedStatefulGaragedoorStopActionTypeId) { m_statefulGarageTargetPercentage[thing] = thing->stateValue(extendedStatefulGaragedoorPercentageStateTypeId).toUInt(); info->finish(Thing::ThingErrorNoError); return; } Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } else if (thing->thingClassId() == thermostatThingClassId) { if (action.actionTypeId() == thermostatTemperatureActionTypeId) { thing->setStateValue(thermostatTemperatureStateTypeId, action.param(thermostatTemperatureActionTemperatureParamTypeId).value()); } else if (action.actionTypeId() == thermostatTargetTemperatureActionTypeId) { double minSetting = thing->setting(thermostatSettingsMinTargetTemperatureParamTypeId).toDouble(); double maxSetting = thing->setting(thermostatSettingsMaxTargetTemperatureParamTypeId).toDouble(); double newTemp = action.param(thermostatTargetTemperatureActionTargetTemperatureParamTypeId).value().toDouble(); newTemp = qMax(newTemp, minSetting); newTemp = qMin(newTemp, maxSetting); thing->setStateValue(thermostatTargetTemperatureStateTypeId, newTemp); } else if (action.actionTypeId() == thermostatHeatingOnActionTypeId) { thing->setStateValue(thermostatHeatingOnStateTypeId, action.param(thermostatHeatingOnActionHeatingOnParamTypeId).value()); } else if (action.actionTypeId() == thermostatCoolingOnActionTypeId) { thing->setStateValue(thermostatCoolingOnStateTypeId, action.param(thermostatCoolingOnActionCoolingOnParamTypeId).value()); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } thermostatCheckPowerOutputState(thing); info->finish(Thing::ThingErrorNoError); return; } else if (thing->thingClassId() == heatingThingClassId) { if (action.actionTypeId() == heatingPowerActionTypeId) { thing->setStateValue(heatingPowerStateTypeId, action.paramValue(heatingPowerActionPowerParamTypeId).toBool()); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } info->finish(Thing::ThingErrorNoError); return; } else if (thing->thingClassId() == coolingThingClassId) { if (action.actionTypeId() == coolingPowerActionTypeId) { thing->setStateValue(coolingPowerStateTypeId, action.paramValue(coolingPowerActionPowerParamTypeId).toBool()); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } info->finish(Thing::ThingErrorNoError); return; } else if (thing->thingClassId() == sgReadyThingClassId) { if (action.actionTypeId() == sgReadyRelay1ActionTypeId) { thing->setStateValue(sgReadyRelay1StateTypeId, action.param(sgReadyRelay1ActionRelay1ParamTypeId).value()); int operatingMode = sgReadyOperatingMode(thing->stateValue(sgReadyRelay1StateTypeId).toBool(), thing->stateValue(sgReadyRelay2StateTypeId).toBool()); thing->setStateValue(sgReadyOperatingModeStateTypeId, operatingMode); thing->setStateValue(sgReadyOperatingModeDescriptionStateTypeId, sgReadyOperatingModeDescription(operatingMode)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == sgReadyRelay2ActionTypeId) { thing->setStateValue(sgReadyRelay2StateTypeId, action.param(sgReadyRelay2ActionRelay2ParamTypeId).value()); int operatingMode = sgReadyOperatingMode(thing->stateValue(sgReadyRelay1StateTypeId).toBool(), thing->stateValue(sgReadyRelay2StateTypeId).toBool()); thing->setStateValue(sgReadyOperatingModeStateTypeId, operatingMode); thing->setStateValue(sgReadyOperatingModeDescriptionStateTypeId, sgReadyOperatingModeDescription(operatingMode)); info->finish(Thing::ThingErrorNoError); return; } if (action.actionTypeId() == sgReadyOperatingModeActionTypeId) { int operatingMode = action.param(sgReadyOperatingModeActionOperatingModeParamTypeId).value().toInt(); thing->setStateValue(sgReadyOperatingModeStateTypeId, operatingMode); thing->setStateValue(sgReadyOperatingModeDescriptionStateTypeId, sgReadyOperatingModeDescription(operatingMode)); if (operatingMode == 1) { thing->setStateValue(sgReadyRelay1StateTypeId, true); thing->setStateValue(sgReadyRelay2StateTypeId, false); } else if (operatingMode == 2) { thing->setStateValue(sgReadyRelay1StateTypeId, false); thing->setStateValue(sgReadyRelay2StateTypeId, false); } else if (operatingMode == 3) { thing->setStateValue(sgReadyRelay1StateTypeId, false); thing->setStateValue(sgReadyRelay2StateTypeId, true); } else if (operatingMode == 4) { thing->setStateValue(sgReadyRelay1StateTypeId, true); thing->setStateValue(sgReadyRelay2StateTypeId, true); } info->finish(Thing::ThingErrorNoError); return; } Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } else if (thing->thingClassId() == doorSensorThingClassId) { if (action.actionTypeId() == doorSensorClosedActionTypeId) { bool closed = action.paramValue(doorSensorClosedActionClosedParamTypeId).toBool(); qCDebug(dcGenericThings()) << "Door sensor is now" << (closed ? "open" : "closed"); thing->setStateValue(doorSensorClosedStateTypeId, closed); info->finish(Thing::ThingErrorNoError); return; } } else if (thing->thingClassId() == presenceSensorThingClassId) { if (action.actionTypeId() == presenceSensorIsPresentActionTypeId) { bool isPresent = action.paramValue(presenceSensorIsPresentActionIsPresentParamTypeId).toBool(); qCDebug(dcGenericThings()) << "Presence sensor is now" << (isPresent ? "present" : "not present"); thing->setStateValue(presenceSensorIsPresentStateTypeId, isPresent); if (isPresent) { thing->setStateValue(presenceSensorLastSeenTimeStateTypeId, QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000); } info->finish(Thing::ThingErrorNoError); return; } } else if (thing->thingClassId() == batteryThingClassId) { if (action.actionTypeId() == batteryBatteryLevelControlActionTypeId) { int value = action.paramValue(batteryBatteryLevelControlActionBatteryLevelControlParamTypeId).toInt(); thing->setStateValue(batteryBatteryLevelStateTypeId, value); thing->setStateValue(batteryBatteryLevelControlStateTypeId, value); int criticalValue = thing->setting(batterySettingsCriticalLevelParamTypeId).toInt(); thing->setStateValue(batteryBatteryCriticalStateTypeId, value <= criticalValue); info->finish(Thing::ThingErrorNoError); return; } else if (action.actionTypeId() == batteryChargingActionTypeId) { thing->setStateValue(batteryChargingStateTypeId, action.paramValue(batteryChargingActionChargingParamTypeId)); info->finish(Thing::ThingErrorNoError); return; } } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8()); } } void IntegrationPluginGenericThings::thingRemoved(Thing *thing) { if (thing->thingClassId() == extendedBlindThingClassId) { m_extendedBlindPercentageTimer.take(thing)->deleteLater(); m_extendedBlindTargetPercentage.remove(thing); } else if (thing->thingClassId() == venetianBlindThingClassId) { m_extendedBlindPercentageTimer.take(thing)->deleteLater(); m_extendedBlindTargetPercentage.remove(thing); m_venetianBlindAngleTimer.take(thing)->deleteLater(); m_venetianBlindTargetAngle.remove(thing); } else if (thing->thingClassId() == smartMeterThingClassId) { m_pulsesPerTimeframe.remove(thing); } else if (thing->thingClassId() == smartMeterThingClassId) { m_smartMeterTimer.take(thing)->deleteLater(); m_pulsesPerTimeframe.remove(thing); } } double IntegrationPluginGenericThings::mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax) { double percent = (value - fromMin) / (fromMax - fromMin); double toValue = toMin + (toMax - toMin) * percent; return toValue; } void IntegrationPluginGenericThings::setBlindState(IntegrationPluginGenericThings::BlindState state, Thing *thing) { //If an ongoing "to percentage" actions is beeing executed, it is now overruled by another action m_extendedBlindTargetPercentage.remove(thing); if (thing->thingClassId() == extendedBlindThingClassId) { switch (state) { case BlindStateOpening: thing->setStateValue(extendedBlindStatusStateTypeId, "Opening"); thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); thing->setStateValue(extendedBlindOpeningOutputStateTypeId, true); thing->setStateValue(extendedBlindMovingStateTypeId, true); m_extendedBlindPercentageTimer.value(thing)->start(); break; case BlindStateClosing: thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); thing->setStateValue(extendedBlindClosingOutputStateTypeId, true); thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); thing->setStateValue(extendedBlindMovingStateTypeId, true); m_extendedBlindPercentageTimer.value(thing)->start(); break; case BlindStateStopped: thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); thing->setStateValue(extendedBlindMovingStateTypeId, false); m_extendedBlindPercentageTimer.value(thing)->stop(); break; } } else if (thing->thingClassId() == venetianBlindThingClassId) { m_venetianBlindTargetAngle.remove(thing); switch (state) { case BlindStateOpening: thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); thing->setStateValue(venetianBlindOpeningOutputStateTypeId, true); thing->setStateValue(venetianBlindMovingStateTypeId, true); m_extendedBlindPercentageTimer.value(thing)->start(); m_venetianBlindAngleTimer.value(thing)->start(); break; case BlindStateClosing: thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); thing->setStateValue(venetianBlindClosingOutputStateTypeId, true); thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); thing->setStateValue(venetianBlindMovingStateTypeId, true); m_extendedBlindPercentageTimer.value(thing)->start(); m_venetianBlindAngleTimer.value(thing)->start(); break; case BlindStateStopped: thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); thing->setStateValue(venetianBlindMovingStateTypeId, false); m_extendedBlindPercentageTimer.value(thing)->stop(); m_venetianBlindAngleTimer.value(thing)->stop(); break; } } } void IntegrationPluginGenericThings::moveBlindToPercentage(Action action, Thing *thing) { if (thing->thingClassId() == extendedBlindThingClassId) { uint targetPercentage = action.param(extendedBlindPercentageActionPercentageParamTypeId).value().toUInt(); uint currentPercentage = thing->stateValue(extendedBlindPercentageStateTypeId).toUInt(); // 100% indicates the device is fully closed if (targetPercentage == currentPercentage) { qCDebug(dcGenericThings()) << "Extended blind is already at given percentage" << targetPercentage; } else if (targetPercentage > currentPercentage) { setBlindState(BlindStateClosing, thing); m_extendedBlindTargetPercentage.insert(thing, targetPercentage); } else if (targetPercentage < currentPercentage) { setBlindState(BlindStateOpening, thing); m_extendedBlindTargetPercentage.insert(thing, targetPercentage); } else { setBlindState(BlindStateStopped, thing); } } else if (thing->thingClassId() == venetianBlindThingClassId) { uint targetPercentage = action.param(venetianBlindPercentageActionPercentageParamTypeId).value().toUInt(); uint currentPercentage = thing->stateValue(venetianBlindPercentageStateTypeId).toUInt(); qCDebug(dcGenericThings()) << "Moving venetian blind to percentage" << targetPercentage << "Current percentage:" << currentPercentage; // 100% indicates the device is fully closed if (targetPercentage == currentPercentage) { qCDebug(dcGenericThings()) << "Extended blind is already at given percentage" << targetPercentage; } else if (targetPercentage > currentPercentage) { setBlindState(BlindStateClosing, thing); m_extendedBlindTargetPercentage.insert(thing, targetPercentage); } else if (targetPercentage < currentPercentage) { setBlindState(BlindStateOpening, thing); m_extendedBlindTargetPercentage.insert(thing, targetPercentage); } else { setBlindState(BlindStateStopped, thing); } } else { qCDebug(dcGenericThings()) << "Move to percentage doesn't support this thingClass"; } } void IntegrationPluginGenericThings::moveBlindToAngle(Action action, Thing *thing) { if (thing->thingClassId() == venetianBlindThingClassId) { if (action.actionTypeId() == venetianBlindAngleActionTypeId) { //NOTE moving percentage affects the angle but the angle doesnt affect the percentage // opening -> -90 // closing -> +90 int targetAngle = action.param(venetianBlindAngleActionAngleParamTypeId).value().toInt(); int currentAngle = thing->stateValue(venetianBlindAngleStateTypeId).toInt(); if (targetAngle == currentAngle) { qCDebug(dcGenericThings()) << "Venetian blind is already at given angle" << targetAngle; } else if (targetAngle > currentAngle) { setBlindState(BlindStateClosing, thing); m_venetianBlindTargetAngle.insert(thing, targetAngle); } else if (targetAngle < currentAngle) { setBlindState(BlindStateOpening, thing); m_venetianBlindTargetAngle.insert(thing, targetAngle); } else { setBlindState(BlindStateStopped, thing); } } } else { qCDebug(dcGenericThings()) << "Move to angle doesn't support this thingClass"; } } void IntegrationPluginGenericThings::thermostatCheckPowerOutputState(Thing *thing) { double targetTemperature = thing->stateValue(thermostatTargetTemperatureStateTypeId).toDouble(); double actualTemperature = thing->stateValue(thermostatTemperatureStateTypeId).toDouble(); double temperatureDifference = thing->setting(thermostatSettingsTemperatureDifferenceParamTypeId).toDouble(); if (actualTemperature <= (targetTemperature-temperatureDifference)) { thing->setStateValue(thermostatHeatingOnStateTypeId, true); } else if (actualTemperature >= targetTemperature) { thing->setStateValue(thermostatHeatingOnStateTypeId, false); } if (actualTemperature >= (targetTemperature+temperatureDifference)) { thing->setStateValue(thermostatCoolingOnStateTypeId, true); } else if (actualTemperature <= targetTemperature) { thing->setStateValue(thermostatCoolingOnStateTypeId, false); } } QString IntegrationPluginGenericThings::sgReadyOperatingModeDescription(int operatingMode) { if (operatingMode == 1) { return "Stop heating."; } else if (operatingMode == 2) { return "Normal mode, with partial heat storage filling."; } else if (operatingMode == 3) { return "Increased room and heat storage temperature."; } else if (operatingMode == 4) { return "Start heating."; } return QString("Unknown operating mode %1").arg(operatingMode); } int IntegrationPluginGenericThings::sgReadyOperatingMode(bool relay1, bool relay2) { if (relay1 && !relay2) { /* * Operating state 1 (Relay state: 1: 0): * This operating state is downward compatible with the often fixed times * activated EVU lock and includes a maximum of 2 hours of "hard" lock time. */ return 1; } else if (!relay1 && !relay2) { /* * Operating state 2 (Relay state: 0: 0): * In this circuit, the heat pump runs in energy-efficient normal mode * with partial heat storage filling for the maximum two-hour EVU lock. */ return 2; } else if (!relay1 && relay2) { /* * Operating state 3 (Relay state: 0: 1): * In this operating state, the heat pump within the controller runs in amplified mode * Operation for space heating and hot water preparation. It's not one * definitive start-up command, but a switch-on recommendation according to the current increase. */ return 3; } else { /* * Operating state 4 (Relay state 1: 1): * This is a definitive start-up command, insofar as this is possible within the framework of the rule settings. * For this operating state, different control models must be set on the controller for different tariff and usage models: * Variant 1: The heat pump (compressor) is actively switched on. * Variant 2: The heat pump (compressor and electrical auxiliary heating) is actively switched on, optional: higher temperature in the heat storage */ return 4; } }