somewhat working
This commit is contained in:
parent
833e59550c
commit
db21e6cdf3
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -7,3 +7,6 @@
|
|||||||
[submodule "qmqtt"]
|
[submodule "qmqtt"]
|
||||||
path = qmqtt
|
path = qmqtt
|
||||||
url = https://github.com/emqtt/qmqtt.git
|
url = https://github.com/emqtt/qmqtt.git
|
||||||
|
[submodule "nymea-remoteproxy"]
|
||||||
|
path = nymea-remoteproxy
|
||||||
|
url = git@gitlab.guh.io:cloud/nymea-remoteproxy.git
|
||||||
|
|||||||
@ -23,6 +23,7 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
|
|||||||
settings.beginGroup("cloud");
|
settings.beginGroup("cloud");
|
||||||
m_username = settings.value("username").toString();
|
m_username = settings.value("username").toString();
|
||||||
m_accessToken = settings.value("accessToken").toByteArray();
|
m_accessToken = settings.value("accessToken").toByteArray();
|
||||||
|
m_accessTokenExpiry = settings.value("accessTokenExpiry").toDateTime();
|
||||||
m_idToken = settings.value("idToken").toByteArray();
|
m_idToken = settings.value("idToken").toByteArray();
|
||||||
m_refreshToken = settings.value("refreshToken").toByteArray();
|
m_refreshToken = settings.value("refreshToken").toByteArray();
|
||||||
|
|
||||||
@ -30,6 +31,9 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
|
|||||||
m_secretKey = settings.value("secretKey").toByteArray();
|
m_secretKey = settings.value("secretKey").toByteArray();
|
||||||
m_sessionToken = settings.value("sessionToken").toByteArray();
|
m_sessionToken = settings.value("sessionToken").toByteArray();
|
||||||
|
|
||||||
|
// if (m_accessTokenExpiry < QDateTime::currentDateTime() && !m_refreshToken.isEmpty()) {
|
||||||
|
refreshAccessToken();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AWSClient::isLoggedIn() const
|
bool AWSClient::isLoggedIn() const
|
||||||
@ -90,12 +94,14 @@ void AWSClient::login(const QString &username, const QString &password)
|
|||||||
|
|
||||||
QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
|
QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
|
||||||
m_accessToken = authenticationResult.value("AccessToken").toByteArray();
|
m_accessToken = authenticationResult.value("AccessToken").toByteArray();
|
||||||
|
m_accessTokenExpiry = QDateTime::currentDateTime().addSecs(authenticationResult.value("ExpiresIn").toInt());
|
||||||
m_idToken = authenticationResult.value("IdToken").toByteArray();
|
m_idToken = authenticationResult.value("IdToken").toByteArray();
|
||||||
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
|
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup("cloud");
|
settings.beginGroup("cloud");
|
||||||
settings.setValue("accessToken", m_accessToken);
|
settings.setValue("accessToken", m_accessToken);
|
||||||
|
settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
|
||||||
settings.setValue("idToken", m_idToken);
|
settings.setValue("idToken", m_idToken);
|
||||||
settings.setValue("refreshToken", m_refreshToken);
|
settings.setValue("refreshToken", m_refreshToken);
|
||||||
|
|
||||||
@ -252,7 +258,7 @@ void AWSClient::connectMQTT()
|
|||||||
void AWSClient::postToMQTT()
|
void AWSClient::postToMQTT()
|
||||||
{
|
{
|
||||||
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com";
|
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com";
|
||||||
QString topic = "850593e9-f2ab-4e89-913a-16f848d48867/eu-west-1:88c8b0f1-3f26-46cb-81f3-ccc37dcb543a/";
|
QString topic = "850593e9-f2ab-4e89-913a-16f848d48867/eu-west-1:88c8b0f1-3f26-46cb-81f3-ccc37dcb543a/proxy";
|
||||||
|
|
||||||
// This is somehow broken in AWS...
|
// This is somehow broken in AWS...
|
||||||
// The Signature needs to be created with having the topic percentage-encoded twice
|
// The Signature needs to be created with having the topic percentage-encoded twice
|
||||||
@ -333,3 +339,68 @@ QByteArray AWSClient::accessToken() const
|
|||||||
return m_accessToken;
|
return m_accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AWSClient::refreshAccessToken()
|
||||||
|
{
|
||||||
|
QUrl url("https://cognito-idp.eu-west-1.amazonaws.com/");
|
||||||
|
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("Action", "InitiateAuth");
|
||||||
|
query.addQueryItem("Version", "2016-04-18");
|
||||||
|
url.setQuery(query);
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-amz-json-1.0");
|
||||||
|
request.setRawHeader("Host", "cognito-idp.eu-west-1.amazonaws.com");
|
||||||
|
request.setRawHeader("X-Amz-Target", "AWSCognitoIdentityProviderService.InitiateAuth");
|
||||||
|
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("AuthFlow", "REFRESH_TOKEN_AUTH");
|
||||||
|
// params.insert("AuthFlow", "USER_PASSWORD_AUTH");
|
||||||
|
params.insert("ClientId", clientId);
|
||||||
|
|
||||||
|
QVariantMap authParams;
|
||||||
|
authParams.insert("REFRESH_TOKEN", m_refreshToken);
|
||||||
|
// authParams.insert("USERNAME", m_username);
|
||||||
|
// authParams.insert("PASSWORD", "H22*xgemmmmm");
|
||||||
|
|
||||||
|
params.insert("AuthParameters", authParams);
|
||||||
|
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
|
||||||
|
QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
|
||||||
|
|
||||||
|
qDebug() << "Refreshing AWS token for user:" << m_username << qUtf8Printable(payload);
|
||||||
|
|
||||||
|
QNetworkReply *reply = m_nam->post(request, payload);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||||
|
reply->deleteLater();
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qWarning() << "Error logging in to aws:" << reply->error() << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "Failed to parse AWS login response" << error.errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
|
||||||
|
// m_accessToken = authenticationResult.value("AccessToken").toByteArray();
|
||||||
|
// m_accessTokenExpiry = QDateTime::currentDateTime().addSecs(authenticationResult.value("ExpiresIn").toInt());
|
||||||
|
// m_idToken = authenticationResult.value("IdToken").toByteArray();
|
||||||
|
// m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
|
||||||
|
|
||||||
|
// QSettings settings;
|
||||||
|
// settings.beginGroup("cloud");
|
||||||
|
// settings.setValue("accessToken", m_accessToken);
|
||||||
|
// settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
|
||||||
|
// settings.setValue("idToken", m_idToken);
|
||||||
|
// settings.setValue("refreshToken", m_refreshToken);
|
||||||
|
|
||||||
|
qDebug() << "AWS login successful" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||||
|
emit isLoggedInChanged();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@ signals:
|
|||||||
void devicesFetched(QList<AWSDevice> devices);
|
void devicesFetched(QList<AWSDevice> devices);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void refreshAccessToken();
|
||||||
void getCredentialsForIdentity(const QString &identityId);
|
void getCredentialsForIdentity(const QString &identityId);
|
||||||
void connectMQTT();
|
void connectMQTT();
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ private:
|
|||||||
|
|
||||||
QString m_username;
|
QString m_username;
|
||||||
QByteArray m_accessToken;
|
QByteArray m_accessToken;
|
||||||
|
QDateTime m_accessTokenExpiry;
|
||||||
QByteArray m_idToken;
|
QByteArray m_idToken;
|
||||||
QByteArray m_refreshToken;
|
QByteArray m_refreshToken;
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
#include "cloudtransport.h"
|
#include "cloudtransport.h"
|
||||||
|
|
||||||
#include "qmqtt.h"
|
#include "awsclient.h"
|
||||||
|
#include "remoteproxyconnection.h"
|
||||||
|
|
||||||
|
using namespace remoteproxyclient;
|
||||||
|
|
||||||
CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
|
CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
|
||||||
NymeaTransportInterface(parent),
|
NymeaTransportInterface(parent),
|
||||||
m_awsClient(awsClient)
|
m_awsClient(awsClient)
|
||||||
{
|
{
|
||||||
|
m_remoteproxyConnection = new RemoteProxyConnection(QUuid::createUuid(), "nymea:app", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CloudTransport::supportedSchemes() const
|
QStringList CloudTransport::supportedSchemes() const
|
||||||
@ -17,34 +20,10 @@ QStringList CloudTransport::supportedSchemes() const
|
|||||||
void CloudTransport::connect(const QUrl &url)
|
void CloudTransport::connect(const QUrl &url)
|
||||||
{
|
{
|
||||||
qDebug() << "should connect to" << url;
|
qDebug() << "should connect to" << url;
|
||||||
QString date = QDateTime::currentDateTime().toString("yyyyMMddThhmmssZ");
|
m_awsClient->postToMQTT();
|
||||||
QString region = "eu-west-1";
|
|
||||||
QString service = "iotdevicegateway";
|
|
||||||
QString credentialScope = date + '/' + region + '/' + service + '/' + "aws4_request";
|
|
||||||
QString algorithm = "AWS4-HMAC-SHA256";
|
|
||||||
QString canonicalQuerystring = "X-Amz-Algorithm=" + algorithm;
|
|
||||||
|
|
||||||
// canonicalQuerystring += "&X-Amz-Credential=" + QByteArray(credentials.accessKeyId + '/' + credentialScope).toPercentageEncoded();
|
m_remoteproxyConnection->connectServer(QHostAddress("127.0.0.1"), 1212);
|
||||||
// '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
|
|
||||||
|
|
||||||
QString requestUrl = "wss://a2addxakg5juii.iot.eu-west-1.amazonaws.com/mqtt?" + canonicalQuerystring;
|
|
||||||
m_mqttClient = new QMQTT::Client(requestUrl, 443, QWebSocketProtocol::VersionLatest, true, this);
|
|
||||||
|
|
||||||
QObject::connect(m_mqttClient, &QMQTT::Client::connected, this, [](){
|
|
||||||
qDebug() << "MQTT connected";
|
|
||||||
});
|
|
||||||
QObject::connect(m_mqttClient, &QMQTT::Client::disconnected, this, []() {
|
|
||||||
qDebug() << "MQTT disconnected";
|
|
||||||
});
|
|
||||||
QObject::connect(m_mqttClient, &QMQTT::Client::error, this, [](QMQTT::ClientError error) {
|
|
||||||
qDebug() << "MQTT error" << error << QMQTT::ClientError::SocketHostNotFoundError;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
m_mqttClient->setUsername("michael.zanetti@guh.io");
|
|
||||||
m_mqttClient->setPassword("H22*gemmmmm");
|
|
||||||
m_mqttClient->setClientId("8rjhfdlf9jf1suok2jcrltd6v");
|
|
||||||
m_mqttClient->connectToHost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudTransport::disconnect()
|
void CloudTransport::disconnect()
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
namespace QMQTT {
|
|
||||||
class Client;
|
|
||||||
}
|
|
||||||
class AWSClient;
|
class AWSClient;
|
||||||
|
namespace remoteproxyclient {
|
||||||
|
class RemoteProxyConnection;
|
||||||
|
}
|
||||||
|
|
||||||
class CloudTransport : public NymeaTransportInterface
|
class CloudTransport : public NymeaTransportInterface
|
||||||
{
|
{
|
||||||
@ -24,8 +24,8 @@ public:
|
|||||||
void sendData(const QByteArray &data) override;
|
void sendData(const QByteArray &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMQTT::Client *m_mqttClient = nullptr;
|
|
||||||
AWSClient *m_awsClient = nullptr;
|
AWSClient *m_awsClient = nullptr;
|
||||||
|
remoteproxyclient::RemoteProxyConnection *m_remoteproxyConnection = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLOUDTRANSPORT_H
|
#endif // CLOUDTRANSPORT_H
|
||||||
|
|||||||
@ -18,8 +18,8 @@
|
|||||||
* *
|
* *
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#ifndef JSONRPCCLIENT_H
|
#ifndef NYMEAJSONRPCCLIENT_H
|
||||||
#define JSONRPCCLIENT_H
|
#define NYMEAJSONRPCCLIENT_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
@ -157,4 +157,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // JSONRPCCLIENT_H
|
#endif // NYMEAJSONRPCCLIENT_H
|
||||||
|
|||||||
@ -12,8 +12,9 @@ include(../config.pri)
|
|||||||
}
|
}
|
||||||
DEFINES += QT_STATIC
|
DEFINES += QT_STATIC
|
||||||
include(../qmqtt/src/mqtt/mqtt.pri)
|
include(../qmqtt/src/mqtt/mqtt.pri)
|
||||||
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \
|
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
|
||||||
connection/sigv4utils.h
|
|
||||||
|
include(../nymea-remoteproxy/libnymea-remoteproxyclient/libnymea-remoteproxyclient.pri)
|
||||||
|
|
||||||
QT -= gui
|
QT -= gui
|
||||||
QT += network websockets bluetooth
|
QT += network websockets bluetooth
|
||||||
@ -89,6 +90,7 @@ HEADERS += \
|
|||||||
connection/tcpsockettransport.h \
|
connection/tcpsockettransport.h \
|
||||||
connection/bluetoothtransport.h \
|
connection/bluetoothtransport.h \
|
||||||
connection/awsclient.h \
|
connection/awsclient.h \
|
||||||
|
connection/sigv4utils.h \
|
||||||
devicemanager.h \
|
devicemanager.h \
|
||||||
jsonrpc/jsontypes.h \
|
jsonrpc/jsontypes.h \
|
||||||
jsonrpc/jsonrpcclient.h \
|
jsonrpc/jsonrpcclient.h \
|
||||||
|
|||||||
1
nymea-remoteproxy
Submodule
1
nymea-remoteproxy
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c2c3304a558a434115c49e168155da8eba81cd98
|
||||||
Reference in New Issue
Block a user