somfytahoma: Avoid duplication in SomfyTahoma*Request

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

View File

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

View File

@ -31,75 +31,62 @@
#include "somfytahomarequests.h"
#include <QJsonDocument>
#include <QUrlQuery>
#include "network/networkaccessmanager.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);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType);
QNetworkReply *reply = networkManager->post(request, body);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
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());
});
return new SomfyTahomaRequest(reply, parent);
}
SomfyTahomaGetRequest::SomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent):
QObject(parent)
SomfyTahomaRequest *createSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent)
{
QUrl url("https://tahomalink.com/enduser-mobile-web/enduserAPI" + path);
QUrl url(somfyTahomaUrl + path);
QNetworkRequest request(url);
QNetworkReply *reply = networkManager->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
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());
});
return new SomfyTahomaRequest(reply, parent);
}
SomfyTahomaLoginRequest::SomfyTahomaLoginRequest(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)
SomfyTahomaRequest *createSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent)
{
return createSomfyTahomaPostRequest(networkManager, "/login", "application/x-www-form-urlencoded", QString("userId=" + username + "&userPassword=" + password).toUtf8(), parent);
}
SomfyTahomaEventFetchRequest::SomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent):
SomfyTahomaPostRequest(networkManager, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent)
SomfyTahomaRequest *createSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent)
{
return createSomfyTahomaPostRequest(networkManager, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent);
}

View File

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