diff --git a/miele/integrationpluginmiele.cpp b/miele/integrationpluginmiele.cpp index b6ed7b48..0917f245 100644 --- a/miele/integrationpluginmiele.cpp +++ b/miele/integrationpluginmiele.cpp @@ -66,6 +66,14 @@ IntegrationPluginMiele::IntegrationPluginMiele() m_mieleDeviceTypeLabelToThingClassId.insert("refrigerator", fridgeThingClassId); m_mieleDeviceTypeLabelToThingClassId.insert("hood", hoodThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::Oven, ovenThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::WashingMachine, washerThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::DishWasher, dishwasherThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::CoffeeSystem, coffeeMakerThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::TumbleDryer, dryerThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::Fridge, fridgeThingClassId); + m_mieleDeviceTypeToThingClassId.insert(Miele::DeviceType::Hood, hoodThingClassId); + } void IntegrationPluginMiele::startPairing(ThingPairingInfo *info) @@ -202,7 +210,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing) qWarning(dcMiele()) << "No Miele account found for" << thing->name(); continue; } - miele->getDevicesShort(); + miele->getDevices(); Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) { QString deviceId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString(); miele->getDeviceState(deviceId); @@ -213,7 +221,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing) if (thing->thingClassId() == mieleAccountThingClassId) { Miele *miele = m_mieleConnections.value(thing); - miele->getDevicesShort(); + miele->getDevices(); miele->connectEventStream(); thing->setStateValue(mieleAccountConnectedStateTypeId, true); thing->setStateValue(mieleAccountLoggedInStateTypeId, true); @@ -413,12 +421,12 @@ void IntegrationPluginMiele::onDevicesFound(QList devices) ThingDescriptors descriptors; foreach(Miele::DeviceShort ds, devices) { - qCDebug(dcMiele()) << "Setting up device: " << ds.type << " " << ds.name << " " << ds.state; - if (!m_mieleDeviceTypeLabelToThingClassId.contains(ds.type.toLower())) { + qCDebug(dcMiele()) << "Setting up device: " << ds.type << " " << ds.name; + if (!m_mieleDeviceTypeToThingClassId.contains(ds.type)) { qCDebug(dcMiele()) << "Device type [" << ds.type << "] is not supported!"; continue; } - ThingClassId deviceClassId = m_mieleDeviceTypeLabelToThingClassId.value(ds.type.toLower()); + ThingClassId deviceClassId = m_mieleDeviceTypeToThingClassId.value(ds.type); ThingDescriptor descriptor(deviceClassId, ds.name, "Appliance type: " + ds.type, parentDevice->id()); ParamList params; params.append(Param(m_idParamTypeIds.value(deviceClassId), ds.fabNumber)); diff --git a/miele/integrationpluginmiele.h b/miele/integrationpluginmiele.h index 303b44ba..a9d68f4a 100644 --- a/miele/integrationpluginmiele.h +++ b/miele/integrationpluginmiele.h @@ -67,18 +67,19 @@ private: QHash m_idParamTypeIds; QHash m_connectedStateTypeIds; - QHash m_mieleDeviceTypeLabelToThingClassId; + QHash m_mieleDeviceTypeLabelToThingClassId; + QHash m_mieleDeviceTypeToThingClassId; Miele *createMieleConnection(); - void setThingState(Thing *thing, const QVariantMap &state); + void setThingState(Thing *thing, const QVariantMap &state); private slots: void onConnectionChanged(bool connected); void onAuthenticationStatusChanged(bool authenticated); void onRequestExecuted(QUuid requestId, bool success); - void onDevicesFound(QList devices); - void onDeviceStateReceived(const QString &deviceId, const QVariantMap &deviceState); + void onDevicesFound(QList devices); + void onDeviceStateReceived(const QString &deviceId, const QVariantMap &deviceState); void onDeviceNotFound(const QString &deviceId); }; diff --git a/miele/miele.cpp b/miele/miele.cpp index 7562357a..68e0cfb3 100644 --- a/miele/miele.cpp +++ b/miele/miele.cpp @@ -92,7 +92,7 @@ void Miele::getAccessTokenFromRefreshToken(const QByteArray &refreshToken) qCWarning(dcMiele()) << "No refresh token given!"; setAuthenticated(false); return; - } + } QUrl url(m_tokenUrl); QUrlQuery query; @@ -173,7 +173,7 @@ void Miele::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC } m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray(); receivedAccessToken(m_accessToken); - m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray(); + m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray(); receivedRefreshToken(m_refreshToken); if (jsonDoc.toVariant().toMap().contains("expires_in")) { @@ -184,7 +184,7 @@ void Miele::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC qCWarning(dcMiele()) << "Expire time too short"; return; } - m_accessTokenExpireTime = QDateTime::currentMSecsSinceEpoch() + (expireTime-(m_refreshInterval*1000)); + m_accessTokenExpireTime = QDateTime::currentMSecsSinceEpoch() + (expireTime-(m_refreshInterval*1000)); } }); } @@ -211,13 +211,23 @@ void Miele::getDevices() if (!checkStatusCode(reply, rawData)) { return; } - QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap(); - if (map.contains("data")) { - QVariantMap dataMap = map.value("data").toMap(); - qCDebug(dcMiele()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString(); - } else if (map.contains("error")) { - qCWarning(dcMiele()) << "Send command" << map.value("error").toMap().value("description").toString(); + QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap(); + + QList foundDevices; + foreach (QVariant deviceData, map.values()) { + QVariantMap deviceDetails = deviceData.toMap(); + if (!deviceDetails.contains("ident")) { + qCWarning(dcMiele()) << "Got device but no ident available"; + continue; + } + DeviceShort ds; + QVariantMap deviceIdentMap = deviceDetails.value("ident").toMap(); + ds.fabNumber = deviceIdentMap.value("deviceIdentLabel").toMap().value("fabNumber").toString(); + ds.name = deviceIdentMap.value("deviceName").toString(); + ds.type = static_cast(deviceIdentMap.value("type").toMap().value("value_raw").toInt()); + foundDevices.append(ds); } + emit devicesFound(foundDevices); }); } @@ -251,7 +261,7 @@ void Miele::getDevicesShort() ds.fabNumber = deviceObj["fabNumber"].toString(); ds.name = deviceObj["deviceName"].toString(); ds.state = deviceObj["state"].toString(); - ds.type = deviceObj["type"].toString(); + //ds.type = deviceObj["type"].toString(); foundDevices.append(ds); } emit devicesFound(foundDevices); @@ -373,7 +383,7 @@ QUuid Miele::setTargetTemperature(const QString &deviceId, int zone, int targetT QJsonArray tempZones; tempZones.push_front(temperatureObj); object.insert("targetTemperature", tempZones); - doc.setObject(object); + doc.setObject(object); return putAction(deviceId, doc); } @@ -440,16 +450,34 @@ void Miele::connectEventStream() connect(reply, &QNetworkReply::readyRead, this, [this, reply]{ while (reply->canReadLine()) { - QByteArray rawData = reply->readAll(); - qCDebug(dcMiele()) << "Raw events data: " << rawData; - QJsonDocument data = QJsonDocument::fromJson(rawData); - qCDebug(dcMiele()) << "Got events data: " << data.toJson(); + QByteArray eventTypeLine = reply->readLine(); + if (eventTypeLine == "\n") { + continue; + } + if (!eventTypeLine.startsWith("event")) { + qCWarning(dcMiele()) << "Invalid event type line: " << eventTypeLine; + return; + } + QString eventType = eventTypeLine.split(':').last().trimmed(); + if (eventType != "devices") { + qCWarning(dcMiele()) << "Ignoring '" << eventType << "' events"; + return; + } + QByteArray eventDataLine = reply->readLine(); + if (!eventDataLine.startsWith("data")) { + qCWarning(dcMiele()) << "Invalid data received: " << eventDataLine; + return; + } + + qCDebug(dcMiele()) << "Raw events data: " << eventDataLine; + QJsonDocument data = QJsonDocument::fromJson(eventDataLine.replace("data: ", "")); + qCDebug(dcMiele()) << "Got events data: " << data.toJson(QJsonDocument::Compact); QVariantMap eventsData = data.toVariant().toMap(); foreach (QVariant eventEntry, eventsData.values()) { QVariantMap eventEntryMap = eventEntry.toMap(); if (!eventEntryMap.contains("ident")) { qCWarning(dcMiele()) << "Got event but no device ident available"; - return; + continue; } QVariantMap deviceIdent = eventEntryMap.value("ident").toMap().value("deviceIdentLabel").toMap(); QString deviceId = deviceIdent.value("fabNumber").toString(); diff --git a/miele/miele.h b/miele/miele.h index 3532758d..d6882e46 100644 --- a/miele/miele.h +++ b/miele/miele.h @@ -90,12 +90,40 @@ public: StatusNotConnected = 255 }; + enum DeviceType { + WashingMachine = 1, + TumbleDryer = 2, + DishWasher = 7, + Oven = 12, + OvenMicrowave = 13, + HobHighlight = 14, + SteamOven = 15, + MicroWave = 16, + CoffeeSystem = 17, + Hood = 18, + Fridge = 19, + Freezer = 20, + FridgeFreezer = 21, + VacuumCleaner = 23, + WasherDryer = 24, + DishWarmer = 25, + HobInduction = 27, + SteamOvenCombination = 31, + WineCabinet = 32, + WineConditioningUnit = 33, + WineStorageConditioningUnit = 34, + SteamOvenMicrowaveCombination = 45, + VacuumDrawer = 48, + DialogOven= 67, + WineCabinetFreezerCombination = 68 + }; + struct DeviceShort { QString details; QString name; QString fabNumber; QString state; - QString type; + DeviceType type; }; Miele(NetworkAccessManager *networkmanager, const QByteArray &clientId, const QByteArray &clientSecret, const QString &language = "en", QObject *parent = nullptr); @@ -125,7 +153,7 @@ public: 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 connectEventStream();