remove websocket compiler flag

add cloud connection basic structure
This commit is contained in:
Simon Stürz 2016-06-06 11:00:16 +02:00 committed by Michael Zanetti
parent b7c73a9a5d
commit 9edc4395d6
23 changed files with 820 additions and 60 deletions

View File

@ -9,7 +9,7 @@ DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \
JSON_PROTOCOL_VERSION=\\\"$${JSON_PROTOCOL_VERSION}\\\" \
REST_API_VERSION=\\\"$${REST_API_VERSION}\\\"
QT+= network
QT+= network websockets
QMAKE_CXXFLAGS += -Werror -std=c++11 -g
QMAKE_LFLAGS += -std=c++11
@ -73,14 +73,9 @@ coverage {
QMAKE_CLEAN += *.gcda *.gcno coverage.info coverage.xml
}
# Enable Radio 433 MHz for GPIO's
enable433gpio {
DEFINES += GPIO433
}
# check websocket support (Qt >= 5.3)
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 2) {
DEFINES += WEBSOCKET
}

View File

@ -60,13 +60,6 @@ contains(DEFINES, BLUETOOTH_LE) {
message("Bluetooth LE disabled (Qt $${QT_VERSION} < 5.4.0).")
}
# Websocket support
contains(DEFINES, WEBSOCKET){
message("Building guh with websocket.")
} else {
message("Building guh without websocket.")
}
# GPIO RF 433 MHz support
contains(DEFINES, GPIO433){
message("Radio 433 for GPIO's enabled")

View File

@ -34,3 +34,4 @@ Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
Q_LOGGING_CATEGORY(dcRest, "Rest")
Q_LOGGING_CATEGORY(dcOAuth2, "OAuth2")
Q_LOGGING_CATEGORY(dcAvahi, "Avahi")
Q_LOGGING_CATEGORY(dcCloud, "Cloud")

View File

@ -22,6 +22,7 @@
#define LOGGINGCATEGORYS_H
#include <QLoggingCategory>
#include <QDebug>
// Include dcCoap
#include "coap/coap.h"
@ -41,5 +42,6 @@ Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
Q_DECLARE_LOGGING_CATEGORY(dcRest)
Q_DECLARE_LOGGING_CATEGORY(dcOAuth2)
Q_DECLARE_LOGGING_CATEGORY(dcAvahi)
Q_DECLARE_LOGGING_CATEGORY(dcCloud)
#endif // LOGGINGCATEGORYS_H

View File

@ -0,0 +1,270 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "cloudauthenticator.h"
#include <QJsonParseError>
#include <QJsonDocument>
namespace guhserver {
CloudAuthenticator::CloudAuthenticator(QString clientId, QString clientSecret, QObject *parent) :
QObject(parent),
m_clientId(clientId),
m_clientSecret(clientSecret),
m_authenticated(false)
{
m_networkManager = new QNetworkAccessManager(this);
connect(m_networkManager, &QNetworkAccessManager::finished, this, &CloudAuthenticator::replyFinished);
m_timer = new QTimer(this);
m_timer->setSingleShot(false);
connect(m_timer, &QTimer::timeout, this, &CloudAuthenticator::refreshTimeout);
}
QUrl CloudAuthenticator::url() const
{
return m_url;
}
void CloudAuthenticator::setUrl(const QUrl &url)
{
m_url = url;
}
QUrlQuery CloudAuthenticator::query() const
{
return m_query;
}
void CloudAuthenticator::setQuery(const QUrlQuery &query)
{
m_query = query;
}
QString CloudAuthenticator::username() const
{
return m_username;
}
void CloudAuthenticator::setUsername(const QString &username)
{
m_username = username;
}
QString CloudAuthenticator::password() const
{
return m_password;
}
void CloudAuthenticator::setPassword(const QString &password)
{
m_password = password;
}
QString CloudAuthenticator::clientId() const
{
return m_clientId;
}
void CloudAuthenticator::setClientId(const QString &clientId)
{
m_clientId = clientId;
}
QString CloudAuthenticator::clientSecret() const
{
return m_clientSecret;
}
void CloudAuthenticator::setClientSecret(const QString clientSecret)
{
m_clientSecret = clientSecret;
}
QString CloudAuthenticator::scope() const
{
return m_scope;
}
void CloudAuthenticator::setScope(const QString &scope)
{
m_scope = scope;
}
QString CloudAuthenticator::token() const
{
return m_token;
}
bool CloudAuthenticator::authenticated() const
{
return m_authenticated;
}
void CloudAuthenticator::startAuthentication()
{
qCDebug(dcCloud()) << "Start authentication" << m_username;
QUrlQuery query;
query.addQueryItem("grant_type", "password");
query.addQueryItem("username", m_username);
query.addQueryItem("password", m_password);
setQuery(query);
QNetworkRequest request(m_url);
QByteArray data = QString(m_clientId + ":" + m_clientSecret).toUtf8().toBase64();
QString header = "Basic " + data;
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
m_tokenRequests.append(m_networkManager->post(request, m_query.toString().toUtf8()));
}
void CloudAuthenticator::setAuthenticated(const bool &authenticated)
{
if (!authenticated) {
m_timer->stop();
qCWarning(dcCloud()) << "Authentication failed" << m_username;
}
m_authenticated = authenticated;
emit authenticationChanged();
}
void CloudAuthenticator::setToken(const QString &token)
{
m_token = token;
emit tokenChanged();
}
void CloudAuthenticator::replyFinished(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// token request
if (m_tokenRequests.contains(reply)) {
QByteArray data = reply->readAll();
m_tokenRequests.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcCloud()) << "Request token reply HTTP error:" << status << reply->errorString();
qCWarning(dcCloud()) << data;
setAuthenticated(false);
reply->deleteLater();
return;
}
// check JSON
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcCloud()) << "Request token reply JSON error:" << error.errorString();
setAuthenticated(false);
reply->deleteLater();
return;
}
if (!jsonDoc.toVariant().toMap().contains("access_token")) {
qCWarning(dcCloud()) << "Could not get access token" << jsonDoc.toJson();
setAuthenticated(false);
reply->deleteLater();
return;
}
setToken(jsonDoc.toVariant().toMap().value("access_token").toString());
setAuthenticated(true);
if (jsonDoc.toVariant().toMap().contains("expires_in") && jsonDoc.toVariant().toMap().contains("refresh_token")) {
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toString();
qCDebug(dcCloud()) << "Token will be refreshed in" << expireTime << "[s]";
m_timer->start((expireTime - 20) * 1000);
}
} else if (m_refreshTokenRequests.contains(reply)) {
QByteArray data = reply->readAll();
m_refreshTokenRequests.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcCloud()) << "Refresh token reply HTTP error:" << status << reply->errorString();
qCWarning(dcCloud()) << data;
setAuthenticated(false);
reply->deleteLater();
return;
}
// check JSON
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcCloud()) << "Refresh token reply JSON error:" << error.errorString();
setAuthenticated(false);
reply->deleteLater();
return;
}
if (!jsonDoc.toVariant().toMap().contains("access_token")) {
qCWarning(dcCloud()) << "Could not get access token after refresh" << jsonDoc.toJson();
setAuthenticated(false);
reply->deleteLater();
return;
}
setToken(jsonDoc.toVariant().toMap().value("access_token").toString());
qCDebug(dcCloud()) << "Token refreshed successfully";
if (jsonDoc.toVariant().toMap().contains("expires_in") && jsonDoc.toVariant().toMap().contains("refresh_token")) {
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toString();
qCDebug(dcCloud()) << "Token will be refreshed in" << expireTime << "[s]";
m_timer->start((expireTime - 20) * 1000);
}
if (!authenticated())
setAuthenticated(true);
}
reply->deleteLater();
}
void CloudAuthenticator::refreshTimeout()
{
qCDebug(dcCloud()) << "Refresh authentication token for" << m_username;
QUrlQuery query;
query.addQueryItem("grant_type", "refresh_token");
query.addQueryItem("refresh_token", m_refreshToken);
query.addQueryItem("client_id", m_clientId);
query.addQueryItem("client_secret", m_clientSecret);
QNetworkRequest request(m_url);
QByteArray data = QString(m_clientId + ":" + m_clientSecret).toUtf8().toBase64();
QString header = "Basic " + data;
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
m_refreshTokenRequests.append(m_networkManager->post(request, query.toString().toUtf8()));
}
}

View File

@ -0,0 +1,103 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef CLOUDAUTHENTICATOR_H
#define CLOUDAUTHENTICATOR_H
#include <QObject>
#include <QString>
#include <QTimer>
#include <QUrl>
#include <QUrlQuery>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "loggingcategories.h"
namespace guhserver {
class CloudAuthenticator : public QObject
{
Q_OBJECT
public:
explicit CloudAuthenticator(QString clientId, QString clientSecret, QObject *parent = 0);
QUrl url() const;
void setUrl(const QUrl &url);
QUrlQuery query() const;
void setQuery(const QUrlQuery &query);
QString username() const;
void setUsername(const QString &username);
QString password() const;
void setPassword(const QString &password);
QString clientId() const;
void setClientId(const QString &clientId);
QString clientSecret() const;
void setClientSecret(const QString clientSecret);
QString scope() const;
void setScope(const QString &scope);
QString token() const;
bool authenticated() const;
void startAuthentication();
private:
QNetworkAccessManager *m_networkManager;
QTimer *m_timer;
QList<QNetworkReply *> m_tokenRequests;
QList<QNetworkReply *> m_refreshTokenRequests;
QUrl m_url;
QUrlQuery m_query;
QString m_username;
QString m_password;
QString m_clientId;
QString m_clientSecret;
QString m_scope;
QString m_token;
QString m_refreshToken;
bool m_authenticated;
void setAuthenticated(const bool &authenticated);
void setToken(const QString &token);
private slots:
void replyFinished(QNetworkReply *reply);
void refreshTimeout();
signals:
void authenticationChanged();
void tokenChanged();
};
}
#endif // CLOUDAUTHENTICATOR_H

View File

@ -0,0 +1,157 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "cloudconnection.h"
#include "loggingcategories.h"
#include "guhsettings.h"
namespace guhserver {
CloudConnection::CloudConnection(QObject *parent) :
QObject(parent),
m_error(CloudConnectionErrorNoError),
m_enabled(false),
m_connected(false),
m_active(false),
m_authenticated(false)
{
m_proxyUrl = QUrl("ws://127.0.0.1:1212");
m_keystoneUrl = QUrl("http://localhost:8000/oauth2/token");
// GuhSettings settings(GuhSettings::SettingsRoleGlobal);
// settings.beginGroup("CloudConnection");
m_connection = new QWebSocket("guhd", QWebSocketProtocol::Version13, this);
connect(m_connection, SIGNAL(connected()), this, SLOT(onConnected()));
connect(m_connection, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
connect(m_connection, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
connect(m_connection, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
m_authenticator = new CloudAuthenticator("0631d42ba0464e4ebd4b78b15c53f532", "b7919ebf3bcf48239f348e764744079b", this);
m_authenticator->setUrl(m_keystoneUrl);
connect(m_authenticator, &CloudAuthenticator::authenticationChanged, this, &CloudConnection::onAuthenticationChanged);
}
void CloudConnection::connectToCloud(const QString &username, const QString &password)
{
m_authenticator->setUsername(username);
m_authenticator->setPassword(password);
m_authenticator->startAuthentication();
}
CloudConnection::CloudConnectionError CloudConnection::error() const
{
return m_error;
}
void CloudConnection::enable()
{
m_enabled = true;
}
void CloudConnection::disable()
{
m_enabled = false;
}
bool CloudConnection::enabled() const
{
return m_enabled;
}
bool CloudConnection::connected() const
{
return m_connected;
}
bool CloudConnection::active() const
{
return m_active;
}
bool CloudConnection::authenticated() const
{
return m_authenticated;
}
void CloudConnection::setEnabled(const bool &enabled)
{
m_enabled = enabled;
emit enabledChanged();
}
void CloudConnection::setConnected(const bool &connected)
{
m_connected = connected;
emit connectedChanged();
}
void CloudConnection::setActive(const bool &active)
{
m_active = active;
emit activeChanged();
}
void CloudConnection::setAuthenticated(const bool &authenticated)
{
m_authenticated = authenticated;
emit authenticatedChanged();
}
void CloudConnection::onAuthenticationChanged()
{
qCDebug(dcCloud()) << "Authentication changed" << m_authenticator->authenticated();
setAuthenticated(m_authenticator->authenticated());
if (m_authenticated) {
qCDebug(dcCloud()) << "Connecting to" << m_proxyUrl.toString();
m_connection->open(m_proxyUrl);
} else {
m_error = CloudConnectionErrorAuthenticationFailed;
}
}
void CloudConnection::onConnected()
{
qCDebug(dcCloud()) << "Connected to cloud proxy server" << m_proxyUrl.toString();
setConnected(true);
// TODO: authenticate cloud connection
}
void CloudConnection::onDisconnected()
{
qCDebug(dcCloud()) << "Disconnected from cloud connection:" << m_connection->closeReason();
setConnected(false);
}
void CloudConnection::onError(const QAbstractSocket::SocketError &error)
{
qCWarning(dcCloud()) << "Websocket error:" << error << m_connection->errorString();
}
void CloudConnection::onTextMessageReceived(const QString &message)
{
qCDebug(dcCloud()) << "Cloud message received" << message;
}
}

View File

@ -0,0 +1,92 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef CLOUDCONNECTION_H
#define CLOUDCONNECTION_H
#include <QUrl>
#include <QObject>
#include <QWebSocket>
#include "cloudauthenticator.h"
namespace guhserver {
class CloudConnection : public QObject
{
Q_OBJECT
Q_ENUMS(CloudConnectionError)
public:
enum CloudConnectionError {
CloudConnectionErrorNoError,
CloudConnectionErrorAuthenticationFailed,
CloudConnectionErrorCloudServerNotReachable
};
explicit CloudConnection(QObject *parent = 0);
void connectToCloud(const QString &username, const QString &password);
CloudConnectionError error() const;
void enable();
void disable();
bool enabled() const;
bool connected() const;
bool active() const;
bool authenticated() const;
private:
QWebSocket *m_connection;
CloudAuthenticator *m_authenticator;
CloudConnectionError m_error;
QUrl m_proxyUrl;
QUrl m_keystoneUrl;
bool m_enabled;
bool m_connected;
bool m_active;
bool m_authenticated;
void setEnabled(const bool &enabled);
void setConnected(const bool &connected);
void setActive(const bool &active);
void setAuthenticated(const bool &authenticated);
signals:
void enabledChanged();
void connectedChanged();
void activeChanged();
void authenticatedChanged();
private slots:
void onAuthenticationChanged();
void onConnected();
void onDisconnected();
void onError(const QAbstractSocket::SocketError &error);
void onTextMessageReceived(const QString &message);
};
}
#endif // CLOUDCONNECTION_H

View File

@ -362,6 +362,11 @@ TimeManager *GuhCore::timeManager() const
return m_timeManager;
}
CloudConnection *GuhCore::cloudConnection() const
{
return m_cloudConnection;
}
/*! Constructs GuhCore with the given \a parent. This is private.
Use \l{GuhCore::instance()} to access the single instance.*/
GuhCore::GuhCore(QObject *parent) :
@ -373,6 +378,9 @@ GuhCore::GuhCore(QObject *parent) :
qCDebug(dcApplication) << "Creating Log Engine";
m_logger = new LogEngine(this);
qCDebug(dcApplication) << "Creating Cloud Connection";
m_cloudConnection = new CloudConnection(this);
qCDebug(dcApplication) << "Creating Device Manager";
m_deviceManager = new DeviceManager(this);

View File

@ -32,6 +32,7 @@
#include "ruleengine.h"
#include "servermanager.h"
#include "cloud/cloudconnection.h"
#include "time/timemanager.h"
#include <QObject>
@ -70,6 +71,7 @@ public:
DeviceManager *deviceManager() const;
RuleEngine *ruleEngine() const;
TimeManager *timeManager() const;
CloudConnection *cloudConnection() const;
signals:
void eventTriggered(const Event &event);
@ -98,6 +100,7 @@ private:
RuleEngine *m_ruleEngine;
LogEngine *m_logger;
TimeManager *m_timeManager;
CloudConnection *m_cloudConnection;
QHash<ActionId, Action> m_pendingActions;

View File

@ -39,8 +39,6 @@
#include "types/action.h"
#include "loggingcategories.h"
#include <QDebug>
namespace guhserver {
/*! Constructs a new \l ActionHandler with the given \a parent. */
@ -75,7 +73,6 @@ QString ActionHandler::name() const
JsonReply* ActionHandler::ExecuteAction(const QVariantMap &params)
{
DeviceId deviceId(params.value("deviceId").toString());
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
ParamList actionParams = JsonTypes::unpackParams(params.value("params").toList());

View File

@ -0,0 +1,105 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "cloudhandler.h"
namespace guhserver {
CloudHandler::CloudHandler(QObject *parent) :
JsonHandler(parent)
{
QVariantMap returns;
QVariantMap params;
setDescription("Authenticate", "Connect and authenticate the cloud connection with the given username and password.");
params.insert("username", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("password", JsonTypes::basicTypeToString(JsonTypes::String));
setParams("Authenticate", params);
returns.insert("cloudConnectionError", JsonTypes::cloudConnectionErrorRef());
setReturns("Authenticate", returns);
params.clear(); returns.clear();
setDescription("GetConnectionStatus", "Get the current status of the cloud connection.");
setParams("GetConnectionStatus", params);
returns.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("authenticated", JsonTypes::basicTypeToString(JsonTypes::Bool));
setReturns("GetConnectionStatus", returns);
// Notification
params.clear(); returns.clear();
setDescription("ConnectionStatusChanged", "Emitted whenever the status of the cloud connection changed.");
params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
params.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool));
params.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool));
params.insert("authenticated", JsonTypes::basicTypeToString(JsonTypes::Bool));
setParams("ConnectionStatusChanged", params);
connect(GuhCore::instance()->cloudConnection(), SIGNAL(enabledChanged()), this, SLOT(onConnectionStatusChanged()));
connect(GuhCore::instance()->cloudConnection(), SIGNAL(connectedChanged()), this, SLOT(onConnectionStatusChanged()));
connect(GuhCore::instance()->cloudConnection(), SIGNAL(activeChanged()), this, SLOT(onConnectionStatusChanged()));
connect(GuhCore::instance()->cloudConnection(), SIGNAL(authenticatedChanged()), this, SLOT(onConnectionStatusChanged()));
}
QString CloudHandler::name() const
{
return "Cloud";
}
JsonReply *CloudHandler::Authenticate(const QVariantMap &params) const
{
Q_UNUSED(params)
QString username = params.value("username").toString();
QString password = params.value("password").toString();
qCDebug(dcJsonRpc()) << "Authenticate cloud connection for user" << username;
GuhCore::instance()->cloudConnection()->connectToCloud(username, password);
QVariantMap returns;
returns.insert("cloudConnectionError", JsonTypes::cloudConnectionErrorToString(CloudConnection::CloudConnectionErrorNoError));
return createReply(returns);
}
JsonReply *CloudHandler::GetConnectionStatus(const QVariantMap &params) const
{
Q_UNUSED(params)
QVariantMap returns;
returns.insert("enabled", GuhCore::instance()->cloudConnection()->enabled());
returns.insert("connected", GuhCore::instance()->cloudConnection()->connected());
returns.insert("active", GuhCore::instance()->cloudConnection()->active());
returns.insert("authenticated", GuhCore::instance()->cloudConnection()->authenticated());
return createReply(returns);
}
void CloudHandler::onConnectionStatusChanged()
{
QVariantMap params;
params.insert("enabled", GuhCore::instance()->cloudConnection()->enabled());
params.insert("connected", GuhCore::instance()->cloudConnection()->connected());
params.insert("active", GuhCore::instance()->cloudConnection()->active());
params.insert("authenticated", GuhCore::instance()->cloudConnection()->authenticated());
emit ConnectionStatusChanged(params);
}
}

View File

@ -0,0 +1,53 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef CLOUDHANDLER_H
#define CLOUDHANDLER_H
#include <QObject>
#include "guhcore.h"
#include "jsonhandler.h"
#include "loggingcategories.h"
namespace guhserver {
class CloudHandler : public JsonHandler
{
Q_OBJECT
public:
CloudHandler(QObject *parent = 0);
QString name() const;
Q_INVOKABLE JsonReply* Authenticate(const QVariantMap &params) const;
Q_INVOKABLE JsonReply* GetConnectionStatus(const QVariantMap &params) const;
signals:
void ConnectionStatusChanged(const QVariantMap &params);
private slots:
void onConnectionStatusChanged();
};
}
#endif // CLOUDHANDLER_H

View File

@ -54,6 +54,8 @@
#include "eventhandler.h"
#include "logginghandler.h"
#include "statehandler.h"
#include "websocketserver.h"
#include "cloudhandler.h"
#ifndef TESTING_ENABLED
#include "tcpserver.h"
@ -61,10 +63,6 @@
#include "mocktcpserver.h"
#endif
#ifdef WEBSOCKET
#include "websocketserver.h"
#endif
#include <QJsonDocument>
#include <QStringList>
#include <QSslConfiguration>
@ -79,9 +77,7 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
#else
m_tcpServer(new TcpServer(this)),
#endif
#ifdef WEBSOCKET
m_websocketServer(new WebSocketServer(sslConfiguration, this)),
#endif
m_notificationId(0)
{
// First, define our own JSONRPC methods
@ -117,16 +113,12 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
m_interfaces.append(m_tcpServer);
#ifdef WEBSOCKET
connect(m_websocketServer, SIGNAL(clientConnected(const QUuid &)), this, SLOT(clientConnected(const QUuid &)));
connect(m_websocketServer, SIGNAL(clientDisconnected(const QUuid &)), this, SLOT(clientDisconnected(const QUuid &)));
connect(m_websocketServer, SIGNAL(dataAvailable(QUuid, QString, QString, QVariantMap)), this, SLOT(processData(QUuid, QString, QString, QVariantMap)));
m_websocketServer->startServer();
m_interfaces.append(m_websocketServer);
#else
Q_UNUSED(sslConfiguration)
#endif
QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection);
}
@ -192,6 +184,7 @@ void JsonRPCServer::setup()
registerHandler(new EventHandler(this));
registerHandler(new LoggingHandler(this));
registerHandler(new StateHandler(this));
registerHandler(new CloudHandler(this));
}
void JsonRPCServer::processData(const QUuid &clientId, const QString &targetNamespace, const QString &method, const QVariantMap &message)

View File

@ -43,9 +43,7 @@ class MockTcpServer;
namespace guhserver {
#ifdef WEBSOCKET
class WebSocketServer;
#endif
#ifndef TESTING_ENABLED
class TcpServer;
@ -84,10 +82,7 @@ private:
TcpServer *m_tcpServer;
#endif
#ifdef WEBSOCKET
WebSocketServer *m_websocketServer;
#endif
QList<TransportInterface *> m_interfaces;
QHash<QString, JsonHandler *> m_handlers;
QHash<JsonReply *, TransportInterface *> m_asyncReplies;

View File

@ -82,6 +82,7 @@ QVariantList JsonTypes::s_loggingSource;
QVariantList JsonTypes::s_loggingLevel;
QVariantList JsonTypes::s_loggingEventType;
QVariantList JsonTypes::s_repeatingMode;
QVariantList JsonTypes::s_cloudConnectionError;
QVariantMap JsonTypes::s_paramType;
QVariantMap JsonTypes::s_param;
@ -110,7 +111,6 @@ QVariantMap JsonTypes::s_calendarItem;
QVariantMap JsonTypes::s_timeEventItem;
QVariantMap JsonTypes::s_repeatingOption;
void JsonTypes::init()
{
// BasicTypes
@ -131,6 +131,7 @@ void JsonTypes::init()
s_loggingLevel = enumToStrings(Logging::staticMetaObject, "LoggingLevel");
s_loggingEventType = enumToStrings(Logging::staticMetaObject, "LoggingEventType");
s_repeatingMode = enumToStrings(RepeatingOption::staticMetaObject, "RepeatingMode");
s_cloudConnectionError = enumToStrings(CloudConnection::staticMetaObject, "CloudConnectionError");
// ParamType
s_paramType.insert("name", basicTypeToString(String));
@ -359,6 +360,7 @@ QVariantMap JsonTypes::allTypes()
allTypes.insert("LoggingSource", loggingSource());
allTypes.insert("LoggingEventType", loggingEventType());
allTypes.insert("RepeatingMode", repeatingMode());
allTypes.insert("CloudConnectionError", cloudConnectionError());
allTypes.insert("StateType", stateTypeDescription());
allTypes.insert("StateDescriptor", stateDescriptorDescription());
@ -1748,10 +1750,10 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(repeatingModeRef());
return result;
}
} else if (refName == removePolicyRef()) {
QPair<bool, QString> result = validateEnum(s_removePolicy, variant);
} else if (refName == cloudConnectionErrorRef()) {
QPair<bool, QString> result = validateEnum(s_cloudConnectionError, variant);
if (!result.first) {
qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(removePolicyRef());
qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(cloudConnectionErrorRef());
return result;
}
} else {

View File

@ -44,6 +44,8 @@
#include "time/timedescriptor.h"
#include "time/timeeventitem.h"
#include "cloud/cloudconnection.h"
#include <QObject>
#include <QVariantMap>
@ -122,6 +124,7 @@ public:
DECLARE_TYPE(loggingLevel, "LoggingLevel", Logging, LoggingLevel)
DECLARE_TYPE(loggingEventType, "LoggingEventType", Logging, LoggingEventType)
DECLARE_TYPE(repeatingMode, "RepeatingMode", RepeatingOption, RepeatingMode)
DECLARE_TYPE(cloudConnectionError, "CloudConnectionError", CloudConnection, CloudConnectionError)
DECLARE_OBJECT(paramType, "ParamType")
DECLARE_OBJECT(param, "Param")
@ -178,7 +181,6 @@ public:
static QVariantMap packTimeEventItem(const TimeEventItem &timeEventItem);
static QVariantMap packTimeDescriptor(const TimeDescriptor &timeDescriptor);
// pack resources
static QVariantList packRules(const QList<Rule> rules);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);

View File

@ -120,6 +120,7 @@ int main(int argc, char *argv[])
s_loggingFilters.insert("TimeManager", false);
s_loggingFilters.insert("Coap", false);
s_loggingFilters.insert("Avahi", false);
s_loggingFilters.insert("Cloud", true);
QHash<QString, bool> loggingFiltersPlugins;
foreach (const QJsonObject &pluginMetadata, DeviceManager::pluginsMetadata()) {

View File

@ -1,15 +1,6 @@
# check websocket support
contains(DEFINES, WEBSOCKET){
QT += websockets
HEADERS += $$top_srcdir/server/websocketserver.h
SOURCES += $$top_srcdir/server/websocketserver.cpp
}
# icons for the webserver
RESOURCES += $$top_srcdir/icons.qrc
HEADERS += $$top_srcdir/server/guhcore.h \
$$top_srcdir/server/tcpserver.h \
$$top_srcdir/server/ruleengine.h \
@ -23,6 +14,7 @@ HEADERS += $$top_srcdir/server/guhcore.h \
$$top_srcdir/server/jsonrpc/eventhandler.h \
$$top_srcdir/server/jsonrpc/statehandler.h \
$$top_srcdir/server/jsonrpc/logginghandler.h \
$$top_srcdir/server/jsonrpc/cloudhandler.h \
$$top_srcdir/server/stateevaluator.h \
$$top_srcdir/server/logging/logging.h \
$$top_srcdir/server/logging/logengine.h \
@ -32,6 +24,7 @@ HEADERS += $$top_srcdir/server/guhcore.h \
$$top_srcdir/server/transportinterface.h \
$$top_srcdir/server/servermanager.h \
$$top_srcdir/server/httprequest.h \
$$top_srcdir/server/websocketserver.h \
$$top_srcdir/server/httpreply.h \
$$top_srcdir/server/rest/restserver.h \
$$top_srcdir/server/rest/restresource.h \
@ -45,7 +38,9 @@ HEADERS += $$top_srcdir/server/guhcore.h \
$$top_srcdir/server/time/calendaritem.h \
$$top_srcdir/server/time/repeatingoption.h \
$$top_srcdir/server/time/timeeventitem.h \
$$top_srcdir/server/time/timemanager.h
$$top_srcdir/server/time/timemanager.h \
$$top_srcdir/server/cloud/cloudconnection.h \
$$top_srcdir/server/cloud/cloudauthenticator.h \
SOURCES += $$top_srcdir/server/guhcore.cpp \
@ -61,6 +56,7 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \
$$top_srcdir/server/jsonrpc/eventhandler.cpp \
$$top_srcdir/server/jsonrpc/statehandler.cpp \
$$top_srcdir/server/jsonrpc/logginghandler.cpp \
$$top_srcdir/server/jsonrpc/cloudhandler.cpp \
$$top_srcdir/server/stateevaluator.cpp \
$$top_srcdir/server/logging/logengine.cpp \
$$top_srcdir/server/logging/logfilter.cpp \
@ -69,6 +65,7 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \
$$top_srcdir/server/transportinterface.cpp \
$$top_srcdir/server/servermanager.cpp \
$$top_srcdir/server/httprequest.cpp \
$$top_srcdir/server/websocketserver.cpp \
$$top_srcdir/server/httpreply.cpp \
$$top_srcdir/server/rest/restserver.cpp \
$$top_srcdir/server/rest/restresource.cpp \
@ -82,4 +79,6 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \
$$top_srcdir/server/time/calendaritem.cpp \
$$top_srcdir/server/time/repeatingoption.cpp \
$$top_srcdir/server/time/timeeventitem.cpp \
$$top_srcdir/server/time/timemanager.cpp
$$top_srcdir/server/time/timemanager.cpp \
$$top_srcdir/server/cloud/cloudconnection.cpp \
$$top_srcdir/server/cloud/cloudauthenticator.cpp \

View File

@ -8,7 +8,7 @@ INCLUDEPATH += ../libguh jsonrpc
target.path = /usr/bin
INSTALLS += target
QT += sql xml
QT += sql xml websockets
LIBS += -L$$top_builddir/libguh/ -lguh

View File

@ -103,7 +103,6 @@ void TransportInterface::sendResponse(const QUuid &clientId, int commandId, cons
sendData(clientId, response);
}
/*! Send a JSON error response to the client with the given \a clientId,
* \a commandId and \a error to the inerted \l{TransportInterface}.
*/

View File

@ -31,9 +31,7 @@
#include <QSignalSpy>
#include <QJsonDocument>
#ifdef WEBSOCKET
#include <QWebSocket>
#endif
using namespace guhserver;
@ -42,7 +40,6 @@ class TestWebSocketServer: public GuhTestBase
Q_OBJECT
private slots:
#ifdef WEBSOCKET
void testHandshake();
void pingTest();
@ -57,11 +54,8 @@ private:
QVariant injectSocketAndWait(const QString &method, const QVariantMap &params = QVariantMap());
QVariant injectSocketData(const QByteArray &data);
#endif
};
#ifdef WEBSOCKET
void TestWebSocketServer::testHandshake()
{
@ -216,7 +210,5 @@ QVariant TestWebSocketServer::injectSocketData(const QByteArray &data)
return QVariant();
}
#endif
#include "testwebsocketserver.moc"
QTEST_MAIN(TestWebSocketServer)

View File

@ -1,9 +1,7 @@
include(../../../guh.pri)
include(../autotests.pri)
contains(DEFINES, WEBSOCKET){
QT += websockets
}
QT += websockets
TARGET = websocketserver
SOURCES += testwebsocketserver.cpp