mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-11 23:59:59 +02:00
Add
This commit is contained in:
parent
f5bdc2e8c2
commit
453179ab53
@ -37,6 +37,8 @@
|
||||
|
||||
#include <network/networkdevicediscovery.h>
|
||||
|
||||
#include "senecconnection.h"
|
||||
|
||||
IntegrationPluginSenec::IntegrationPluginSenec()
|
||||
{
|
||||
// Testing the convert methods
|
||||
@ -52,6 +54,8 @@ IntegrationPluginSenec::IntegrationPluginSenec()
|
||||
// QString rawValue = "u8_64"; // 100
|
||||
// quint8 value = SenecStorageLan::parseUInt8(rawValue);
|
||||
// qCWarning(dcSenec()) << rawValue << value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
IntegrationPluginSenec::~IntegrationPluginSenec()
|
||||
@ -107,7 +111,31 @@ void IntegrationPluginSenec::discoverThings(ThingDiscoveryInfo *info)
|
||||
|
||||
void IntegrationPluginSenec::startPairing(ThingPairingInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter username and password for your SENEC.home account."));
|
||||
if (info->thingClassId() == senecConnectionThingClassId) {
|
||||
qCDebug(dcSenec()) << "Start pairing process ...";
|
||||
|
||||
SenecConnection *connection = new SenecConnection(hardwareManager()->networkManager(), this);
|
||||
//m_unfinishedTadoAccounts.insert(info->thingId(), tado);
|
||||
|
||||
connect(info, &ThingPairingInfo::aborted, this, [connection]() {
|
||||
qCWarning(dcSenec()) << "Thing pairing has been aborted, cleaning up...";
|
||||
//m_unfinishedTadoAccounts.remove(info->thingId());
|
||||
connection->deleteLater();
|
||||
});
|
||||
|
||||
connect(connection, &SenecConnection::initFinished, info, [info, connection] (bool success) {
|
||||
if (!success) {
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSenec()) << "Senec server is reachable. Starting the OpenID auth process" << connection->authEndpoint().toString(QUrl::FullyEncodedy);
|
||||
info->setOAuthUrl(connection->authEndpoint());
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
connection->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
|
||||
|
||||
@ -40,6 +40,43 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "290e4abb-d000-43a4-9e23-e298e5c36707",
|
||||
"name": "senecConnection",
|
||||
"displayName": "SENEC connection",
|
||||
"interfaces": ["account"],
|
||||
"createMethods": ["user"],
|
||||
"setupMethod": "oauth",
|
||||
"paramTypes": [
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "1180576a-1de2-4815-b442-877b572ce586",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": true,
|
||||
"cached": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "ff40d5c7-3095-4b3e-9e10-4c0774336764",
|
||||
"name": "loggedIn",
|
||||
"displayName": "Logged in",
|
||||
"displayNameEvent": "Logged in changed",
|
||||
"defaultValue": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "5d3b2396-6528-47c2-b5a4-f751531bccea",
|
||||
"name": "userDisplayName",
|
||||
"displayName": "User name",
|
||||
"displayNameEvent": "User name changed",
|
||||
"defaultValue": "",
|
||||
"type": "QString"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "345df3b1-d411-4db5-bbb2-3b14eb86c1ba",
|
||||
"name": "senecStorageLan",
|
||||
|
||||
@ -5,12 +5,14 @@ QT+= network
|
||||
SOURCES += \
|
||||
integrationpluginsenec.cpp \
|
||||
senecaccount.cpp \
|
||||
senecconnection.cpp \
|
||||
senecdiscovery.cpp \
|
||||
senecstoragelan.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginsenec.h \
|
||||
senecaccount.h \
|
||||
senecconnection.h \
|
||||
senecdiscovery.h \
|
||||
senecstoragelan.h
|
||||
|
||||
|
||||
184
senec/senecconnection.cpp
Normal file
184
senec/senecconnection.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "senecconnection.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QRegularExpression>
|
||||
|
||||
SenecConnection::SenecConnection(NetworkAccessManager *networkManager, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_networkManager{networkManager}
|
||||
{
|
||||
m_configUrl = QUrl("https://sso.senec.com/realms/senec/.well-known/openid-configuration");
|
||||
m_systemsUrl = QUrl("https://senec-app-systems-proxy.prod.senec.dev");
|
||||
m_measurementsUrl = QUrl("https://senec-app-measurements-proxy.prod.senec.dev");
|
||||
|
||||
m_clientId = QString("endcustomer-app-frontend");
|
||||
m_redirectUrl =/* QString("http://127.0.0.1:8888");*/ QUrl("senec-app-auth://keycloak.prod");
|
||||
m_scopes << "roles" << "meinsenec" << "openid";
|
||||
m_userAgent = QString("nymea (+https://github.com/nymea/nymea)");
|
||||
}
|
||||
|
||||
void SenecConnection::initialize()
|
||||
{
|
||||
qCDebug(dcSenec()) << "OpenID: Initialize and get configuration";
|
||||
|
||||
QNetworkRequest request(m_configUrl);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent.toUtf8());
|
||||
|
||||
QNetworkReply *reply = m_networkManager->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply, request](){
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcSenec()) << "OpenID: Failed to get configuration" << request.url().toString() << reply->errorString();
|
||||
if (!data.isEmpty())
|
||||
qCWarning(dcSenec()) << "OpenID: Response data:" << qUtf8Printable(data);
|
||||
|
||||
emit initFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//qCDebug(dcPushNotifications()) << "OAuth2: Request access token response" << qUtf8Printable(data);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcSenec()) << "OpenID: Failed to get configuration. Response data JSON error:" << error.errorString();
|
||||
emit initFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap configMap = jsonDoc.toVariant().toMap();
|
||||
m_authEndpoint = QUrl(configMap.value("authorization_endpoint").toString());
|
||||
|
||||
QUrlQuery queryParams;
|
||||
queryParams.addQueryItem("client_id", m_clientId);
|
||||
queryParams.addQueryItem("redirect_uri", m_redirectUrl.toString());
|
||||
queryParams.addQueryItem("response_type", "code");
|
||||
queryParams.addQueryItem("scope", m_scopes.join("+"));
|
||||
|
||||
// queryParams.addQueryItem("nonce", QUuid::createUuid().toString());
|
||||
// m_codeChallenge = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||
|
||||
// queryParams.addQueryItem("code_challenge", m_codeChallenge);
|
||||
// queryParams.addQueryItem("code_challenge_method", "S256");
|
||||
m_authEndpoint.setQuery(queryParams);
|
||||
emit initFinished(true);
|
||||
});
|
||||
}
|
||||
|
||||
QUrl SenecConnection::authEndpoint() const
|
||||
{
|
||||
return m_authEndpoint;
|
||||
}
|
||||
|
||||
// void SenecConnection::login(const QString &username, const QString &password)
|
||||
// {
|
||||
// Q_UNUSED(username, password)
|
||||
// QNetworkRequest request(m_configUrl);
|
||||
// request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent.toUtf8());
|
||||
|
||||
// QNetworkReply *reply = m_networkManager->get(request);
|
||||
// connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
// connect(reply, &QNetworkReply::finished, this, [this, reply, request](){
|
||||
|
||||
// QByteArray data = reply->readAll();
|
||||
// if (reply->error() != QNetworkReply::NoError) {
|
||||
// qCWarning(dcSenec()) << "OpenID: Failed to get configuration" << request.url().toString() << reply->errorString();
|
||||
// if (!data.isEmpty())
|
||||
// qCWarning(dcSenec()) << "OpenID: Response data:" << qUtf8Printable(data);
|
||||
|
||||
// // setAuthenticated(false);
|
||||
|
||||
// // // Retry in 30 seconds, maybe we are not online yet
|
||||
// // m_refreshTimer.start(60 * 1000);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// //qCDebug(dcPushNotifications()) << "OAuth2: Request access token response" << qUtf8Printable(data);
|
||||
|
||||
// QJsonParseError error;
|
||||
// QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
// if (error.error != QJsonParseError::NoError) {
|
||||
// qCWarning(dcSenec()) << "OpenID: Failed to get configuration. Response data JSON error:" << error.errorString();
|
||||
// //setAuthenticated(false);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// QVariantMap configMap = jsonDoc.toVariant().toMap();
|
||||
// m_authEndpoint = QUrl(configMap.value("authorization_endpoint").toString());
|
||||
|
||||
|
||||
|
||||
// // QUrl url(m_baseTokenUrl);
|
||||
// // QUrlQuery query;
|
||||
// // query.clear();
|
||||
// // query.addQueryItem("grant_type", "refresh_token");
|
||||
// // query.addQueryItem("refresh_token", refreshToken);
|
||||
// // query.addQueryItem("client_secret", m_clientSecret);
|
||||
|
||||
// // QNetworkRequest request(m_authEndpoint);
|
||||
// // request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent.toUtf8());
|
||||
// // request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
|
||||
|
||||
// // // QUrlQuery queryParams;
|
||||
// // // queryParams.addQueryItem("client_id", m_clientId);
|
||||
// // // queryParams.addQueryItem("redirect_uri", m_redirectUrl);
|
||||
// // // queryParams.addQueryItem("response_type", "code");
|
||||
// // // queryParams.addQueryItem("scope", m_scopes.join(" "));
|
||||
// // // queryParams.addQueryItem("nonce", QUuid::createUuid().toString());
|
||||
// // // m_codeChallenge = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||
|
||||
// // // queryParams.addQueryItem("code_challenge", m_codeChallenge);
|
||||
// // // queryParams.addQueryItem("code_challenge_method", "S256");
|
||||
// // // url.setQuery(queryParams);
|
||||
|
||||
|
||||
// // // QNetworkReply *reply = m_networkManager->post(request, query.toString().toUtf8());
|
||||
// // // connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
// // // connect(reply, &QNetworkReply::finished, this, [this, reply](){
|
||||
|
||||
// // redirect_uri: REDIRECT_URI,
|
||||
// // scope: SCOPE,
|
||||
// // code_challenge:,
|
||||
// // code_challenge_method: 'S256',
|
||||
|
||||
|
||||
// });
|
||||
|
||||
// });
|
||||
// }
|
||||
72
senec/senecconnection.h
Normal file
72
senec/senecconnection.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef SENECCONNECTION_H
|
||||
#define SENECCONNECTION_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QObject>
|
||||
|
||||
#include <network/networkaccessmanager.h>
|
||||
|
||||
class SenecConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SenecConnection(NetworkAccessManager *networkManager, QObject *parent = nullptr);
|
||||
|
||||
void initialize();
|
||||
|
||||
QUrl authEndpoint() const;
|
||||
|
||||
// void login(const QString &username, const QString &password);
|
||||
|
||||
signals:
|
||||
void initFinished(bool success);
|
||||
|
||||
private:
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
|
||||
QUrl m_configUrl;
|
||||
QUrl m_systemsUrl;
|
||||
QUrl m_measurementsUrl;
|
||||
|
||||
QString m_clientId;
|
||||
QUrl m_redirectUrl;
|
||||
QStringList m_scopes;
|
||||
QString m_userAgent;
|
||||
|
||||
// Fetch from config url
|
||||
QUrl m_authEndpoint;
|
||||
QString m_codeChallenge;
|
||||
|
||||
};
|
||||
|
||||
#endif // SENECCONNECTION_H
|
||||
@ -1,6 +1,6 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT *= serialport
|
||||
QT += serialport
|
||||
|
||||
PKGCONFIG += libudev
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user