somfytahoma: Avoid duplication in SomfyTahoma*Request

This commit is contained in:
Christian Fetzer 2021-04-04 16:26:09 +02:00
parent 68ca8605f3
commit ff1355e1a5
4 changed files with 71 additions and 107 deletions

View File

@ -46,11 +46,11 @@ void IntegrationPluginSomfyTahoma::startPairing(ThingPairingInfo *info)
void IntegrationPluginSomfyTahoma::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password) void IntegrationPluginSomfyTahoma::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
{ {
SomfyTahomaLoginRequest *request = new SomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this); SomfyTahomaRequest *request = createSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this);
connect(request, &SomfyTahomaLoginRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma.")); info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma."));
}); });
connect(request, &SomfyTahomaLoginRequest::finished, info, [this, info, username, password](const QVariant &/*result*/){ connect(request, &SomfyTahomaRequest::finished, info, [this, info, username, password](const QVariant &/*result*/){
pluginStorage()->beginGroup(info->thingId().toString()); pluginStorage()->beginGroup(info->thingId().toString());
pluginStorage()->setValue("username", username); pluginStorage()->setValue("username", username);
pluginStorage()->setValue("password", password); pluginStorage()->setValue("password", password);
@ -62,14 +62,14 @@ void IntegrationPluginSomfyTahoma::confirmPairing(ThingPairingInfo *info, const
void IntegrationPluginSomfyTahoma::setupThing(ThingSetupInfo *info) void IntegrationPluginSomfyTahoma::setupThing(ThingSetupInfo *info)
{ {
if (info->thing()->thingClassId() == tahomaThingClassId) { if (info->thing()->thingClassId() == tahomaThingClassId) {
SomfyTahomaLoginRequest *request = createLoginRequestWithStoredCredentials(info->thing()); SomfyTahomaRequest *request = createLoginRequestWithStoredCredentials(info->thing());
connect(request, &SomfyTahomaLoginRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma.")); info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma."));
}); });
connect(request, &SomfyTahomaLoginRequest::finished, info, [this, info](const QVariant &/*result*/){ connect(request, &SomfyTahomaRequest::finished, info, [this, info](const QVariant &/*result*/){
QUuid accountId = info->thing()->id(); QUuid accountId = info->thing()->id();
SomfyTahomaGetRequest *request = new SomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this); SomfyTahomaRequest *request = createSomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this);
connect(request, &SomfyTahomaGetRequest::finished, this, [this, accountId](const QVariant &result){ connect(request, &SomfyTahomaRequest::finished, this, [this, accountId](const QVariant &result){
QList<ThingDescriptor> unknownDevices; QList<ThingDescriptor> unknownDevices;
foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) { foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) {
QVariantMap gatewayMap = gatewayVariant.toMap(); QVariantMap gatewayMap = gatewayVariant.toMap();
@ -177,11 +177,11 @@ void IntegrationPluginSomfyTahoma::refreshAccount(Thing *thing)
hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]); hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]);
} }
SomfyTahomaGetRequest *setupRequest = new SomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this); SomfyTahomaRequest *setupRequest = createSomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this);
connect(setupRequest, &SomfyTahomaGetRequest::error, this, [this, thing](){ connect(setupRequest, &SomfyTahomaRequest::error, this, [this, thing](){
markDisconnected(thing); markDisconnected(thing);
}); });
connect(setupRequest, &SomfyTahomaGetRequest::finished, this, [this, thing](const QVariant &result){ connect(setupRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){
thing->setStateValue(tahomaLoggedInStateTypeId, true); thing->setStateValue(tahomaLoggedInStateTypeId, true);
thing->setStateValue(tahomaConnectedStateTypeId, true); thing->setStateValue(tahomaConnectedStateTypeId, true);
foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) { foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) {
@ -201,29 +201,29 @@ void IntegrationPluginSomfyTahoma::refreshAccount(Thing *thing)
} }
}); });
SomfyTahomaPostRequest *eventRegistrationRequest = new SomfyTahomaPostRequest(hardwareManager()->networkManager(), "/events/register", "application/json", QByteArray(), this); SomfyTahomaRequest *eventRegistrationRequest = createSomfyTahomaPostRequest(hardwareManager()->networkManager(), "/events/register", "application/json", QByteArray(), this);
connect(eventRegistrationRequest, &SomfyTahomaPostRequest::error, this, [this, thing](){ connect(eventRegistrationRequest, &SomfyTahomaRequest::error, this, [this, thing](){
qCWarning(dcSomfyTahoma()) << "Failed to register for events."; qCWarning(dcSomfyTahoma()) << "Failed to register for events.";
markDisconnected(thing); markDisconnected(thing);
}); });
connect(eventRegistrationRequest, &SomfyTahomaPostRequest::finished, this, [this, thing](const QVariant &result){ connect(eventRegistrationRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){
thing->setStateValue(tahomaConnectedStateTypeId, true); thing->setStateValue(tahomaConnectedStateTypeId, true);
QString eventListenerId = result.toMap()["id"].toString(); QString eventListenerId = result.toMap()["id"].toString();
m_eventPollTimer[thing] = hardwareManager()->pluginTimerManager()->registerTimer(2 /*sec*/); m_eventPollTimer[thing] = hardwareManager()->pluginTimerManager()->registerTimer(2 /*sec*/);
connect(m_eventPollTimer[thing], &PluginTimer::timeout, thing, [this, thing, eventListenerId](){ connect(m_eventPollTimer[thing], &PluginTimer::timeout, thing, [this, thing, eventListenerId](){
SomfyTahomaEventFetchRequest *eventFetchRequest = new SomfyTahomaEventFetchRequest(hardwareManager()->networkManager(), eventListenerId, this); SomfyTahomaRequest *eventFetchRequest = createSomfyTahomaEventFetchRequest(hardwareManager()->networkManager(), eventListenerId, this);
connect(eventFetchRequest, &SomfyTahomaEventFetchRequest::error, thing, [this, thing](QNetworkReply::NetworkError error){ connect(eventFetchRequest, &SomfyTahomaRequest::error, thing, [this, thing](QNetworkReply::NetworkError error){
markDisconnected(thing); markDisconnected(thing);
if (error == QNetworkReply::AuthenticationRequiredError) { if (error == QNetworkReply::AuthenticationRequiredError) {
qCInfo(dcSomfyTahoma()) << "Failed to fetch events: Authentication expired, reauthenticating"; qCInfo(dcSomfyTahoma()) << "Failed to fetch events: Authentication expired, reauthenticating";
SomfyTahomaLoginRequest *request = createLoginRequestWithStoredCredentials(thing); SomfyTahomaRequest *request = createLoginRequestWithStoredCredentials(thing);
connect(request, &SomfyTahomaLoginRequest::error, this, [this, thing](){ connect(request, &SomfyTahomaRequest::error, this, [this, thing](){
// This is a fatal error. The user needs to reconfigure the account to provide new credentials. // This is a fatal error. The user needs to reconfigure the account to provide new credentials.
qCWarning(dcSomfyTahoma()) << "Failed to reauthenticate"; qCWarning(dcSomfyTahoma()) << "Failed to reauthenticate";
hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]); hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]);
m_eventPollTimer.remove(thing); m_eventPollTimer.remove(thing);
}); });
connect(request, &SomfyTahomaLoginRequest::finished, this, [this, thing](const QVariant &/*result*/){ connect(request, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &/*result*/){
qCInfo(dcSomfyTahoma()) << "Reauthentication successful"; qCInfo(dcSomfyTahoma()) << "Reauthentication successful";
refreshAccount(thing); refreshAccount(thing);
}); });
@ -231,7 +231,7 @@ void IntegrationPluginSomfyTahoma::refreshAccount(Thing *thing)
qCWarning(dcSomfyTahoma()) << "Failed to fetch events:" << error; qCWarning(dcSomfyTahoma()) << "Failed to fetch events:" << error;
} }
}); });
connect(eventFetchRequest, &SomfyTahomaEventFetchRequest::finished, thing, [this, thing](const QVariant &result){ connect(eventFetchRequest, &SomfyTahomaRequest::finished, thing, [this, thing](const QVariant &result){
thing->setStateValue(tahomaConnectedStateTypeId, true); thing->setStateValue(tahomaConnectedStateTypeId, true);
restoreChildConnectedState(thing); restoreChildConnectedState(thing);
if (!result.toList().empty()) { if (!result.toList().empty()) {
@ -458,11 +458,11 @@ void IntegrationPluginSomfyTahoma::executeAction(ThingActionInfo *info)
{"commands", QJsonArray{QJsonObject{{"name", actionName}, {"commands", QJsonArray{QJsonObject{{"name", actionName},
{"parameters", actionParameters}}}}}}} {"parameters", actionParameters}}}}}}}
}}; }};
SomfyTahomaPostRequest *request = new SomfyTahomaPostRequest(hardwareManager()->networkManager(), "/exec/apply", "application/json", jsonRequest.toJson(QJsonDocument::Compact), this); SomfyTahomaRequest *request = createSomfyTahomaPostRequest(hardwareManager()->networkManager(), "/exec/apply", "application/json", jsonRequest.toJson(QJsonDocument::Compact), this);
connect(request, &SomfyTahomaPostRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorHardwareFailure); info->finish(Thing::ThingErrorHardwareFailure);
}); });
connect(request, &SomfyTahomaPostRequest::finished, info, [this, info](const QVariant &result){ connect(request, &SomfyTahomaRequest::finished, info, [this, info](const QVariant &result){
qCInfo(dcSomfyTahoma()) << "Action started" << info->thing() << info->action().actionTypeId(); qCInfo(dcSomfyTahoma()) << "Action started" << info->thing() << info->action().actionTypeId();
m_pendingActions.insert(result.toMap()["execId"].toString(), info); m_pendingActions.insert(result.toMap()["execId"].toString(), info);
}); });
@ -471,13 +471,13 @@ void IntegrationPluginSomfyTahoma::executeAction(ThingActionInfo *info)
} }
} }
SomfyTahomaLoginRequest *IntegrationPluginSomfyTahoma::createLoginRequestWithStoredCredentials(Thing *thing) SomfyTahomaRequest *IntegrationPluginSomfyTahoma::createLoginRequestWithStoredCredentials(Thing *thing)
{ {
pluginStorage()->beginGroup(thing->id().toString()); pluginStorage()->beginGroup(thing->id().toString());
QString username = pluginStorage()->value("username").toString(); QString username = pluginStorage()->value("username").toString();
QString password = pluginStorage()->value("password").toString(); QString password = pluginStorage()->value("password").toString();
pluginStorage()->endGroup(); pluginStorage()->endGroup();
return new SomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this); return createSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this);
} }
void IntegrationPluginSomfyTahoma::markDisconnected(Thing *thing) void IntegrationPluginSomfyTahoma::markDisconnected(Thing *thing)

View File

@ -34,7 +34,7 @@
#include "integrations/integrationplugin.h" #include "integrations/integrationplugin.h"
#include "plugintimer.h" #include "plugintimer.h"
class SomfyTahomaLoginRequest; class SomfyTahomaRequest;
class IntegrationPluginSomfyTahoma : public IntegrationPlugin class IntegrationPluginSomfyTahoma : public IntegrationPlugin
{ {
@ -54,7 +54,7 @@ public:
void executeAction(ThingActionInfo *info) override; void executeAction(ThingActionInfo *info) override;
private: private:
SomfyTahomaLoginRequest *createLoginRequestWithStoredCredentials(Thing *thing); SomfyTahomaRequest *createLoginRequestWithStoredCredentials(Thing *thing);
void refreshAccount(Thing *thing); void refreshAccount(Thing *thing);
void handleEvents(const QVariantList &eventList); void handleEvents(const QVariantList &eventList);
void updateThingStates(const QString &deviceUrl, const QVariantList &stateList); void updateThingStates(const QString &deviceUrl, const QVariantList &stateList);

View File

@ -31,75 +31,62 @@
#include "somfytahomarequests.h" #include "somfytahomarequests.h"
#include <QJsonDocument> #include <QJsonDocument>
#include <QUrlQuery>
#include "network/networkaccessmanager.h" #include "network/networkaccessmanager.h"
#include "extern-plugininfo.h" #include "extern-plugininfo.h"
SomfyTahomaPostRequest::SomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent):
QObject(parent) static const QString somfyTahomaUrl = QStringLiteral("https://tahomalink.com/enduser-mobile-web/enduserAPI");
SomfyTahomaRequest::SomfyTahomaRequest(QNetworkReply *reply, QObject *parent) : QObject(parent)
{ {
QUrl url("https://tahomalink.com/enduser-mobile-web/enduserAPI" + path); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [this, reply] {
deleteLater();
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcSomfyTahoma()) << "Request for" << reply->url().path() << "failed:" << reply->errorString();
emit error(reply->error());
return;
}
QByteArray data = reply->readAll();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qCWarning(dcSomfyTahoma()) << "Json parse error in reply for" << reply->url().path() << ":" << parseError.errorString();
emit error(QNetworkReply::UnknownContentError);
return;
}
emit finished(jsonDoc.toVariant());
});
}
SomfyTahomaRequest *createSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent)
{
QUrl url(somfyTahomaUrl + path);
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType);
QNetworkReply *reply = networkManager->post(request, body); QNetworkReply *reply = networkManager->post(request, body);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); return new SomfyTahomaRequest(reply, parent);
connect(reply, &QNetworkReply::finished, this, [this, reply, path] {
deleteLater();
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcSomfyTahoma()) << "Request for" << path << "failed:" << reply->errorString();
emit error(reply->error());
return;
}
QByteArray data = reply->readAll();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qCWarning(dcSomfyTahoma()) << "Json parse error in reply for" << path << ":" << parseError.errorString();
emit error(QNetworkReply::UnknownContentError);
return;
}
emit finished(jsonDoc.toVariant());
});
} }
SomfyTahomaGetRequest::SomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent): SomfyTahomaRequest *createSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent)
QObject(parent)
{ {
QUrl url("https://tahomalink.com/enduser-mobile-web/enduserAPI" + path); QUrl url(somfyTahomaUrl + path);
QNetworkRequest request(url); QNetworkRequest request(url);
QNetworkReply *reply = networkManager->get(request); QNetworkReply *reply = networkManager->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); return new SomfyTahomaRequest(reply, parent);
connect(reply, &QNetworkReply::finished, this, [this, reply, path] {
deleteLater();
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcSomfyTahoma()) << "Request for" << path << "failed:" << reply->errorString();
emit error(reply->error());
return;
}
QByteArray data = reply->readAll();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qCWarning(dcSomfyTahoma()) << "Json parse error in reply for" << path << ":" << parseError.errorString();
emit error(QNetworkReply::UnknownContentError);
return;
}
emit finished(jsonDoc.toVariant());
});
} }
SomfyTahomaLoginRequest::SomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent): SomfyTahomaRequest *createSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent)
SomfyTahomaPostRequest(networkManager, "/login", "application/x-www-form-urlencoded", QString("userId=" + username + "&userPassword=" + password).toUtf8(), parent)
{ {
return createSomfyTahomaPostRequest(networkManager, "/login", "application/x-www-form-urlencoded", QString("userId=" + username + "&userPassword=" + password).toUtf8(), parent);
} }
SomfyTahomaRequest *createSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent)
SomfyTahomaEventFetchRequest::SomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent):
SomfyTahomaPostRequest(networkManager, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent)
{ {
return createSomfyTahomaPostRequest(networkManager, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent);
} }

View File

@ -35,44 +35,21 @@
class NetworkAccessManager; class NetworkAccessManager;
class SomfyTahomaPostRequest : public QObject class SomfyTahomaRequest : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
SomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent); SomfyTahomaRequest(QNetworkReply *reply, QObject *parent);
signals: signals:
void error(QNetworkReply::NetworkError error); void error(QNetworkReply::NetworkError error);
void finished(const QVariant &results); void finished(const QVariant &results);
}; };
class SomfyTahomaGetRequest : public QObject SomfyTahomaRequest *createSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent);
{ SomfyTahomaRequest *createSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent);
Q_OBJECT SomfyTahomaRequest *createSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent);
SomfyTahomaRequest *createSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent);
public:
SomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent);
signals:
void error(QNetworkReply::NetworkError error);
void finished(const QVariant &results);
};
class SomfyTahomaLoginRequest : public SomfyTahomaPostRequest
{
Q_OBJECT
public:
SomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent);
};
class SomfyTahomaEventFetchRequest : public SomfyTahomaPostRequest
{
Q_OBJECT
public:
SomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent);
};
#endif // SOMFYTAHOMAREQUESTS_H #endif // SOMFYTAHOMAREQUESTS_H