Added hood implementation.

Handled device disconnected.
This commit is contained in:
Paul Bot 2021-09-23 10:27:27 +03:00
parent 7d2de6f268
commit adbd78796a
5 changed files with 303 additions and 28 deletions

View File

@ -64,6 +64,7 @@ IntegrationPluginMiele::IntegrationPluginMiele()
m_mieleDeviceTypeLabelToThingClassId.insert("coffee system", coffeeMakerThingClassId);
m_mieleDeviceTypeLabelToThingClassId.insert("tumber dryer", dryerThingClassId);
m_mieleDeviceTypeLabelToThingClassId.insert("refrigerator", fridgeThingClassId);
m_mieleDeviceTypeLabelToThingClassId.insert("hood", hoodThingClassId);
}
@ -88,7 +89,9 @@ void IntegrationPluginMiele::startPairing(ThingPairingInfo *info)
void IntegrationPluginMiele::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
{
Q_UNUSED(username);
//Q_UNUSED(username);
qCDebug(dcMiele()) << "\n\n Confirm pairing for username: [" << username << "]";
if (info->thingClassId() == mieleAccountThingClassId) {
qCDebug(dcMiele()) << "Confirm pairing Miele account";
@ -166,6 +169,7 @@ void IntegrationPluginMiele::setupThing(ThingSetupInfo *info)
connect(info, &ThingSetupInfo::aborted, miele, &Miele::deleteLater);
connect(miele, &Miele::devicesFound, this, &IntegrationPluginMiele::onDevicesFound);
connect(miele, &Miele::deviceStateReceived, this, &IntegrationPluginMiele::onDeviceStateReceived);
connect(miele, &Miele::deviceNotFound, this, &IntegrationPluginMiele::onDeviceNotFound);
}
} else if (m_idParamTypeIds.contains(thing->thingClassId())) {
Thing *parentThing = myThings().findById(thing->parentId());
@ -212,8 +216,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing)
miele->getDevicesShort();
//miele->connectEventStream();
thing->setStateValue(mieleAccountConnectedStateTypeId, true);
thing->setStateValue(mieleAccountLoggedInStateTypeId, true);
//TBD Set user name
thing->setStateValue(mieleAccountLoggedInStateTypeId, true);
} else if (m_idParamTypeIds.contains(thing->thingClassId())) {
Thing *parentThing = myThings().findById(thing->parentId());
if (!parentThing)
@ -245,10 +248,58 @@ void IntegrationPluginMiele::executeAction(ThingActionInfo *info)
double targetTemp = action.param(fridgeTargetTemperatureActionTargetTemperatureParamTypeId).value().toDouble();
int iTargetTemp = floor(targetTemp);
qCDebug(dcMiele()) << "Setting fridge temp: " << iTargetTemp;
miele->setTargetTemperature(deviceId, 1, iTargetTemp);
QUuid requestId = miele->setTargetTemperature(deviceId, 1, iTargetTemp);
info->finish(Thing::ThingErrorNoError);
thing->setStateValue(fridgeTargetTemperatureStateTypeId, iTargetTemp);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
} else if (action.actionTypeId() == fridgeStartSuperCoolingActionTypeId) {
QUuid requestId = miele->processAction(deviceId, Miele::ProcessActionsStartSupercooling);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
// don't set state, it should come as event once it successfully started on the actual device
//thing->setStateValue(fridgePowerStateTypeId, !currentSuperCoolingState);
} else if (action.actionTypeId() == fridgeStopSuperCoolingActionTypeId) {
QUuid requestId = miele->processAction(deviceId, Miele::ProcessActionsStopSupercooling);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
}
} else if (thing->thingClassId() == hoodThingClassId) {
if (action.actionTypeId() == hoodStopHoodActionTypeId) {
// TODO: should check if current state of the hood allows the Stop action
QUuid requestId = miele->processAction(deviceId, Miele::ProcessActionsStop);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
} else if (action.actionTypeId() == hoodVentilationStepActionTypeId) {
int ventStep = action.param(hoodVentilationStepActionVentilationStepParamTypeId).value().toInt();
QUuid requestId = miele->setVentilationStep(deviceId, ventStep);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
} else if (action.actionTypeId() == hoodLightColorActionTypeId) {
QString color = action.param(hoodLightColorActionLightColorParamTypeId).value().toString();
QUuid requestId = miele->setColorsStr(deviceId, color);
m_pendingActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
} else if (action.actionTypeId() == hoodLightActionTypeId) {
bool power = action.param(hoodLightActionLightParamTypeId).value().toBool();
QUuid requestId = miele->setLight(deviceId, power);
connect(info, &ThingActionInfo::aborted, [requestId, this] {
m_pendingActions.remove(requestId);
});
}
} else if (thing->thingClassId() == ovenThingClassId) {
} else {
@ -358,7 +409,7 @@ void IntegrationPluginMiele::onDevicesFound(QList<Miele::DeviceShort> devices)
if(m_mieleConnections.values().contains(miele)) {
Thing *parentDevice = myThings().findById(m_mieleConnections.key(miele)->id());
qCDebug(dcMiele()) << devices.size() << " devices received for prent: " << parentDevice->id();
qCDebug(dcMiele()) << devices.size() << " devices received for parent: " << parentDevice->id();
ThingDescriptors descriptors;
foreach(Miele::DeviceShort ds, devices) {
@ -420,6 +471,7 @@ void IntegrationPluginMiele::setThingState(Thing *thing, const QVariantMap &stat
? false
: true;
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), connected);
thing->setStateValue(fridgeOperationStateStateTypeId, state.value("status").toMap().value("value_localized").toString());
// Fridges should have only one temperature zone
QVariant fridgeTempZone = state.value("temperature").toList().first();
@ -430,7 +482,60 @@ void IntegrationPluginMiele::setThingState(Thing *thing, const QVariantMap &stat
double fridgeTargetTemp = fridgeTargetTempZone.toMap().value("value_raw").toDouble();
thing->setStateValue(fridgeTargetTemperatureStateTypeId, fridgeTargetTemp / 100);
thing->setStateValue(fridgeSignalDoorStateTypeId, state.value("signalDoor").toBool());
thing->setStateValue(fridgeSignalInfoStateTypeId, state.value("signalInfo").toBool());
thing->setStateValue(fridgeSignalFailureStateTypeId, state.value("signalFailure").toBool());
QVariantMap remoteEnabledModes = state.value("remoteEnable").toMap();
thing->setStateValue(fridgeFullRemoteControlStateTypeId, remoteEnabledModes.value("fullRemoteControl").toBool());
thing->setStateValue(fridgeSmartGridStateTypeId, remoteEnabledModes.value("smartGrid").toBool());
thing->setStateValue(fridgeMobileStartStateTypeId, remoteEnabledModes.value("mobileStart").toBool());
} else if (thing->thingClassId() == hoodThingClassId) {
qCDebug(dcMiele()) << "Setting state for hood!";
int status = state.value("status").toMap().value("value_raw").toInt();
bool connected = (status == Miele::StatusNotConnected) ? false : true;
bool poweredOn = (status == Miele::StatusOff) ? false : true;
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), connected);
thing->setStateValue(hoodPowerStateTypeId, poweredOn);
thing->setStateValue(hoodOperationStateStateTypeId, state.value("status").toMap().value("value_localized").toString());
thing->setStateValue(hoodSignalInfoStateTypeId, state.value("signalInfo").toBool());
thing->setStateValue(hoodSignalFailureStateTypeId, state.value("signalFailure").toBool());
thing->setStateValue(hoodLightStateTypeId, state.value("light").toInt() != 0 ? true : false);
QVariantMap remoteEnabledModes = state.value("remoteEnable").toMap();
thing->setStateValue(hoodFullRemoteControlStateTypeId, remoteEnabledModes.value("fullRemoteControl").toBool());
thing->setStateValue(hoodSmartGridStateTypeId, remoteEnabledModes.value("smartGrid").toBool());
thing->setStateValue(hoodMobileStartStateTypeId, remoteEnabledModes.value("mobileStart").toBool());
int ventilationStep = state.value("ventilationStep").toMap().value("value_raw").toInt();
thing->setStateValue(hoodVentilationStepStateTypeId, ventilationStep);
} else {
qCWarning(dcMiele()) << "Device " << thing->name() << " is not yet supported!";
}
}
void IntegrationPluginMiele::onDeviceNotFound(const QString &deviceId)
{
Miele *miele = static_cast<Miele*>(sender());
if (!m_mieleConnections.values().contains(miele)) {
qCWarning(dcMiele()) << "Can't find Miele connection!";
return;
}
Thing *parentDevice = myThings().findById(m_mieleConnections.key(miele)->id());
if (!parentDevice) {
qCWarning(dcMiele()) << "Can't find parent thing!";
return;
}
foreach(Thing *thing, myThings().filterByParentId(parentDevice->id())) {
if (thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString() == deviceId) {
qCDebug(dcMiele()) << "Device not found anymore: " << thing->name();
emit autoThingDisappeared(thing->id());
break;
}
}
}

View File

@ -79,6 +79,7 @@ private slots:
void onDevicesFound(QList<Miele::DeviceShort> devices);
void onDeviceStateReceived(const QString &deviceId, const QVariantMap &deviceState);
void onDeviceNotFound(const QString &deviceId);
};
#endif // INTEGRATIONPLUGINMIELE_H

View File

@ -51,14 +51,6 @@
"displayNameEvent": "Logged in changed",
"defaultValue": true,
"type": "bool"
},
{
"id": "a5b85688-d319-4f61-8907-7da8a2b16d64",
"name": "userDisplayName",
"displayName": "User name",
"displayNameEvent": "User name changed",
"defaultValue": "",
"type": "QString"
}
]
},
@ -198,6 +190,38 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "2f2039bb-b0af-4272-a8ba-558589f49299",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Not Connected",
"type": "QString"
},
{
"id": "bafefd33-cfdb-4715-a1c1-fb3d4215f84c",
"name": "fullRemoteControl",
"displayName": "Full remote control",
"displayNameEvent": "Full remote control changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "89081d4a-5e46-4569-b0f9-52347491a013",
"name": "smartGrid",
"displayName": "Smart grid enabled",
"displayNameEvent": "Smart grid enabled changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "a878082e-a530-439a-9d71-dfe430fb4988",
"name": "mobileStart",
"displayName": "Mobile start enabled",
"displayNameEvent": "Mobile start enabled changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "ef656321-e2c8-4339-be18-aa3cdb53dea6",
@ -225,15 +249,40 @@
"ioType": "analogInput"
},
{
"id": "60a46368-febc-4cff-bbfb-99064dbb93a9",
"name": "power",
"displayName": "On/off",
"displayNameEvent": "Turned on/off",
"displayNameAction": "Turn on/off",
"type": "bool",
"id": "6954a425-e02e-4930-b073-1cc70805305a",
"name": "signalDoor",
"displayName": "Door open",
"displayNameEvent": "Door open changed",
"defaultValue": false,
"writable": true,
"ioType": "digitalInput"
"type": "bool"
},
{
"id": "0469a4b9-ec7d-444c-9aa3-410518ec41ef",
"name": "signalInfo",
"displayName": "Unread notification",
"displayNameEvent": "Unread notification changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "cbc573bd-ad3f-4d58-a796-b81bea14622d",
"name": "signalFailure",
"displayName": "Failure notification",
"displayNameEvent": "Failure notification changed",
"defaultValue": false,
"type": "bool"
}
],
"actionTypes": [
{
"id": "0b206df2-47aa-4f8a-9c14-ff483c539826",
"name": "startSuperCooling",
"displayName": "Start SuperCooling"
},
{
"id": "293568c2-5f8c-42f9-b150-769e181a8cbd",
"name": "stopSuperCooling",
"displayName": "Stop SuperCooling"
}
]
},
@ -296,7 +345,7 @@
"id": "707e46a5-9ca0-4375-8249-2de19ec669ec",
"name": "hood",
"displayName": "Hood",
"interfaces": ["connectable"],
"interfaces": ["power", "connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
@ -316,6 +365,115 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "2d5c88b4-34fd-4f15-b731-332dc905ef27",
"name": "power",
"displayName": "Power",
"displayNameEvent": "Powered on/off",
"displayNameAction": "Power on/off",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "db566fc5-383f-4726-a730-9dadac76e2d0",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Not Connected",
"type": "QString"
},
{
"id": "d64b646c-8405-4384-8aa3-02e288dc0603",
"name": "signalInfo",
"displayName": "Unread notification",
"displayNameEvent": "Unread notification changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "8da242c3-117c-4cb7-91f9-2bd34835e427",
"name": "signalFailure",
"displayName": "Failure notification",
"displayNameEvent": "Failure notification changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "dd97c6dd-94fd-4dd3-b2ce-812c40e6247b",
"name": "fullRemoteControl",
"displayName": "Full remote control",
"displayNameEvent": "Full remote control changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "0b1a6594-fda6-4c48-a898-7b54b30538f7",
"name": "smartGrid",
"displayName": "Smart grid enabled",
"displayNameEvent": "Smart grid enabled changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "363d5770-6f11-41c8-981c-9f1d49278b3c",
"name": "mobileStart",
"displayName": "Mobile start enabled",
"displayNameEvent": "Mobile start enabled changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "ae7044b9-3a46-4c98-bd02-2abded425c35",
"name": "ventilationStep",
"displayName": "Ventilation step",
"displayNameEvent": "Ventilation step changed",
"displayNameAction": "Set ventilation step",
"defaultValue": 0,
"type": "int",
"possibleValues": [
0, 1, 2, 3, 4
],
"writable": true
},
{
"id": "29d4fb9f-0ad3-4911-89c1-68789d58e00c",
"name": "light",
"displayName": "Light",
"displayNameEvent": "Light on/off changed",
"displayNameAction": "Set light on/off",
"defaultValue": false,
"type": "bool",
"writable": true
},
{
"id": "d5953bee-eb5a-4c3d-a7a4-3f24562f585d",
"name": "lightColor",
"displayName": "Light color",
"displayNameEvent": "Light color changed",
"displayNameAction": "Set light color",
"defaultValue": "white",
"type": "QString",
"writable": true,
"possibleValues": [
"white",
"blue",
"red",
"yellow",
"orange",
"green",
"pink",
"purple",
"turquoise"
]
}
],
"actionTypes": [
{
"id": "0aae84bb-5502-437c-b821-46ef26209e09",
"name": "stopHood",
"displayName": "Stop"
}
]
},

View File

@ -92,11 +92,7 @@ void Miele::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
qCWarning(dcMiele()) << "No refresh token given!";
setAuthenticated(false);
return;
}
//delete me
qCDebug(dcMiele()) << "Refresh token is not empty: " << refreshToken;
qCDebug(dcMiele()) << "Client: " << m_clientId << " secret: " << m_clientSecret;
}
QUrl url(m_tokenUrl);
QUrlQuery query;
@ -302,6 +298,10 @@ void Miele::getDeviceState(const QString &deviceId) {
QByteArray rawData = reply->readAll();
if (!checkStatusCode(reply, rawData)) {
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status == 404) {
emit deviceNotFound(deviceId);
}
return;
}
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
@ -387,6 +387,15 @@ QUuid Miele::setColors(const QString &deviceId, Miele::Color color)
return putAction(deviceId, doc);
}
QUuid Miele::setColorsStr(const QString &deviceId, const QString &color)
{
QJsonDocument doc;
QJsonObject object;
object.insert("colors", color.toLower());
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::setModes(const QString &deviceId, Miele::Mode mode)
{
QJsonDocument doc;

View File

@ -122,9 +122,10 @@ public:
QUuid setLight(const QString &deviceId, bool power);
QUuid setTargetTemperature(const QString &deviceId, int zone, int targetTemperature);
QUuid setColors(const QString &deviceId, Color color);
QUuid setColorsStr(const QString &deviceId, const QString &color);
QUuid setModes(const QString &deviceId, Mode mode);
QUuid setVentilationStep(const QString &deviceId, int step);
QUuid setStartTime(const QString &deviceId, int seconds);
QUuid setStartTime(const QString &deviceId, int seconds);
// EVENTS
void getAllEvents();
@ -162,6 +163,7 @@ signals:
void commandExecuted(const QUuid &commandId, bool success);
void devicesFound(QList<DeviceShort> devices);
void deviceStateReceived(const QString &deviceId, const QVariantMap &deviceState);
void deviceNotFound(const QString &deviceId);
private slots:
void onRefreshTimeout();