diff --git a/tado/integrationplugintado.cpp b/tado/integrationplugintado.cpp index 318d6bcb..5ed34da5 100644 --- a/tado/integrationplugintado.cpp +++ b/tado/integrationplugintado.cpp @@ -63,7 +63,6 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString { qCDebug(dcTado()) << "Confirm pairing" << username << "password" << password << "Network manager available" << hardwareManager()->networkManager()->available(); Tado *tado = new Tado(hardwareManager()->networkManager(), username, this); - connect(tado, &Tado::tokenReceived, this, &IntegrationPluginTado::onTokenReceived); connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged); connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted); connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged); @@ -72,21 +71,31 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived); connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived); m_unfinishedTadoAccounts.insert(info->thingId(), tado); - m_unfinishedDevicePairings.insert(info->thingId(), info); - tado->getToken(password); connect(info, &ThingPairingInfo::aborted, this, [info, tado, this]() { qCWarning(dcTado()) << "Thing pairing has been aborted, going to clean-up"; - m_unfinishedDevicePairings.remove(info->thingId()); m_unfinishedTadoAccounts.remove(info->thingId()); tado->deleteLater(); - //TODO clean up plugin storage }); - pluginStorage()->beginGroup(info->thingId().toString()); - pluginStorage()->setValue("username", username); - pluginStorage()->setValue("password", password); - pluginStorage()->endGroup(); + connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){ + if (error != QNetworkReply::NetworkError::NoError){ + info->finish(Thing::ThingErrorSetupFailed); + } + // info->finish(success) will be called after the token has been received + }); + + connect(tado, &Tado::tokenReceived, info, [this, info, username, password](Tado::Token token) { + Q_UNUSED(token) + + pluginStorage()->beginGroup(info->thingId().toString()); + pluginStorage()->setValue("username", username); + pluginStorage()->setValue("password", password); + pluginStorage()->endGroup(); + + info->finish(Thing::ThingErrorNoError); + }); + tado->getToken(password); } void IntegrationPluginTado::setupThing(ThingSetupInfo *info) @@ -108,7 +117,6 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info) pluginStorage()->endGroup(); tado = new Tado(hardwareManager()->networkManager(), username, this); - connect(tado, &Tado::tokenReceived, this, &IntegrationPluginTado::onTokenReceived); connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged); connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted); connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged); @@ -116,14 +124,43 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info) connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived); connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived); connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived); - tado->getToken(password); + m_tadoAccounts.insert(thing->id(), tado); - m_asyncDeviceSetup.insert(tado, info); connect(info, &ThingSetupInfo::aborted, [info, this] { - Tado *tado = m_tadoAccounts.take(info->thing()->id()); - m_asyncDeviceSetup.remove(tado); - tado->deleteLater(); + if (m_tadoAccounts.contains(info->thing()->id())) { + Tado *tado = m_tadoAccounts.take(info->thing()->id()); + tado->deleteLater(); + } }); + + connect(tado, &Tado::tokenReceived, info, [this, info, tado](Tado::Token token) { + Q_UNUSED(token) + + qCDebug(dcTado()) << "Token received, account setup successfull"; + info->finish(Thing::ThingErrorNoError); + }); + + connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){ + if (error == QNetworkReply::NetworkError::HostNotFoundError) { + QTimer::singleShot(2000, info, [info, this] { + + pluginStorage()->beginGroup(info->thing()->id().toString()); + QString password = pluginStorage()->value("password").toString(); + pluginStorage()->endGroup(); + if (m_tadoAccounts.contains(info->thing()->id())) { + Tado *tado = m_tadoAccounts.take(info->thing()->id()); + tado->getToken(password); + } + }); + } else if (error != QNetworkReply::NetworkError::NoError){ + if (m_tadoAccounts.contains(info->thing()->id())) { + Tado *tado = m_tadoAccounts.take(info->thing()->id()); + tado->deleteLater(); + } + info->finish(Thing::ThingErrorSetupFailed); + } + }); + tado->getToken(password); } } else if (thing->thingClassId() == zoneThingClassId) { @@ -250,20 +287,6 @@ void IntegrationPluginTado::onConnectionChanged(bool connected) { Tado *tado = static_cast(sender()); - if (m_asyncDeviceSetup.contains(tado)) { - //Thing setup failed, try as long as ThingSetupInfo is valid. - if (!connected) { - QTimer::singleShot(2000, tado, [tado, this]{ - if(m_asyncDeviceSetup.contains(tado)){ - //Check once more if the ThingSetupInfo is still valid - pluginStorage()->beginGroup(m_asyncDeviceSetup.value(tado)->thing()->id().toString()); - QString password = pluginStorage()->value("password").toString(); - pluginStorage()->endGroup(); - tado->getToken(password); - } - }); - } - } if (m_tadoAccounts.values().contains(tado)){ Thing *thing = myThings().findById(m_tadoAccounts.key(tado)); if (!thing) @@ -280,18 +303,6 @@ void IntegrationPluginTado::onAuthenticationStatusChanged(bool authenticated) { Tado *tado = static_cast(sender()); - if (m_unfinishedTadoAccounts.values().contains(tado) && !authenticated){ - qCWarning(dcTado()) << "Authentication Status changed: " << authenticated << "removing unfinished Tado account"; - ThingId id = m_unfinishedTadoAccounts.key(tado); - m_unfinishedTadoAccounts.remove(id); - - if (m_unfinishedDevicePairings.contains(id)) { - qCWarning(dcTado()) << "Removing unfinished device pairing"; - ThingPairingInfo *info = m_unfinishedDevicePairings.take(id); - info->finish(Thing::ThingErrorSetupFailed); - } - } - if (m_tadoAccounts.values().contains(tado)){ Thing *thing = myThings().findById(m_tadoAccounts.key(tado)); if (!thing){ @@ -325,28 +336,6 @@ void IntegrationPluginTado::onRequestExecuted(QUuid requestId, bool success) } } -void IntegrationPluginTado::onTokenReceived(Tado::Token token) -{ - Q_UNUSED(token) - - qCDebug(dcTado()) << "Token received"; - Tado *tado = static_cast(sender()); - - if (m_asyncDeviceSetup.contains(tado)) { - ThingSetupInfo *info = m_asyncDeviceSetup.take(tado); - info->finish(Thing::ThingErrorNoError); - } - - if (m_unfinishedTadoAccounts.values().contains(tado)) { - qCDebug(dcTado()) << "onTokenReceived: Finishing pairing process"; - ThingId id = m_unfinishedTadoAccounts.key(tado); - if (m_unfinishedDevicePairings.contains(id)) { - ThingPairingInfo *info = m_unfinishedDevicePairings.take(id); - info->finish(Thing::ThingErrorNoError); - } - } -} - void IntegrationPluginTado::onHomesReceived(QList homes) { qCDebug(dcTado()) << "Homes received"; diff --git a/tado/integrationplugintado.h b/tado/integrationplugintado.h index 23c46063..28d344bf 100644 --- a/tado/integrationplugintado.h +++ b/tado/integrationplugintado.h @@ -57,10 +57,8 @@ public: private: PluginTimer *m_pluginTimer = nullptr; QHash m_unfinishedTadoAccounts; - QHash m_unfinishedDevicePairings; QHash m_tadoAccounts; - QHash m_asyncDeviceSetup; QHash m_asyncActions; private slots: @@ -69,7 +67,6 @@ private slots: void onConnectionChanged(bool connected); void onAuthenticationStatusChanged(bool authenticated); void onRequestExecuted(QUuid requestId, bool success); - void onTokenReceived(Tado::Token token); void onHomesReceived(QList homes); void onZonesReceived(const QString &homeId, QList zones); void onZoneStateReceived(const QString &homeId,const QString &zoneId, Tado::ZoneState sate); diff --git a/tado/tado.cpp b/tado/tado.cpp index b9d20c62..71338c39 100644 --- a/tado/tado.cpp +++ b/tado/tado.cpp @@ -87,6 +87,7 @@ void Tado::getToken(const QString &password) int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // Check HTTP status code if (status != 200 || reply->error() != QNetworkReply::NoError) { + emit connectionError(reply->error()); if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } @@ -136,6 +137,10 @@ void Tado::getToken(const QString &password) void Tado::getHomes() { + if(m_accessToken.isEmpty()) { + qCWarning(dcTado()) << "Not sending request, get the access token first"; + return; + } QNetworkRequest request; request.setUrl(QUrl(m_baseControlUrl + "/me")); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded"); @@ -149,6 +154,7 @@ void Tado::getHomes() // Check HTTP status code if (status != 200 || reply->error() != QNetworkReply::NoError) { + emit connectionError(reply->error()); if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } @@ -229,6 +235,10 @@ void Tado::getZones(const QString &homeId) void Tado::getZoneState(const QString &homeId, const QString &zoneId) { + if(m_accessToken.isEmpty()) { + qCWarning(dcTado()) << "Not sending request, get the access token first"; + return; + } QNetworkRequest request; request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/state")); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded"); @@ -242,6 +252,8 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId) // Check HTTP status code if (status != 200 || reply->error() != QNetworkReply::NoError) { + emit connectionError(reply->error()); + if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } @@ -295,6 +307,10 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId) QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature) { + if(m_accessToken.isEmpty()) { + qCWarning(dcTado()) << "Not sending request, get the access token first"; + return ""; + } QUuid requestId = QUuid::createUuid(); QNetworkRequest request; request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay")); @@ -318,6 +334,8 @@ QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, // Check HTTP status code if (status != 200 || reply->error() != QNetworkReply::NoError) { emit requestExecuted(requestId, false); + emit connectionError(reply->error()); + if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } @@ -358,6 +376,10 @@ QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId) { + if(m_accessToken.isEmpty()) { + qCWarning(dcTado()) << "Not sending request, get the access token first"; + return ""; + } QUuid requestId = QUuid::createUuid(); QNetworkRequest request; request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay")); @@ -371,6 +393,7 @@ QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId) // Check HTTP status code if (status < 200 || status > 210 || reply->error() != QNetworkReply::NoError) { emit requestExecuted(requestId ,false); + emit connectionError(reply->error()); if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } @@ -432,6 +455,11 @@ void Tado::setConnectionStatus(bool status) void Tado::onRefreshTimer() { + if(m_refreshToken.isEmpty()) { + qCWarning(dcTado()) << "Not sending request, get the access token first"; + return; + } + QNetworkRequest request; request.setUrl(QUrl(m_baseAuthorizationUrl)); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded"); @@ -450,6 +478,7 @@ void Tado::onRefreshTimer() // Check HTTP status code if (status != 200 || reply->error() != QNetworkReply::NoError) { + emit connectionError(reply->error()); if (reply->error() == QNetworkReply::HostNotFoundError) { setConnectionStatus(false); } diff --git a/tado/tado.h b/tado/tado.h index 1efa7a76..1e813130 100644 --- a/tado/tado.h +++ b/tado/tado.h @@ -42,6 +42,7 @@ class Tado : public QObject { Q_OBJECT public: + struct Token { QString accesToken; QString tokenType; @@ -65,7 +66,6 @@ public: QString tadoMode; }; - struct ZoneState { bool connected; bool power; @@ -131,6 +131,7 @@ signals: void zonesReceived(const QString &homeId, QList zones); void zoneStateReceived(const QString &homeId,const QString &zoneId, ZoneState sate); void overlayReceived(const QString &homeId, const QString &zoneId, const Overlay &overlay); + void connectionError(QNetworkReply::NetworkError error); private slots: void onRefreshTimer();