added dyn. api credentials optaining

This commit is contained in:
Boernsman 2020-10-27 13:08:25 +01:00
parent df59d45e83
commit bc2ff5b7be
3 changed files with 125 additions and 39 deletions

View File

@ -63,13 +63,6 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
{
qCDebug(dcTado()) << "Confirm pairing" << username << "Network manager available" << hardwareManager()->networkManager()->available();
Tado *tado = new Tado(hardwareManager()->networkManager(), username, this);
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
m_unfinishedTadoAccounts.insert(info->thingId(), tado);
connect(info, &ThingPairingInfo::aborted, this, [info, tado, this]() {
@ -78,13 +71,18 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
tado->deleteLater();
});
connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){
connect(tado, &Tado::connectionError, info, [info] (QNetworkReply::NetworkError error){
if (error != QNetworkReply::NetworkError::NoError){
info->finish(Thing::ThingErrorSetupFailed);
qCWarning(dcTado()) << "Confirm pairing failed" << error;
info->finish(Thing::ThingErrorSetupFailed, tr("Connection error"));
}
// info->finish(success) will be called after the token has been received
});
connect(tado, &Tado::apiCredentialsReceived, info, [password, tado] {
tado->getToken(password);
});
connect(tado, &Tado::tokenReceived, info, [this, info, username, password](Tado::Token token) {
Q_UNUSED(token)
@ -95,7 +93,7 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
info->finish(Thing::ThingErrorNoError);
});
tado->getToken(password);
tado->getApiCredentials();
}
void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
@ -109,7 +107,7 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
if (m_unfinishedTadoAccounts.contains(thing->id())) {
tado = m_unfinishedTadoAccounts.take(thing->id());
m_tadoAccounts.insert(thing->id(), tado);
return info->finish(Thing::ThingErrorNoError);
info->finish(Thing::ThingErrorNoError);
} else {
pluginStorage()->beginGroup(thing->id().toString());
QString username = pluginStorage()->value("username").toString();
@ -117,14 +115,6 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
pluginStorage()->endGroup();
tado = new Tado(hardwareManager()->networkManager(), username, this);
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
m_tadoAccounts.insert(thing->id(), tado);
connect(info, &ThingSetupInfo::aborted, [info, this] {
if (m_tadoAccounts.contains(info->thing()->id())) {
@ -133,7 +123,11 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
}
});
connect(tado, &Tado::tokenReceived, info, [this, info, tado](Tado::Token token) {
connect(tado, &Tado::apiCredentialsReceived, info, [password, tado] {
tado->getToken(password);
});
connect(tado, &Tado::tokenReceived, info, [ info](Tado::Token token) {
Q_UNUSED(token)
qCDebug(dcTado()) << "Token received, account setup successfull";
@ -141,18 +135,7 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
});
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 (error != QNetworkReply::NetworkError::NoError){
if (m_tadoAccounts.contains(info->thing()->id())) {
Tado *tado = m_tadoAccounts.take(info->thing()->id());
tado->deleteLater();
@ -160,15 +143,23 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
info->finish(Thing::ThingErrorSetupFailed);
}
});
tado->getToken(password);
tado->getApiCredentials();
}
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
return;
} else if (thing->thingClassId() == zoneThingClassId) {
qCDebug(dcTado) << "Setup tado thermostat" << thing->params();
return info->finish(Thing::ThingErrorNoError);
} else {
return info->finish(Thing::ThingErrorThingClassNotFound);
qCWarning(dcTado()) << "Unhandled thing class in setupDevice";
return info->finish(Thing::ThingErrorThingClassNotFound);
}
}

View File

@ -56,6 +56,11 @@ QString Tado::username()
return m_username;
}
bool Tado::apiAvailable()
{
return m_apiAvailable;
}
bool Tado::authenticated()
{
return m_authenticationStatus;
@ -66,8 +71,61 @@ bool Tado::connected()
return m_connectionStatus;
}
void Tado::getApiCredentials(const QString &url)
{
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
qCDebug(dcTado()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [reply, this] {
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
return;
}
QRegExp filter;
filter.setPatternSyntax(QRegExp::Wildcard);
filter.setPattern("*tgaRestApiV2Endpoint:*");
QStringList list = QString(reply->readAll()).split('\n');
int index = list.indexOf(filter);
if (index == -1)
return;
m_baseControlUrl = list.value(index).split(": ").last().remove(QRegExp("[,']"));;
qCDebug(dcTado()) << "Received control url" << m_baseControlUrl;
filter.setPattern("*apiEndpoint*");
index = list.indexOf(filter);
if (index == -1)
return;
m_baseAuthorizationUrl = list.value(index).split(": ").last().remove(QRegExp("[,']"))+"/token";
qCDebug(dcTado()) << "Received auth url" << m_baseAuthorizationUrl;
filter.setPattern("*clientId*");
index = list.indexOf(filter);
if (index == -1)
return;
m_clientId = list.value(index).split(": ").last().remove(QRegExp("[,']"));
qCDebug(dcTado()) << "Received client id" << m_clientId;
filter.setPattern("*clientSecret*");
index = list.indexOf(filter);
if (index == -1)
return;
m_clientSecret = list.value(index).split(": ").last().remove(QRegExp("[,']"));
qCDebug(dcTado()) << "Received client secret" << m_clientSecret;
m_apiAvailable = true;
emit apiCredentialsReceived();
});
}
void Tado::getToken(const QString &password)
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return;
}
QNetworkRequest request;
request.setUrl(QUrl(m_baseAuthorizationUrl));
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
@ -102,7 +160,7 @@ void Tado::getToken(const QString &password)
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcTado()) << "Get Token: Received invalide JSON object";
qDebug(dcTado()) << "Get Token: Received invalide JSON object:" << data;
return;
}
if (data.isObject()) {
@ -137,6 +195,11 @@ void Tado::getToken(const QString &password)
void Tado::getHomes()
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return;
}
if(m_accessToken.isEmpty()) {
qCWarning(dcTado()) << "Not sending request, get the access token first";
return;
@ -188,6 +251,16 @@ void Tado::getHomes()
void Tado::getZones(const QString &homeId)
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return;
}
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"));
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
@ -235,10 +308,16 @@ void Tado::getZones(const QString &homeId)
void Tado::getZoneState(const QString &homeId, const QString &zoneId)
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return;
}
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");
@ -307,10 +386,16 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId)
QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature)
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return "";
}
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"));
@ -376,10 +461,16 @@ QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power,
QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId)
{
if (!m_apiAvailable) {
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
return "";
}
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"));

View File

@ -93,9 +93,11 @@ public:
void setUsername(const QString &username);
QString username();
bool apiAvailable();
bool authenticated();
bool connected();
void getApiCredentials(const QString &url = "https://my.tado.com/webapp/env.js");
void getToken(const QString &password);
void getHomes();
void getZones(const QString &homeId);
@ -105,10 +107,11 @@ public:
QUuid deleteOverlay(const QString &homeId, const QString &zoneId);
private:
QByteArray m_baseAuthorizationUrl = "https://auth.tado.com/oauth/token";
QByteArray m_baseControlUrl = "https://my.tado.com/api/v2";
QByteArray m_clientSecret = "4HJGRffVR8xb3XdEUQpjgZ1VplJi6Xgw";
QByteArray m_clientId = "public-api-preview";
bool m_apiAvailable = false;
QString m_baseAuthorizationUrl;
QString m_baseControlUrl;
QString m_clientSecret;
QString m_clientId;
NetworkAccessManager *m_networkManager = nullptr;
QString m_username;
@ -123,6 +126,7 @@ private:
signals:
void connectionChanged(bool connected);
void apiCredentialsReceived();
void authenticationStatusChanged(bool authenticated);
void requestExecuted(QUuid requestId, bool success);