added percentage counter

pull/1/head
bernhard.trinnes 2020-07-03 15:00:32 +02:00
parent 8a10124051
commit 9641d02fb7
3 changed files with 222 additions and 45 deletions

View File

@ -1,8 +1,9 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
*
* This file is part of nymea. * This file is part of nymea.
* This project including source code and documentation is protected by * This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including * copyright law, and remains the property of nymea GmbH. All rights, including
@ -42,6 +43,32 @@ IntegrationPluginGenericThings::IntegrationPluginGenericThings()
void IntegrationPluginGenericThings::setupThing(ThingSetupInfo *info) void IntegrationPluginGenericThings::setupThing(ThingSetupInfo *info)
{ {
info->finish(Thing::ThingErrorNoError); 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) void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info)
@ -136,94 +163,73 @@ void IntegrationPluginGenericThings::executeAction(ThingActionInfo *info)
return info->finish(Thing::ThingErrorActionTypeNotFound); return info->finish(Thing::ThingErrorActionTypeNotFound);
} else if (thing->thingClassId() == extendedBlindThingClassId) { } else if (thing->thingClassId() == extendedBlindThingClassId) {
if (action.actionTypeId() == extendedBlindOpenActionTypeId) { if (action.actionTypeId() == extendedBlindOpenActionTypeId) {
thing->setStateValue(extendedBlindStatusStateTypeId, "Opening"); setBlindState(BlindStateOpening, thing);
thing->setStateValue(extendedBlindClosingOutputStateTypeId, false);
thing->setStateValue(extendedBlindOpeningOutputStateTypeId, true);
//TODO set moving state
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedBlindStopActionTypeId) { } else if (action.actionTypeId() == extendedBlindStopActionTypeId) {
thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false);
thing->setStateValue(extendedBlindClosingOutputStateTypeId, false);
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedBlindCloseActionTypeId) { } else if (action.actionTypeId() == extendedBlindCloseActionTypeId) {
thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); setBlindState(BlindStateClosing, thing);
thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false);
thing->setStateValue(extendedBlindClosingOutputStateTypeId, true);
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedBlindOpeningOutputActionTypeId) { } else if (action.actionTypeId() == extendedBlindOpeningOutputActionTypeId) {
bool on = action.param(extendedBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); bool on = action.param(extendedBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool();
thing->setStateValue(extendedBlindOpeningOutputStateTypeId, on); thing->setStateValue(extendedBlindOpeningOutputStateTypeId, on);
if (on) { if (on) {
thing->setStateValue(extendedBlindStatusStateTypeId, "Opening"); setBlindState(BlindStateOpening, thing);
thing->setStateValue(extendedBlindClosingOutputStateTypeId, false);
} else { } else {
thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
} }
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedBlindClosingOutputActionTypeId) { } else if (action.actionTypeId() == extendedBlindClosingOutputActionTypeId) {
bool on = action.param(extendedBlindClosingOutputActionClosingOutputParamTypeId).value().toBool(); bool on = action.param(extendedBlindClosingOutputActionClosingOutputParamTypeId).value().toBool();
thing->setStateValue(extendedBlindClosingOutputStateTypeId, on); thing->setStateValue(extendedBlindClosingOutputStateTypeId, on);
if (on) { if (on) {
thing->setStateValue(extendedBlindStatusStateTypeId, "Closing"); setBlindState(BlindStateClosing, thing);
thing->setStateValue(extendedBlindOpeningOutputStateTypeId, false);
} else { } else {
thing->setStateValue(extendedBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
} }
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedBlindPercentageActionTypeId) { } else if (action.actionTypeId() == extendedBlindPercentageActionTypeId) {
int percentage = action.param(extendedBlindPercentageActionPercentageParamTypeId).value().toBool(); moveBlindToPercentage(action, thing);
Q_UNUSED(percentage)
//TODO move to percentage
} else { } else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
} }
} else if (thing->thingClassId() == venetianBlindThingClassId) { } else if (thing->thingClassId() == venetianBlindThingClassId) {
if (action.actionTypeId() == venetianBlindOpenActionTypeId) { if (action.actionTypeId() == venetianBlindOpenActionTypeId) {
thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); setBlindState(BlindStateOpening, thing);
thing->setStateValue(venetianBlindClosingOutputStateTypeId, false);
thing->setStateValue(venetianBlindOpeningOutputStateTypeId, true);
//TODO set moving state
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == venetianBlindStopActionTypeId) { } else if (action.actionTypeId() == venetianBlindStopActionTypeId) {
thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false);
thing->setStateValue(venetianBlindClosingOutputStateTypeId, false);
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == venetianBlindCloseActionTypeId) { } else if (action.actionTypeId() == venetianBlindCloseActionTypeId) {
thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); setBlindState(BlindStateClosing, thing);
thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false);
thing->setStateValue(venetianBlindClosingOutputStateTypeId, true);
return info->finish(Thing::ThingErrorNoError); return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == venetianBlindOpeningOutputActionTypeId) { } else if (action.actionTypeId() == venetianBlindOpeningOutputActionTypeId) {
bool on = action.param(venetianBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool(); bool on = action.param(venetianBlindOpeningOutputActionOpeningOutputParamTypeId).value().toBool();
thing->setStateValue(venetianBlindOpeningOutputStateTypeId, on); thing->setStateValue(venetianBlindOpeningOutputStateTypeId, on);
if (on) { if (on) {
thing->setStateValue(venetianBlindStatusStateTypeId, "Opening"); setBlindState(BlindStateOpening, thing);
thing->setStateValue(venetianBlindClosingOutputStateTypeId, false);
} else { } else {
thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
} }
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == venetianBlindClosingOutputActionTypeId) { } else if (action.actionTypeId() == venetianBlindClosingOutputActionTypeId) {
bool on = action.param(venetianBlindClosingOutputActionClosingOutputParamTypeId).value().toBool(); bool on = action.param(venetianBlindClosingOutputActionClosingOutputParamTypeId).value().toBool();
thing->setStateValue(venetianBlindClosingOutputStateTypeId, on); thing->setStateValue(venetianBlindClosingOutputStateTypeId, on);
if (on) { if (on) {
thing->setStateValue(venetianBlindStatusStateTypeId, "Closing"); setBlindState(BlindStateClosing, thing);
thing->setStateValue(venetianBlindOpeningOutputStateTypeId, false);
} else { } else {
thing->setStateValue(venetianBlindStatusStateTypeId, "Stopped"); setBlindState(BlindStateStopped, thing);
} }
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == venetianBlindPercentageActionTypeId) { } else if (action.actionTypeId() == venetianBlindPercentageActionTypeId) {
int percentage = action.param(venetianBlindPercentageActionPercentageParamTypeId).value().toInt(); moveBlindToPercentage(action, thing);
Q_UNUSED(percentage) info->finish(Thing::ThingErrorNoError);
//TODO move to percentage
} else if (action.actionTypeId() == venetianBlindAngleActionTypeId) { } else if (action.actionTypeId() == venetianBlindAngleActionTypeId) {
int angle = action.param(venetianBlindAngleActionAngleParamTypeId).value().toInt(); moveBlindToAngle(action, thing);
Q_UNUSED(angle) info->finish(Thing::ThingErrorNoError);
//TODO move to angle
} else { } else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); 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 IntegrationPluginGenericThings::mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax)
{ {
double percent = (value - fromMin) / (fromMax - fromMin); double percent = (value - fromMin) / (fromMax - fromMin);
double toValue = toMin + (toMax - toMin) * percent; double toValue = toMin + (toMax - toMin) * percent;
return toValue; 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)
{
}

View File

@ -32,6 +32,7 @@
#define INTEGRATIONPLUGINGENERICTHINGS_H #define INTEGRATIONPLUGINGENERICTHINGS_H
#include "integrations/integrationplugin.h" #include "integrations/integrationplugin.h"
#include <QTimer>
class IntegrationPluginGenericThings: public IntegrationPlugin class IntegrationPluginGenericThings: public IntegrationPlugin
{ {
@ -44,9 +45,24 @@ public:
explicit IntegrationPluginGenericThings(); explicit IntegrationPluginGenericThings();
void setupThing(ThingSetupInfo *info) override; void setupThing(ThingSetupInfo *info) override;
void executeAction(ThingActionInfo *info) override; void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
private: private:
double mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax); double mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax);
QHash<Thing *, QTimer *> m_extendedBlindPercentageTimer;
QHash<Thing *, QTimer *> m_venetianBlindAngleTimer;
QHash<Thing *, int> 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 #endif // INTEGRATIONPLUGINGENERICTHINGS_H

View File

@ -135,7 +135,16 @@
"name": "extendedBlind", "name": "extendedBlind",
"displayName": "Generic extended blind", "displayName": "Generic extended blind",
"createMethods": ["user"], "createMethods": ["user"],
"interfaces": ["blind"], "interfaces": ["extendedblind"],
"paramTypes": [
{
"id": "27a95b8d-7f97-441b-a3be-0646c517cb06",
"name": "closingTime",
"displayName": "Closing time [MilliSecond]",
"type": "int",
"defaultValue": 0
}
],
"stateTypes": [ "stateTypes": [
{ {
"id": "e559f077-e904-4bbc-8ec3-344b814d2eab", "id": "e559f077-e904-4bbc-8ec3-344b814d2eab",
@ -216,7 +225,23 @@
"name": "venetianBlind", "name": "venetianBlind",
"displayName": "Venetian blind", "displayName": "Venetian blind",
"createMethods": ["user"], "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": [ "stateTypes": [
{ {
"id": "6041dacf-5303-4dc0-ba3c-7ecaa438f2dd", "id": "6041dacf-5303-4dc0-ba3c-7ecaa438f2dd",