From ff48a4788c91b79fc33a0d64029934a7068f45c5 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 21 Jul 2020 09:41:58 +0200 Subject: [PATCH] added status parsing --- homeconnect/homeconnect.cpp | 56 ++++++++++++++++---- homeconnect/homeconnect.h | 23 +++++++- homeconnect/integrationpluginhomeconnect.cpp | 56 +++++++++++++++++--- homeconnect/integrationpluginhomeconnect.h | 7 +++ 4 files changed, 126 insertions(+), 16 deletions(-) diff --git a/homeconnect/homeconnect.cpp b/homeconnect/homeconnect.cpp index 1fa9f812..5ec08a34 100644 --- a/homeconnect/homeconnect.cpp +++ b/homeconnect/homeconnect.cpp @@ -371,20 +371,17 @@ void HomeConnect::getStatus(const QString &haid) QJsonParseError error; QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); if (error.error != QJsonParseError::NoError) { - qCDebug(dcHomeConnect()) << "Get status: Recieved invalide JSON object"; + qCDebug(dcHomeConnect()) << "Get status: Received invalide JSON object"; return; } - QHash statusList; + QHash statusList; qCDebug(dcHomeConnect()) << "Get status" << data.toJson(); QVariantList statusVariantList= data.toVariant().toMap().value("data").toMap().value("status").toList(); Q_FOREACH(QVariant status, statusVariantList) { QVariantMap map = status.toMap(); - if (map.value("key") == "BSH.Common.Status.OperationState") { - qCDebug(dcHomeConnect()) << map.value("value").toString(); - } - statusList.insert(map.value("key").toString(), map.value("value").toString()); + statusList.insert(map.value("key").toString(), map.value("value")); } - emit receivedStatus(haid, statusList); + emit receivedStatusList(haid, statusList); }); } @@ -413,7 +410,7 @@ void HomeConnect::getSettings(const QString &haid) QJsonParseError error; QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); if (error.error != QJsonParseError::NoError) { - qCDebug(dcHomeConnect()) << "Get settings: Recieved invalide JSON object"; + qCDebug(dcHomeConnect()) << "Get settings: Received invalide JSON object"; return; } qCDebug(dcHomeConnect()) << "Get settings" << data.toJson(); @@ -426,6 +423,47 @@ void HomeConnect::getSettings(const QString &haid) }); } +void HomeConnect::connectEventStream() +{ + QUuid commandId = QUuid::createUuid(); + QUrl url = QUrl(m_baseControlUrl+"/api/homeappliances/events"); + + QNetworkRequest request(url); + request.setRawHeader("Authorization", "Bearer "+m_accessToken); + request.setRawHeader("Accept-Language", "en-US"); + request.setRawHeader("accept", "text/event-stream"); + + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + connect(reply, &QNetworkReply::readyRead, this, [this, reply]{ + + QJsonParseError error; + QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { + qCDebug(dcHomeConnect()) << "Event stream: Received invalide JSON object"; + return; + } + if (data.toVariant().toMap().contains("items")) { + QList events; + QVariantList itemsList = data.toVariant().toMap().value("items").toList(); + Q_FOREACH(QVariant item, itemsList) { + QVariantMap map = item.toMap(); + Event event; + event.key = map["key"].toString(); + event.uri = map["uri"].toString(); + event.name = map["uri"].toString(); + event.value = map["value"]; + event.unit = map["unit"].toString(); + event.timestamp = map["timestamp"].toInt(); + events.append(event); + } + emit receivedEvents(events); + } else if (data.toVariant().toMap().contains("error")) { + qCWarning(dcHomeConnect()) << "Event stream error" << data.toVariant().toMap().value("error"); + } + }); +} + QUuid HomeConnect::sendCommand(const QString &haid, const QString &command) { QUuid commandId = QUuid::createUuid(); @@ -450,7 +488,7 @@ QUuid HomeConnect::sendCommand(const QString &haid, const QString &command) QJsonParseError error; QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); if (error.error != QJsonParseError::NoError) { - qCDebug(dcHomeConnect()) << "Send command: Recieved invalide JSON object"; + qCDebug(dcHomeConnect()) << "Send command: Received invalide JSON object"; return; } qCDebug(dcHomeConnect()) << "Send command" << data.toJson(); diff --git a/homeconnect/homeconnect.h b/homeconnect/homeconnect.h index e6ed79e6..afed0c0c 100644 --- a/homeconnect/homeconnect.h +++ b/homeconnect/homeconnect.h @@ -77,6 +77,25 @@ public: }; + /* + "key": "Cooking.Oven.Option.SetpointTemperature", + "name": "Target temperature for the oven", + "uri": "/api/homeappliances/BOSCH-HNG6764B6-0000000011FF/programs/active/options/Cooking.Oven.Option.SetpointTemperature", + "timestamp": 1556793979, + "level": "hint", + "handling": "none", + "value": 200, + "unit": "°C" + */ + struct Event { + QString key; + QString name; + QString uri; + int timestamp; + QVariant value; + QString unit; + }; + HomeConnect(NetworkAccessManager *networkmanager, const QByteArray &clientKey, const QByteArray &clientSecret, bool simulationMode = false, QObject *parent = nullptr); QByteArray accessToken(); QByteArray refreshToken(); @@ -96,6 +115,7 @@ public: void getStatus(const QString &haid); void getSettings(const QString &haid); + void connectEventStream(); QUuid sendCommand(const QString &haid, const QString &command); //commands "BSH.Common.Command.ResumeProgram" & "PauseProgram" private: @@ -122,8 +142,9 @@ signals: void authenticationStatusChanged(bool authenticated); void commandExecuted(QUuid commandId,bool success); - void receivedStatus(const QString &haId, const QHash &statusList); + void receivedStatusList(const QString &haId, const QHash &statusList); void receivedHomeAppliances(const QList &appliances); void receivedAvailablePrograms(); + void receivedEvents(const QList events); }; #endif // HOMECONNECT_H diff --git a/homeconnect/integrationpluginhomeconnect.cpp b/homeconnect/integrationpluginhomeconnect.cpp index 3d5a02e0..88c96bd7 100644 --- a/homeconnect/integrationpluginhomeconnect.cpp +++ b/homeconnect/integrationpluginhomeconnect.cpp @@ -59,6 +59,16 @@ IntegrationPluginHomeConnect::IntegrationPluginHomeConnect() m_connectedStateTypeIds.insert(cookTopThingClassId, cookTopConnectedStateTypeId); m_connectedStateTypeIds.insert(cleaningRobotThingClassId, cleaningRobotConnectedStateTypeId); m_connectedStateTypeIds.insert(hoodThingClassId, hoodConnectedStateTypeId); + + m_localControlStateTypeIds.insert(ovenThingClassId, ovenLocalControlStateStateTypeId); + + m_remoteStartAllowanceStateTypeIds.insert(ovenThingClassId, ovenRemoteStartAllowanceStateStateTypeId); + + m_remoteControlActivationStateTypeIds.insert(ovenThingClassId, ovenRemoteControlActivationStateStateTypeId); + + m_doorStateTypeIds.insert(ovenThingClassId, ovenDoorStateEventTypeId); + + m_operationStateTypeIds.insert(ovenThingClassId, ovenOperationStateEventTypeId); } void IntegrationPluginHomeConnect::startPairing(ThingPairingInfo *info) @@ -141,6 +151,8 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info) connect(homeConnect, &HomeConnect::commandExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted); connect(homeConnect, &HomeConnect::authenticationStatusChanged, this, &IntegrationPluginHomeConnect::onAuthenticationStatusChanged); connect(homeConnect, &HomeConnect::receivedHomeAppliances, this, &IntegrationPluginHomeConnect::onReceivedHomeAppliances); + connect(homeConnect, &HomeConnect::receivedStatusList, this, &IntegrationPluginHomeConnect::onReceivedStatusList); + //TODO add settings received m_homeConnectConnections.insert(thing, homeConnect); info->finish(Thing::ThingErrorNoError); } else { @@ -154,6 +166,8 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info) connect(homeConnect, &HomeConnect::commandExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted); connect(homeConnect, &HomeConnect::authenticationStatusChanged, this, &IntegrationPluginHomeConnect::onAuthenticationStatusChanged); connect(homeConnect, &HomeConnect::receivedHomeAppliances, this, &IntegrationPluginHomeConnect::onReceivedHomeAppliances); + connect(homeConnect, &HomeConnect::receivedStatusList, this, &IntegrationPluginHomeConnect::onReceivedStatusList); + //TODO add settings received homeConnect->getAccessTokenFromRefreshToken(refreshToken); m_asyncSetup.insert(homeConnect, info); } @@ -303,7 +317,7 @@ void IntegrationPluginHomeConnect::browseThing(BrowseResult *result) return; QString haid = thing->stateValue(m_idParamTypeIds.value(thing->thingClassId())).toString(); homeConnect->getProgramsAvailable(haid); - connect(homeConnect, &HomeConnect::re) + //connect(homeConnect, &HomeConnect::re) } } @@ -318,7 +332,7 @@ void IntegrationPluginHomeConnect::executeBrowserItem(BrowserActionInfo *info) { Q_UNUSED(info) Thing *thing = info->thing(); - qCDebug(dcHomeConnect()) << "Execute browse item called " << thing->name(); + qCDebug(dcHomeConnect()) << "Execute browse item called " << thing->name(); } void IntegrationPluginHomeConnect::onConnectionChanged(bool connected) @@ -439,15 +453,45 @@ void IntegrationPluginHomeConnect::onReceivedHomeAppliances(QList statusList) +void IntegrationPluginHomeConnect::onReceivedStatusList(const QString &haId, const QHash &statusList) { HomeConnect *homeConnectConnection = static_cast(sender()); Thing *parentThing = m_homeConnectConnections.key(homeConnectConnection); if (!parentThing) return; - if (statusList.contains("BSH.Common.Status.LocalControlActive")) { - + Q_FOREACH(Thing *thing, myThings().filterByParentId(parentThing->id())) { + if (thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString() == haId) { + if (statusList.contains("BSH.Common.Status.LocalControlActive")) { + if (m_localControlStateTypeIds.contains(thing->thingClassId())) { + thing->setStateValue(m_localControlStateTypeIds.value(thing->thingClassId()), statusList.value("BSH.Common.Status.LocalControlActive").toBool()); + } + } + if (statusList.contains("BSH.Common.Status.RemoteControlActive")) { + if (m_remoteControlActivationStateTypeIds.contains(thing->thingClassId())) { + thing->setStateValue(m_remoteControlActivationStateTypeIds.value(thing->thingClassId()), statusList.value("BSH.Common.Status.RemoteControlActive").toBool()); + } + } + if (statusList.contains("BSH.Common.Status.RemoteControlStartAllowed")) { + if (m_remoteStartAllowanceStateTypeIds.contains(thing->thingClassId())) { + thing->setStateValue(m_remoteStartAllowanceStateTypeIds.value(thing->thingClassId()), statusList.value("BSH.Common.Status.RemoteControlStartAllowed").toBool()); + } + } + if (statusList.contains("BSH.Common.Status.DoorState")) { + if (m_doorStateTypeIds.contains(thing->thingClassId())) { + thing->setStateValue(m_doorStateTypeIds.value(thing->thingClassId()), statusList.value("BSH.Common.Status.DoorState").toString().split('.').last()); + } + } + if (statusList.contains("BSH.Common.Status.OperationState")) { + if (m_operationStateTypeIds.contains(thing->thingClassId())) { + thing->setStateValue(m_operationStateTypeIds.value(thing->thingClassId()), statusList.value("BSH.Common.Status.OperationState").toString().split('.').last()); + } + } + } } - +} + +void IntegrationPluginHomeConnect::onReceivedEvents(const QList events) +{ + Q_UNUSED(events) } diff --git a/homeconnect/integrationpluginhomeconnect.h b/homeconnect/integrationpluginhomeconnect.h index c4c8ce6b..e78f1b7a 100644 --- a/homeconnect/integrationpluginhomeconnect.h +++ b/homeconnect/integrationpluginhomeconnect.h @@ -72,6 +72,12 @@ private: QHash m_idParamTypeIds; QHash m_connectedStateTypeIds; + QHash m_doorStateStateTypeIds; + QHash m_localControlStateTypeIds; + QHash m_remoteControlActivationStateTypeIds; + QHash m_remoteStartAllowanceStateTypeIds; + QHash m_operationStateTypeIds; + QHash m_doorStateTypeIds; HomeConnect *createHomeConnection(); @@ -81,6 +87,7 @@ private slots: void onRequestExecuted(QUuid requestId, bool success); void onReceivedHomeAppliances(QList appliances); void onReceivedStatusList(const QString &haId, const QHash &statusList); + void onReceivedEvents(const QList events); }; #endif // INTEGRATIONPLUGINHOMECONNECT_H