Merge PR #21: Generic shading: Add generic awning with position control

remove-unneeded-dependency
jenkins 2023-11-28 10:40:17 +01:00
commit 2c2c18468d
3 changed files with 212 additions and 0 deletions

View File

@ -86,6 +86,49 @@ void IntegrationPluginGenericShading::setupThing(ThingSetupInfo *info)
}
}
});
} else if (thing->thingClassId() == extendedAwningThingClassId) {
uint closingDuration = thing->setting(extendedAwningSettingsClosingDurationParamTypeId).toUInt();
QTimer* timer = new QTimer(this);
timer->setInterval(closingDuration/100.00); // closing timer / 100 to update on every percent
m_extendedAwningPercentageTimer.insert(thing, timer);
connect(thing, &Thing::settingChanged, thing, [timer] (const ParamTypeId &paramTypeId, const QVariant &value) {
if (paramTypeId == extendedAwningSettingsClosingDurationParamTypeId) {
timer->setInterval(value.toUInt()/100.00);
}
});
connect(timer, &QTimer::timeout, this, [thing, this] {
uint currentPercentage = thing->stateValue(extendedAwningPercentageStateTypeId).toUInt();
if (thing->stateValue(extendedAwningStatusStateTypeId).toString() == "Closing") {
if (currentPercentage == 100) {
setBlindState(BlindStateStopped, thing);
qCDebug(dcGenericShading()) << "Extended awning is closed, stopping timer";
} else {
currentPercentage++;
thing->setStateValue(extendedAwningPercentageStateTypeId, currentPercentage);
}
} else if (thing->stateValue(extendedAwningStatusStateTypeId).toString() == "Opening") {
if (currentPercentage == 0) {
setBlindState(BlindStateStopped, thing);
qCDebug(dcGenericShading()) << "Extended awning is opened, stopping timer";
} else {
currentPercentage--;
thing->setStateValue(extendedAwningPercentageStateTypeId, currentPercentage);
}
} else {
setBlindState(BlindStateStopped, thing);
}
if (m_extendedAwningPercentageTimer.contains(thing)) {
uint targetPercentage = m_extendedAwningTargetPercentage.value(thing);
if (targetPercentage == currentPercentage) {
qCDebug(dcGenericShading()) << "Extended awning 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();
@ -230,6 +273,40 @@ void IntegrationPluginGenericShading::executeAction(ThingActionInfo *info)
} else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
}
} else if (thing->thingClassId() == extendedAwningThingClassId) {
if (action.actionTypeId() == extendedAwningOpenActionTypeId) {
setBlindState(BlindStateOpening, thing);
return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedAwningStopActionTypeId) {
setBlindState(BlindStateStopped, thing);
return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedAwningCloseActionTypeId) {
setBlindState(BlindStateClosing, thing);
return info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedAwningOpeningOutputActionTypeId) {
bool on = action.param(extendedAwningOpeningOutputActionOpeningOutputParamTypeId).value().toBool();
thing->setStateValue(extendedAwningOpeningOutputStateTypeId, on);
if (on) {
setBlindState(BlindStateOpening, thing);
} else {
setBlindState(BlindStateStopped, thing);
}
info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedAwningClosingOutputActionTypeId) {
bool on = action.param(extendedAwningClosingOutputActionClosingOutputParamTypeId).value().toBool();
thing->setStateValue(extendedAwningClosingOutputStateTypeId, on);
if (on) {
setBlindState(BlindStateClosing, thing);
} else {
setBlindState(BlindStateStopped, thing);
}
info->finish(Thing::ThingErrorNoError);
} else if (action.actionTypeId() == extendedAwningPercentageActionTypeId) {
moveBlindToPercentage(action, thing);
} 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");
@ -433,6 +510,31 @@ void IntegrationPluginGenericShading::setBlindState(IntegrationPluginGenericShad
m_extendedBlindPercentageTimer.value(thing)->stop();
break;
}
} else if (thing->thingClassId() == extendedAwningThingClassId) {
switch (state) {
case BlindStateOpening:
thing->setStateValue(extendedAwningStatusStateTypeId, "Opening");
thing->setStateValue(extendedAwningClosingOutputStateTypeId, false);
thing->setStateValue(extendedAwningOpeningOutputStateTypeId, true);
thing->setStateValue(extendedAwningMovingStateTypeId, true);
m_extendedAwningPercentageTimer.value(thing)->start();
break;
case BlindStateClosing:
thing->setStateValue(extendedAwningStatusStateTypeId, "Closing");
thing->setStateValue(extendedAwningClosingOutputStateTypeId, true);
thing->setStateValue(extendedAwningOpeningOutputStateTypeId, false);
thing->setStateValue(extendedAwningMovingStateTypeId, true);
m_extendedAwningPercentageTimer.value(thing)->start();
break;
case BlindStateStopped:
thing->setStateValue(extendedAwningStatusStateTypeId, "Stopped");
thing->setStateValue(extendedAwningClosingOutputStateTypeId, false);
thing->setStateValue(extendedAwningOpeningOutputStateTypeId, false);
thing->setStateValue(extendedAwningMovingStateTypeId, false);
m_extendedAwningPercentageTimer.value(thing)->stop();
break;
}
} else if (thing->thingClassId() == venetianBlindThingClassId) {
m_venetianBlindTargetAngle.remove(thing);
switch (state) {
@ -481,6 +583,22 @@ void IntegrationPluginGenericShading::moveBlindToPercentage(Action action, Thing
} else {
setBlindState(BlindStateStopped, thing);
}
} else if (thing->thingClassId() == extendedAwningThingClassId) {
uint targetPercentage = action.param(extendedAwningPercentageActionPercentageParamTypeId).value().toUInt();
uint currentPercentage = thing->stateValue(extendedAwningPercentageStateTypeId).toUInt();
// 100% indicates the device is fully closed
if (targetPercentage == currentPercentage) {
qCDebug(dcGenericShading()) << "Extended awningis already at given percentage" << targetPercentage;
} else if (targetPercentage > currentPercentage) {
setBlindState(BlindStateClosing, thing);
m_extendedAwningTargetPercentage.insert(thing, targetPercentage);
} else if (targetPercentage < currentPercentage) {
setBlindState(BlindStateOpening, thing);
m_extendedAwningTargetPercentage.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();

View File

@ -54,8 +54,10 @@ private:
double mapDoubleValue(double value, double fromMin, double fromMax, double toMin, double toMax);
QHash<Thing *, QTimer *> m_extendedBlindPercentageTimer;
QHash<Thing *, QTimer *> m_extendedAwningPercentageTimer;
QHash<Thing *, QTimer *> m_venetianBlindAngleTimer;
QHash<Thing *, uint> m_extendedBlindTargetPercentage;
QHash<Thing *, uint> m_extendedAwningTargetPercentage;
QHash<Thing *, int> m_venetianBlindTargetAngle;
enum BlindState {

View File

@ -69,6 +69,98 @@
}
]
},
{
"id": "be9ffcc5-28b9-4db9-aaec-d6e758776a60",
"name": "extendedAwning",
"displayName": "Generic awning with position control",
"createMethods": ["user"],
"interfaces": ["extendedawning"],
"settingsTypes": [
{
"id": "8f1d651d-3196-48c7-b752-9d906c44168c",
"name": "closingDuration",
"displayName": "Closing duration [ms]",
"type": "uint",
"minValue": 1000,
"defaultValue": 5000
}
],
"stateTypes": [
{
"id": "43c174e2-31d2-4256-a81f-09997ec1c0a3",
"name": "openingOutput",
"displayName": "Opening output",
"displayNameEvent": "Opening output changed",
"displayNameAction": "Set opening output",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput",
"writable": true
},
{
"id": "4992092c-d765-4764-a3d5-658171a74093",
"name": "closingOutput",
"displayName": "Closing output",
"displayNameEvent": "Closing output changed",
"displayNameAction": "Set closing output",
"type": "bool",
"defaultValue": false,
"ioType": "digitalInput",
"writable": true
},
{
"id": "c24f6229-91df-4ca5-8555-d6d5d948062c",
"name": "status",
"displayName": "Status",
"displayNameEvent": "Status changed",
"type": "QString",
"possibleValues": [
"Opening",
"Stopped",
"Closing"
],
"defaultValue": "Stopped"
},
{
"id": "010d3f47-7c05-4e71-a2f9-3f53958e8095",
"name": "moving",
"type": "bool",
"displayName": "Moving",
"displayNameEvent": "Moving changed",
"defaultValue": false
},
{
"id": "ce82e5d1-dbb8-4916-a966-a2ab85e4cda7",
"name": "percentage",
"displayName": "Percentage",
"displayNameEvent": "Percentage changed",
"displayNameAction": "Set percentage",
"type": "int",
"minValue": 0,
"maxValue": 100,
"defaultValue": 0,
"unit": "Percentage",
"writable": true
}
],
"actionTypes": [
{
"id": "4ee66b18-0c2b-4578-9ae1-34d816e84563",
"name": "open",
"displayName": "Open"
},
{
"id": "48ae5686-7bd6-4f10-a6a4-2ac502aafa5f",
"name": "stop",
"displayName": "Stop"
},
{
"id": "6e71e4a1-af8b-4a93-a66c-ef1782e03621",
"name": "close",
"displayName": "Close"
}
]
},
{
"id": "17ee3657-6ad8-4ae2-8959-3cf66cec8d13",
"name": "blind",