From 9641d02fb74f8dacee833890cf456bbbd4cd4fb0 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Fri, 3 Jul 2020 15:00:32 +0200 Subject: [PATCH] added percentage counter --- .../integrationplugingenericthings.cpp | 222 ++++++++++++++---- .../integrationplugingenericthings.h | 16 ++ .../integrationplugingenericthings.json | 29 ++- 3 files changed, 222 insertions(+), 45 deletions(-) diff --git a/genericthings/integrationplugingenericthings.cpp b/genericthings/integrationplugingenericthings.cpp index 6a177f4..d1ad231 100644 --- a/genericthings/integrationplugingenericthings.cpp +++ b/genericthings/integrationplugingenericthings.cpp @@ -1,8 +1,9 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* * * 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 @@ -42,6 +43,32 @@ IntegrationPluginGenericThings::IntegrationPluginGenericThings() void IntegrationPluginGenericThings::setupThing(ThingSetupInfo *info) { info->finish(Thing::ThingErrorNoError); + Thing *thing = info->thing(); + if (thing->thingClassId() == extendedBlindThingClassId) { + int closingTime = thing->paramValue(extendedBlindThingClosingTimeParamTypeId).toInt(); + QTimer* timer = new QTimer(this); + timer->setInterval(closingTime/100); // closing timer / 100 to update on every percent + m_extendedBlindPercentageTimer.insert(thing, timer); + connect(timer, &QTimer::timeout, this, [thing, this] { + int targetPercentage = m_extendedBlindTargetPercentage.value(thing); + m_extendedBlindTargetPercentage.insert(thing, targetPercentage++); + int currentPercentage = thing->stateValue(extendedBlindPercentageStateTypeId).toInt(); + thing->setStateValue(extendedBlindPercentageStateTypeId, currentPercentage++); + if (targetPercentage == currentPercentage) { + //Stop timer + setBlindState(BlindStateStopped, thing); + } + if (BlindStateOpening) { + + } else if (BlindStateClosing) { + + } else { + + } + }); + } else if (info->thing()->thingClassId() == venetianBlindThingClassId) { + + } } void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info) @@ -136,94 +163,73 @@ void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info) return info->finish(Thing::ThingErrorActionTypeNotFound); } else if (thing->thingClassId() == extendedBlindThingClassId) { + if (action.actionTypeId() == extendedBlindOpenActionTypeId) { - thing->setStateValue(extendedBlindStatusStateTypeId, "Opening"); - thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); - thing->setStateValue(extendedBlindOpeningOutputStateTypeId, true); - //TODO set moving state + setBlindState(BlindStateOpening, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindStopActionTypeId) { - thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); - thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); - thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); + setBlindState(BlindStateStopped, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindCloseActionTypeId) { - thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); - thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); - thing->setStateValue(extendedBlindClosingOutputStateTypeId, true); + 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) { - thing->setStateValue(extendedBlindStatusStateTypeId, "Opening"); - thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); + setBlindState(BlindStateOpening, thing); } else { - thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); + 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) { - thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); - thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); + setBlindState(BlindStateClosing, thing); } else { - thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); + setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == extendedBlindPercentageActionTypeId) { - int percentage = action.param(extendedBlindPercentageActionPercentageParamTypeId).value().toBool(); - Q_UNUSED(percentage) - //TODO move to percentage + 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) { - thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); - thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); - thing->setStateValue(venetianBlindOpeningOutputStateTypeId, true); - //TODO set moving state + setBlindState(BlindStateOpening, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindStopActionTypeId) { - thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); - thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); - thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); + setBlindState(BlindStateStopped, thing); return info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindCloseActionTypeId) { - thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); - thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); - thing->setStateValue(venetianBlindClosingOutputStateTypeId, true); + 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) { - thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); - thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); + setBlindState(BlindStateOpening, thing); } else { - thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); + 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) { - thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); - thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); + setBlindState(BlindStateClosing, thing); } else { - thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); + setBlindState(BlindStateStopped, thing); } info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindPercentageActionTypeId) { - int percentage = action.param(venetianBlindPercentageActionPercentageParamTypeId).value().toInt(); - Q_UNUSED(percentage) - //TODO move to percentage + moveBlindToPercentage(action, thing); + info->finish(Thing::ThingErrorNoError); } else if (action.actionTypeId() == venetianBlindAngleActionTypeId) { - int angle = action.param(venetianBlindAngleActionAngleParamTypeId).value().toInt(); - Q_UNUSED(angle) - //TODO move to angle + moveBlindToAngle(action, thing); + info->finish(Thing::ThingErrorNoError); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } @@ -349,9 +355,139 @@ void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info) } } +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(); + } +} + 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_extendedBlindPercentageTimer.value(thing)->stop(); + 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); + break; + case BlindStateClosing: + thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); + thing->setStateValue(extendedBlindClosingOutputStateTypeId, true); + thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); + thing->setStateValue(extendedBlindMovingStateTypeId, true); + break; + case BlindStateStopped: + thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); + thing->setStateValue(extendedBlindClosingOutputStateTypeId, false); + thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false); + thing->setStateValue(extendedBlindMovingStateTypeId, false); + break; + } + } else if (thing->thingClassId() == venetianBlindThingClassId) { + switch (state) { + case BlindStateOpening: + thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); + thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); + thing->setStateValue(venetianBlindOpeningOutputStateTypeId, true); + thing->setStateValue(venetianBlindMovingStateTypeId, true); + break; + case BlindStateClosing: + thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); + thing->setStateValue(venetianBlindClosingOutputStateTypeId, true); + thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); + thing->setStateValue(venetianBlindMovingStateTypeId, true); + break; + case BlindStateStopped: + thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); + thing->setStateValue(venetianBlindClosingOutputStateTypeId, false); + thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false); + thing->setStateValue(venetianBlindMovingStateTypeId, false); + break; + } + } +} + +void IntegrationPluginGenericThings::setBlindMovingState(Action action, Thing *thing) +{ + if (thing->thingClassId() == extendedBlindThingClassId) { + int percentage = thing->stateValue(extendedBlindPercentageStateTypeId).toInt(); + if (action.actionTypeId() == extendedBlindOpenActionTypeId) { + if (percentage != 100) { + setBlindState(BlindStateOpening, thing); + } else { + // Blind already open + setBlindState(BlindStateStopped, thing); + } + } else if (action.actionTypeId() == extendedBlindStopActionTypeId) { + setBlindState(BlindStateStopped, thing); + thing->setStateValue(extendedBlindMovingStateTypeId, false); + + } else if (action.actionTypeId() == extendedBlindCloseActionTypeId) { + if (percentage != 0) { + setBlindState(BlindStateClosing, thing); + } else { + // Blind already closed + setBlindState(BlindStateStopped, thing); + thing->setStateValue(extendedBlindMovingStateTypeId, false); + } + } + + } else if (thing->thingClassId() == venetianBlindThingClassId) { + + } +} + +void IntegrationPluginGenericThings::moveBlindToPercentage(Action action, Thing *thing) +{ + if (thing->thingClassId() == extendedBlindThingClassId) { + int targetPercentage = action.param(extendedBlindPercentageActionPercentageParamTypeId).value().toBool(); + int currentPercentage = thing->stateValue(extendedBlindPercentageStateTypeId).toInt(); + // 100% indicates the device is fully closed + if (targetPercentage == currentPercentage) { + //Nothing to do + } else if (targetPercentage > currentPercentage) { + setBlindState(BlindStateClosing, thing); + m_extendedBlindTargetPercentage.insert(thing, targetPercentage); + m_extendedBlindPercentageTimer.value(thing)->start(); + } else if (targetPercentage < currentPercentage) { + setBlindState(BlindStateOpening, thing); + m_extendedBlindTargetPercentage.insert(thing, targetPercentage); + m_extendedBlindPercentageTimer.value(thing)->start(); + } else { + setBlindState(BlindStateStopped, thing); + } + } else if (thing->thingClassId() == venetianBlindThingClassId) { + int targetPercentage = action.param(venetianBlindPercentageActionPercentageParamTypeId).value().toBool(); + int currentPercentage = thing->stateValue(venetianBlindPercentageStateTypeId).toInt(); + if (targetPercentage == currentPercentage) { + + } else if (targetPercentage > currentPercentage) { + + } else if (targetPercentage < currentPercentage) { + + } + } +} + +void IntegrationPluginGenericThings::moveBlindToAngle(Action action, Thing *thing) +{ + +} diff --git a/genericthings/integrationplugingenericthings.h b/genericthings/integrationplugingenericthings.h index 5e6f7f3..d4e5f98 100644 --- a/genericthings/integrationplugingenericthings.h +++ b/genericthings/integrationplugingenericthings.h @@ -32,6 +32,7 @@ #define INTEGRATIONPLUGINGENERICTHINGS_H #include "integrations/integrationplugin.h" +#include class IntegrationPluginGenericThings: public IntegrationPlugin { @@ -44,9 +45,24 @@ public: explicit IntegrationPluginGenericThings(); void setupThing(ThingSetupInfo *info) override; void executeAction(ThingActionInfo *info) override; + void thingRemoved(Thing *thing) override; private: double mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax); + + QHash m_extendedBlindPercentageTimer; + QHash m_venetianBlindAngleTimer; + QHash m_extendedBlindTargetPercentage; + + enum BlindState { + BlindStateOpening, + BlindStateClosing, + BlindStateStopped + }; + void setBlindState(BlindState state, Thing *thing); + void setBlindMovingState(Action action, Thing *thing); + void moveBlindToPercentage(Action action, Thing *thing); + void moveBlindToAngle(Action action, Thing *thing); }; #endif // INTEGRATIONPLUGINGENERICTHINGS_H diff --git a/genericthings/integrationplugingenericthings.json b/genericthings/integrationplugingenericthings.json index 45aee59..846afd2 100644 --- a/genericthings/integrationplugingenericthings.json +++ b/genericthings/integrationplugingenericthings.json @@ -135,7 +135,16 @@ "name": "extendedBlind", "displayName": "Generic extended blind", "createMethods": ["user"], - "interfaces": ["blind"], + "interfaces": ["extendedblind"], + "paramTypes": [ + { + "id": "27a95b8d-7f97-441b-a3be-0646c517cb06", + "name": "closingTime", + "displayName": "Closing time [MilliSecond]", + "type": "int", + "defaultValue": 0 + } + ], "stateTypes": [ { "id": "e559f077-e904-4bbc-8ec3-344b814d2eab", @@ -216,7 +225,23 @@ "name": "venetianBlind", "displayName": "Venetian blind", "createMethods": ["user"], - "interfaces": ["blind"], + "interfaces": ["venetianblind"], + "paramTypes": [ + { + "id": "4c0bf07d-aaab-4f67-af65-00ceaefbaa84", + "name": "closingTime", + "displayName": "Closing time [MilliSecond]", + "type": "int", + "defaultValue": 0 + }, + { + "id": "6c8340bf-7fd3-43e3-a75b-dfa2f6426e11", + "name": "angleTime", + "displayName": "Angle end to end time [MilliSecond]", + "type": "int", + "defaultValue": 0 + } + ], "stateTypes": [ { "id": "6041dacf-5303-4dc0-ba3c-7ecaa438f2dd",