From f3d944e8902a4a3acffe7ffa4708cfabddafc2fa Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 15 Nov 2018 23:11:06 +0100 Subject: [PATCH] more work on mqtt, intermediate commit --- .../configuration/basicconfiguration.cpp | 237 ----------- .../configuration/mqttbrokerconfiguration.cpp | 32 ++ .../configuration/mqttbrokerconfiguration.h | 29 ++ .../configuration/nymeaconfiguration.cpp | 373 ++++++++++++++++++ ...icconfiguration.h => nymeaconfiguration.h} | 73 ++-- .../configuration/serverconfiguration.cpp | 38 ++ .../configuration/serverconfiguration.h | 27 +- .../configuration/serverconfigurations.cpp | 38 ++ .../configuration/serverconfigurations.h | 3 + libnymea-app-core/engine.cpp | 15 +- libnymea-app-core/engine.h | 11 +- libnymea-app-core/jsonrpc/jsonrpcclient.cpp | 3 +- libnymea-app-core/libnymea-app-core.h | 11 +- libnymea-app-core/libnymea-app-core.pro | 10 +- nymea-app/images.qrc | 2 + nymea-app/resources.qrc | 2 + nymea-app/ui/Nymea.qml | 2 +- nymea-app/ui/RootItem.qml | 2 +- nymea-app/ui/SettingsPage.qml | 53 +-- .../ui/components/MeaListItemDelegate.qml | 1 + .../ui/images/messaging-app-symbolic.svg | 176 +++++++++ nymea-app/ui/images/mqtt.svg | 72 ++++ nymea-app/ui/system/CloudSettingsPage.qml | 4 +- .../ui/system/ConnectionInterfaceDelegate.qml | 6 +- .../ui/system/ConnectionInterfacesPage.qml | 75 +++- .../ui/system/MqttBrokerSettingsPage.qml | 81 ++++ .../ui/system/ServerConfigurationDialog.qml | 95 +++++ 27 files changed, 1144 insertions(+), 327 deletions(-) delete mode 100644 libnymea-app-core/configuration/basicconfiguration.cpp create mode 100644 libnymea-app-core/configuration/mqttbrokerconfiguration.cpp create mode 100644 libnymea-app-core/configuration/mqttbrokerconfiguration.h create mode 100644 libnymea-app-core/configuration/nymeaconfiguration.cpp rename libnymea-app-core/configuration/{basicconfiguration.h => nymeaconfiguration.h} (62%) create mode 100644 nymea-app/ui/images/messaging-app-symbolic.svg create mode 100644 nymea-app/ui/images/mqtt.svg create mode 100644 nymea-app/ui/system/MqttBrokerSettingsPage.qml create mode 100644 nymea-app/ui/system/ServerConfigurationDialog.qml diff --git a/libnymea-app-core/configuration/basicconfiguration.cpp b/libnymea-app-core/configuration/basicconfiguration.cpp deleted file mode 100644 index dc76ed2d..00000000 --- a/libnymea-app-core/configuration/basicconfiguration.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#include "basicconfiguration.h" -#include "serverconfiguration.h" - -#include "jsonrpc/jsonrpcclient.h" - -BasicConfiguration::BasicConfiguration(JsonRpcClient* client, QObject *parent) : - JsonHandler(parent), - m_client(client), - m_tcpServerConfigurations(new ServerConfigurations(this)), - m_websocketServerConfigurations(new ServerConfigurations(this)) -{ - client->registerNotificationHandler(this, "notificationReceived"); -} - -QString BasicConfiguration::nameSpace() const -{ - return "Configuration"; -} - -bool BasicConfiguration::debugServerEnabled() const -{ - return m_debugServerEnabled; -} - -void BasicConfiguration::setDebugServerEnabled(bool debugServerEnabled) -{ - QVariantMap params; - params.insert("enabled", debugServerEnabled); - m_client->sendCommand("Configuration.SetDebugServerEnabled", params, this, "setDebugServerEnabledResponse"); -} - -QString BasicConfiguration::serverName() const -{ - return m_serverName; -} - -void BasicConfiguration::setServerName(const QString &serverName) -{ - QVariantMap params; - params.insert("serverName", serverName); - m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse"); -} - -bool BasicConfiguration::cloudEnabled() const -{ - return m_cloudEnabled; -} - -void BasicConfiguration::setCloudEnabled(bool cloudEnabled) -{ - QVariantMap params; - params.insert("enabled", cloudEnabled); - m_client->sendCommand("Configuration.SetCloudEnabled", params, this, "setCloudEnabledResponse"); -} - -QString BasicConfiguration::language() const -{ - return m_language; -} - -void BasicConfiguration::setLanguage(const QString &language) -{ - QVariantMap params; - params.insert("language", language); - m_client->sendCommand("Configuration.SetLanguage", params); -} - -QString BasicConfiguration::timezone() const -{ - return m_timezone; -} - -void BasicConfiguration::setTimezone(const QString &timezone) -{ - QVariantMap params; - params.insert("timeZone", timezone); - m_client->sendCommand("Configuration.SetTimeZone", params, this, "setTimezoneResponse"); -} - -QStringList BasicConfiguration::timezones() const -{ - return m_timezones; -} - -ServerConfigurations *BasicConfiguration::tcpServerConfigurations() const -{ - return m_tcpServerConfigurations; -} - -ServerConfigurations *BasicConfiguration::websocketServerConfigurations() const -{ - return m_websocketServerConfigurations; -} - -void BasicConfiguration::setTcpServerConfiguration(ServerConfiguration *configuration) const -{ - QVariantMap params; - params.insert("id", configuration->id()); - params.insert("address", configuration->address()); - params.insert("port", configuration->address()); - params.insert("authentiactionEnabled", configuration->authenticationEnabled()); - params.insert("sslEnabled", configuration->sslEnabled()); - m_client->sendCommand("Configuration.SetTcpServerConfiguration", params); -} - -void BasicConfiguration::deleteTcpServerConfiguration(const QString &id) -{ - QVariantMap params; - params.insert("id", id); - m_client->sendCommand("Configuration.DeleteTcpServerConfiguration", params, this, "deleteTcpConfigReply"); -} - -void BasicConfiguration::deleteWebsocketServerConfiguration(const QString &id) -{ - QVariantMap params; - params.insert("id", id); - m_client->sendCommand("Configuration.DeleteWebSocketServerConfiguration", params, this, "deleteWebSocketConfigReply"); -} - -QStringList BasicConfiguration::availableLanguages() const -{ - return m_availableLanguages; -} - -void BasicConfiguration::init() -{ - m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse"); - m_client->sendCommand("Configuration.GetAvailableLanguages", this, "getAvailableLanguagesResponse"); - m_client->sendCommand("Configuration.GetTimeZones", this, "getTimezonesResponse"); -} - -void BasicConfiguration::getConfigurationsResponse(const QVariantMap ¶ms) -{ - qDebug() << "have config reply" << params; - QVariantMap basicConfig = params.value("params").toMap().value("basicConfiguration").toMap(); - m_debugServerEnabled = basicConfig.value("debugServerEnabled").toBool(); - emit debugServerEnabledChanged(); - m_serverName = basicConfig.value("serverName").toString(); - emit serverNameChanged(); - m_language = basicConfig.value("language").toString(); - emit languageChanged(); - m_timezone = basicConfig.value("timeZone").toString(); - emit timezoneChanged(); - QVariantMap cloudConfig = params.value("params").toMap().value("cloud").toMap(); - m_cloudEnabled = cloudConfig.value("enabled").toBool(); - emit cloudEnabledChanged(); - - tcpServerConfigurations()->clear(); - foreach (const QVariant &tcpServerVariant, params.value("params").toMap().value("tcpServerConfigurations").toList()) { - qDebug() << "tcp server config:" << tcpServerVariant; - QVariantMap tcpConfigMap = tcpServerVariant.toMap(); - ServerConfiguration *config = new ServerConfiguration(tcpConfigMap.value("id").toString(), QHostAddress(tcpConfigMap.value("address").toString()), tcpConfigMap.value("port").toInt(), tcpConfigMap.value("authenticationEnabled").toBool(), tcpConfigMap.value("sslEnabled").toBool()); - m_tcpServerConfigurations->addConfiguration(config); - } - websocketServerConfigurations()->clear(); - foreach (const QVariant &websocketServerVariant, params.value("params").toMap().value("webSocketServerConfigurations").toList()) { - QVariantMap websocketConfigMap = websocketServerVariant.toMap(); - ServerConfiguration *config = new ServerConfiguration(websocketConfigMap.value("id").toString(), QHostAddress(websocketConfigMap.value("address").toString()), websocketConfigMap.value("port").toInt(), websocketConfigMap.value("authenticationEnabled").toBool(), websocketConfigMap.value("sslEnabled").toBool()); - m_websocketServerConfigurations->addConfiguration(config); - } -} - -void BasicConfiguration::getCloudConfigurationResponse(const QVariantMap ¶ms) -{ - qDebug() << "Cloud config reply" << params; -} - -void BasicConfiguration::setDebugServerEnabledResponse(const QVariantMap ¶ms) -{ - qDebug() << "Debug server set:" << params; -} - -void BasicConfiguration::setServerNameResponse(const QVariantMap ¶ms) -{ - qDebug() << "Server name set:" << params; -} - -void BasicConfiguration::setCloudEnabledResponse(const QVariantMap ¶ms) -{ - qDebug() << "Set cloud enabled:" << params; -} - -void BasicConfiguration::getAvailableLanguagesResponse(const QVariantMap ¶ms) -{ -// qDebug() << "Get available languages response" << params; - m_availableLanguages = params.value("params").toMap().value("languages").toStringList(); - emit availableLanguagesChanged(); -} - -void BasicConfiguration::getTimezonesResponse(const QVariantMap ¶ms) -{ -// qDebug() << "Get timezones response" << params; - m_timezones = params.value("params").toMap().value("timeZones").toStringList(); - emit timezonesChanged(); -} - -void BasicConfiguration::setTimezoneResponse(const QVariantMap ¶ms) -{ - qDebug() << "Set timezones response" << params; -} - -void BasicConfiguration::deleteTcpConfigReply(const QVariantMap ¶ms) -{ - if (params.value("params").toMap().value("configurationError").toString() == "ConfigurationErrorNoError") { - } -} - -void BasicConfiguration::deleteWebSocketConfigReply(const QVariantMap ¶ms) -{ - -} - -void BasicConfiguration::notificationReceived(const QVariantMap ¬ification) -{ - QString notif = notification.value("notification").toString(); - if (notif == "Configuration.BasicConfigurationChanged") { - QVariantMap params = notification.value("params").toMap().value("basicConfiguration").toMap(); - qDebug() << "notif" << params; - m_debugServerEnabled = params.value("debugServerEnabled").toBool(); - emit debugServerEnabledChanged(); - m_serverName = params.value("serverName").toString(); - emit serverNameChanged(); - m_language = params.value("language").toString(); - emit languageChanged(); - m_timezone = params.value("timeZone").toString(); - emit timezoneChanged(); - return; - } - if (notif == "Configuration.CloudConfigurationChanged") { - QVariantMap params = notification.value("params").toMap().value("cloudConfiguration").toMap(); - qDebug() << "notif" << params; - m_cloudEnabled = params.value("enabled").toBool(); - emit cloudEnabledChanged(); - return; - } - qDebug() << "Unhandled Configuration notification" << notif; -} diff --git a/libnymea-app-core/configuration/mqttbrokerconfiguration.cpp b/libnymea-app-core/configuration/mqttbrokerconfiguration.cpp new file mode 100644 index 00000000..9836e776 --- /dev/null +++ b/libnymea-app-core/configuration/mqttbrokerconfiguration.cpp @@ -0,0 +1,32 @@ +#include "mqttbrokerconfiguration.h" + +MqttBrokerConfiguration::MqttBrokerConfiguration(QObject *parent) : QObject(parent) +{ + +} + +QString MqttBrokerConfiguration::username() const +{ + return m_username; +} + +void MqttBrokerConfiguration::setUsername(const QString &username) +{ + if (m_username != username) { + m_username = username; + emit usernameChanged(); + } +} + +QString MqttBrokerConfiguration::password() const +{ + return m_password; +} + +void MqttBrokerConfiguration::setPassword(const QString &password) +{ + if (m_password != password) { + m_password = password; + emit passwordChanged(); + } +} diff --git a/libnymea-app-core/configuration/mqttbrokerconfiguration.h b/libnymea-app-core/configuration/mqttbrokerconfiguration.h new file mode 100644 index 00000000..9e955d12 --- /dev/null +++ b/libnymea-app-core/configuration/mqttbrokerconfiguration.h @@ -0,0 +1,29 @@ +#ifndef MQTTBROKERCONFIGURATION_H +#define MQTTBROKERCONFIGURATION_H + +#include + +class MqttBrokerConfiguration : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) + Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) +public: + explicit MqttBrokerConfiguration(QObject *parent = nullptr); + + QString username() const; + void setUsername(const QString &username); + + QString password() const; + void setPassword(const QString &password); + +signals: + void usernameChanged(); + void passwordChanged(); + +private: + QString m_username; + QString m_password; +}; + +#endif // MQTTBROKERCONFIGURATION_H diff --git a/libnymea-app-core/configuration/nymeaconfiguration.cpp b/libnymea-app-core/configuration/nymeaconfiguration.cpp new file mode 100644 index 00000000..ad2bef97 --- /dev/null +++ b/libnymea-app-core/configuration/nymeaconfiguration.cpp @@ -0,0 +1,373 @@ +#include "nymeaconfiguration.h" + +#include "serverconfiguration.h" +#include "serverconfigurations.h" +#include "mqttbrokerconfiguration.h" + +#include "jsonrpc/jsonrpcclient.h" + +#include + +NymeaConfiguration::NymeaConfiguration(JsonRpcClient *client, QObject *parent): + JsonHandler(parent), + m_client(client), + m_tcpServerConfigurations(new ServerConfigurations(this)), + m_webSocketServerConfigurations(new ServerConfigurations(this)), + m_mqttServerConfigurations(new ServerConfigurations(this)), + m_mqttBrokerConfiguration(new MqttBrokerConfiguration(this)) +{ + client->registerNotificationHandler(this, "notificationReceived"); +} + +QString NymeaConfiguration::nameSpace() const +{ + return "Configuration"; +} + +void NymeaConfiguration::init() +{ + m_tcpServerConfigurations->clear(); + m_webSocketServerConfigurations->clear(); + m_mqttServerConfigurations->clear(); + m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse"); + m_client->sendCommand("Configuration.GetAvailableLanguages", this, "getAvailableLanguagesResponse"); + m_client->sendCommand("Configuration.GetTimeZones", this, "getTimezonesResponse"); +} + +QString NymeaConfiguration::serverName() const +{ + return m_serverName; +} + +void NymeaConfiguration::setServerName(const QString &serverName) +{ + QVariantMap params; + params.insert("serverName", serverName); + m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse"); +} + +QString NymeaConfiguration::language() const +{ + return m_language; +} + +void NymeaConfiguration::setLanguage(const QString &language) +{ + QVariantMap params; + params.insert("language", language); + m_client->sendCommand("Configuration.SetLanguage", params); +} + +QStringList NymeaConfiguration::availableLanguages() const +{ + return m_availableLanguages; +} + +QString NymeaConfiguration::timezone() const +{ + return m_timezone; +} + +void NymeaConfiguration::setTimezone(const QString &timezone) +{ + QVariantMap params; + params.insert("timeZone", timezone); + m_client->sendCommand("Configuration.SetTimeZone", params, this, "setTimezoneResponse"); +} + +QStringList NymeaConfiguration::timezones() const +{ + return m_timezones; +} + +bool NymeaConfiguration::debugServerEnabled() const +{ + return m_debugServerEnabled; +} + +void NymeaConfiguration::setDebugServerEnabled(bool debugServerEnabled) +{ + QVariantMap params; + params.insert("enabled", debugServerEnabled); + m_client->sendCommand("Configuration.SetDebugServerEnabled", params, this, "setDebugServerEnabledResponse"); +} + +bool NymeaConfiguration::cloudEnabled() const +{ + return m_cloudEnabled; +} + +void NymeaConfiguration::setCloudEnabled(bool cloudEnabled) +{ + QVariantMap params; + params.insert("enabled", cloudEnabled); + m_client->sendCommand("Configuration.SetCloudEnabled", params, this, "setCloudEnabledResponse"); +} + +ServerConfigurations *NymeaConfiguration::tcpServerConfigurations() const +{ + return m_tcpServerConfigurations; +} + +ServerConfigurations *NymeaConfiguration::webSocketServerConfigurations() const +{ + return m_webSocketServerConfigurations; +} + +ServerConfigurations *NymeaConfiguration::mqttServerConfigurations() const +{ + return m_mqttServerConfigurations; +} + +MqttBrokerConfiguration *NymeaConfiguration::mqttBrokerConfiguration() const +{ + return m_mqttBrokerConfiguration; +} + +ServerConfiguration *NymeaConfiguration::createServerConfiguration(const QString &address, int port, bool authEnabled, bool sslEnabled) +{ + return new ServerConfiguration(QUuid::createUuid().toString(), QHostAddress(address), port, authEnabled, sslEnabled); +} + +void NymeaConfiguration::setTcpServerConfiguration(ServerConfiguration *configuration) +{ + QVariantMap params; + QVariantMap configurationMap; + configurationMap.insert("id", configuration->id()); + configurationMap.insert("address", configuration->address()); + configurationMap.insert("port", configuration->port()); + configurationMap.insert("authenticationEnabled", configuration->authenticationEnabled()); + configurationMap.insert("sslEnabled", configuration->sslEnabled()); + params.insert("configuration", configurationMap); + m_client->sendCommand("Configuration.SetTcpServerConfiguration", params, this, "setTcpConfigReply"); +} + +void NymeaConfiguration::setWebSocketServerConfiguration(ServerConfiguration *configuration) +{ + QVariantMap params; + QVariantMap configurationMap; + configurationMap.insert("id", configuration->id()); + configurationMap.insert("address", configuration->address()); + configurationMap.insert("port", configuration->port()); + configurationMap.insert("authenticationEnabled", configuration->authenticationEnabled()); + configurationMap.insert("sslEnabled", configuration->sslEnabled()); + params.insert("configuration", configurationMap); + m_client->sendCommand("Configuration.SetWebSocketServerConfiguration", params, this, "setWebSocketConfigReply"); +} + +void NymeaConfiguration::setMqttServerConfiguration(ServerConfiguration *configuration) +{ + QVariantMap params; + QVariantMap configurationMap; + configurationMap.insert("id", configuration->id()); + configurationMap.insert("address", configuration->address()); + configurationMap.insert("port", configuration->port()); + configurationMap.insert("authenticationEnabled", configuration->authenticationEnabled()); + configurationMap.insert("sslEnabled", configuration->sslEnabled()); + params.insert("configuration", configurationMap); + m_client->sendCommand("Configuration.SetMqttServerConfiguration", params, this, "setMqttConfigReply"); +} + +void NymeaConfiguration::deleteTcpServerConfiguration(const QString &id) +{ + QVariantMap params; + params.insert("id", id); + m_client->sendCommand("Configuration.DeleteTcpServerConfiguration", params, this, "deleteTcpConfigReply"); +} + +void NymeaConfiguration::deleteWebSocketServerConfiguration(const QString &id) +{ + QVariantMap params; + params.insert("id", id); + m_client->sendCommand("Configuration.DeleteWebSocketServerConfiguration", params, this, "deleteWebSocketConfigReply"); +} + +void NymeaConfiguration::deleteMqttServerConfiguration(const QString &id) +{ + QVariantMap params; + params.insert("id", id); + m_client->sendCommand("Configuration.DeleteMqttServerConfiguration", params, this, "deleteMqttConfigReply"); +} + +void NymeaConfiguration::getConfigurationsResponse(const QVariantMap ¶ms) +{ + qDebug() << "have config reply" << params; + QVariantMap basicConfig = params.value("params").toMap().value("basicConfiguration").toMap(); + m_debugServerEnabled = basicConfig.value("debugServerEnabled").toBool(); + emit debugServerEnabledChanged(); + m_serverName = basicConfig.value("serverName").toString(); + emit serverNameChanged(); + m_language = basicConfig.value("language").toString(); + emit languageChanged(); + m_timezone = basicConfig.value("timeZone").toString(); + emit timezoneChanged(); + QVariantMap cloudConfig = params.value("params").toMap().value("cloud").toMap(); + m_cloudEnabled = cloudConfig.value("enabled").toBool(); + emit cloudEnabledChanged(); + + tcpServerConfigurations()->clear(); + foreach (const QVariant &tcpServerVariant, params.value("params").toMap().value("tcpServerConfigurations").toList()) { + qDebug() << "tcp server config:" << tcpServerVariant; + QVariantMap tcpConfigMap = tcpServerVariant.toMap(); + ServerConfiguration *config = new ServerConfiguration(tcpConfigMap.value("id").toString(), QHostAddress(tcpConfigMap.value("address").toString()), tcpConfigMap.value("port").toInt(), tcpConfigMap.value("authenticationEnabled").toBool(), tcpConfigMap.value("sslEnabled").toBool()); + m_tcpServerConfigurations->addConfiguration(config); + } + webSocketServerConfigurations()->clear(); + foreach (const QVariant &websocketServerVariant, params.value("params").toMap().value("webSocketServerConfigurations").toList()) { + QVariantMap websocketConfigMap = websocketServerVariant.toMap(); + ServerConfiguration *config = new ServerConfiguration(websocketConfigMap.value("id").toString(), QHostAddress(websocketConfigMap.value("address").toString()), websocketConfigMap.value("port").toInt(), websocketConfigMap.value("authenticationEnabled").toBool(), websocketConfigMap.value("sslEnabled").toBool()); + m_webSocketServerConfigurations->addConfiguration(config); + } + + if (m_client->ensureServerVersion("1.11")) { + foreach (const QVariant &mqttServerVariant, params.value("params").toMap().value("mqttServerConfigurations").toList()) { + QVariantMap mqttConfigMap = mqttServerVariant.toMap(); + ServerConfiguration *config = new ServerConfiguration(mqttConfigMap.value("id").toString(), QHostAddress(mqttConfigMap.value("address").toString()), mqttConfigMap.value("port").toInt(), mqttConfigMap.value("authenticationEnabled").toBool(), mqttConfigMap.value("sslEnabled").toBool()); + m_mqttServerConfigurations->addConfiguration(config); + } + } +} + +void NymeaConfiguration::getAvailableLanguagesResponse(const QVariantMap ¶ms) +{ + qDebug() << "available languages" << params; +} + +void NymeaConfiguration::getTimezonesResponse(const QVariantMap ¶ms) +{ +// qDebug() << "Get timezones response" << params; + m_timezones = params.value("params").toMap().value("timeZones").toStringList(); + emit timezonesChanged(); +} + +void NymeaConfiguration::setTimezoneResponse(const QVariantMap ¶ms) +{ + qDebug() << "Set timezones response" << params; +} + +void NymeaConfiguration::setServerNameResponse(const QVariantMap ¶ms) +{ + qDebug() << "Server name set:" << params; +} + +void NymeaConfiguration::getCloudConfigurationResponse(const QVariantMap ¶ms) +{ + qDebug() << "Cloud config reply" << params; +} + +void NymeaConfiguration::setCloudEnabledResponse(const QVariantMap ¶ms) +{ + qDebug() << "Set cloud enabled:" << params; +} + +void NymeaConfiguration::setDebugServerEnabledResponse(const QVariantMap ¶ms) +{ + qDebug() << "Debug server set:" << params; +} + +void NymeaConfiguration::setTcpConfigReply(const QVariantMap ¶ms) +{ + +} + +void NymeaConfiguration::deleteTcpConfigReply(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().value("configurationError").toString() == "ConfigurationErrorNoError") { + } +} + +void NymeaConfiguration::setWebSocketConfigReply(const QVariantMap ¶ms) +{ + qDebug() << "set weboscket config reply" << params; +} + +void NymeaConfiguration::deleteWebSocketConfigReply(const QVariantMap ¶ms) +{ + +} + +void NymeaConfiguration::setMqttConfigReply(const QVariantMap ¶ms) +{ + qDebug() << "Set mqtt config reply" << params; +} + +void NymeaConfiguration::deleteMqttConfigReply(const QVariantMap ¶ms) +{ + qDebug() << "Delete Mqtt Broker config reply:" << params; +} + +void NymeaConfiguration::notificationReceived(const QVariantMap ¬ification) +{ + QString notif = notification.value("notification").toString(); + if (notif == "Configuration.BasicConfigurationChanged") { + QVariantMap params = notification.value("params").toMap().value("basicConfiguration").toMap(); + qDebug() << "notif" << params; + m_debugServerEnabled = params.value("debugServerEnabled").toBool(); + emit debugServerEnabledChanged(); + m_serverName = params.value("serverName").toString(); + emit serverNameChanged(); + m_language = params.value("language").toString(); + emit languageChanged(); + m_timezone = params.value("timeZone").toString(); + emit timezoneChanged(); + return; + } + if (notif == "Configuration.CloudConfigurationChanged") { + QVariantMap params = notification.value("params").toMap().value("cloudConfiguration").toMap(); + qDebug() << "notif" << params; + m_cloudEnabled = params.value("enabled").toBool(); + emit cloudEnabledChanged(); + return; + } + if (notif.endsWith("ServerConfigurationChanged")) { + ServerConfigurations *configModel = nullptr; + QVariantMap params; + if (notif == "Configuration.TcpServerConfigurationChanged") { + configModel = m_tcpServerConfigurations; + params = notification.value("params").toMap().value("tcpServerConfiguration").toMap(); + } + if (notif == "Configuration.WebSocketServerConfigurationChanged") { + configModel = m_webSocketServerConfigurations; + params = notification.value("params").toMap().value("webSocketServerConfiguration").toMap(); + } + if (notif == "Configuration.MqttServerConfigurationChanged") { + configModel = m_mqttServerConfigurations; + params = notification.value("params").toMap().value("mqttServerConfiguration").toMap(); + } + if (!configModel) { + return; + } + + ServerConfiguration *serverConfig = nullptr; + for (int i = 0; i < configModel->rowCount(); i++) { + ServerConfiguration* config = configModel->get(i); + if (config->id() == params.value("id").toString()) { + serverConfig = config; + } + } + + if (!serverConfig) { + serverConfig = new ServerConfiguration(params.value("id").toString()); + configModel->addConfiguration(serverConfig); + } + serverConfig->setAddress(params.value("address").toString()); + serverConfig->setPort(params.value("port").toInt()); + serverConfig->setAuthenticationEnabled(params.value("authenticationEnabled").toBool()); + serverConfig->setSslEnabled(params.value("sslEnabled").toBool()); + return; + } + if (notif == "Configuration.TcpServerConfigurationRemoved") { + m_tcpServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString()); + return; + } + if (notif == "Configuration.WebSocketServerConfigurationRemoved") { + m_webSocketServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString()); + return; + } + if (notif == "Configuration.MqttServerConfigurationRemoved") { + m_mqttServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString()); + return; + } + + qDebug() << "Unhandled Configuration notification" << notif << notification; +} diff --git a/libnymea-app-core/configuration/basicconfiguration.h b/libnymea-app-core/configuration/nymeaconfiguration.h similarity index 62% rename from libnymea-app-core/configuration/basicconfiguration.h rename to libnymea-app-core/configuration/nymeaconfiguration.h index 6ff63a4d..0760bf4e 100644 --- a/libnymea-app-core/configuration/basicconfiguration.h +++ b/libnymea-app-core/configuration/nymeaconfiguration.h @@ -1,60 +1,73 @@ -#ifndef BASICCONFIGURATION_H -#define BASICCONFIGURATION_H +#ifndef NYMEACONFIGURATION_H +#define NYMEACONFIGURATION_H #include + #include "jsonrpc/jsonhandler.h" -#include "serverconfigurations.h" class JsonRpcClient; +class ServerConfiguration; +class ServerConfigurations; +class MqttBrokerConfiguration; -class BasicConfiguration : public JsonHandler +class NymeaConfiguration : public JsonHandler { Q_OBJECT - Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged) + Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged) + Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged) - Q_PROPERTY(QString timezone READ timezone WRITE setTimezone NOTIFY timezoneChanged) - - Q_PROPERTY(bool cloudEnabled READ cloudEnabled WRITE setCloudEnabled NOTIFY cloudEnabledChanged) - Q_PROPERTY(QStringList availableLanguages READ availableLanguages NOTIFY availableLanguagesChanged) + + Q_PROPERTY(QString timezone READ timezone WRITE setTimezone NOTIFY timezoneChanged) Q_PROPERTY(QStringList timezones READ timezones NOTIFY timezonesChanged) + Q_PROPERTY(bool cloudEnabled READ cloudEnabled WRITE setCloudEnabled NOTIFY cloudEnabledChanged) + Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged) + Q_PROPERTY(ServerConfigurations* tcpServerConfigurations READ tcpServerConfigurations CONSTANT) - Q_PROPERTY(ServerConfigurations* websocketServerConfigurations READ websocketServerConfigurations CONSTANT) + Q_PROPERTY(ServerConfigurations* webSocketServerConfigurations READ webSocketServerConfigurations CONSTANT) + Q_PROPERTY(ServerConfigurations* mqttServerConfigurations READ mqttServerConfigurations CONSTANT) + + Q_PROPERTY(MqttBrokerConfiguration* mqttBrokerConfiguration READ mqttBrokerConfiguration CONSTANT) public: - explicit BasicConfiguration(JsonRpcClient* client, QObject *parent = nullptr); + explicit NymeaConfiguration(JsonRpcClient* client, QObject *parent = nullptr); QString nameSpace() const override; - bool debugServerEnabled() const; - void setDebugServerEnabled(bool debugServerEnabled); - QString serverName() const; void setServerName(const QString &serverName); - bool cloudEnabled() const; - void setCloudEnabled(bool cloudEnabled); - QString language() const; void setLanguage(const QString &language); - QStringList availableLanguages() const; QString timezone() const; void setTimezone(const QString &timezone); - QStringList timezones() const; - ServerConfigurations *tcpServerConfigurations() const; - ServerConfigurations *websocketServerConfigurations() const; + bool debugServerEnabled() const; + void setDebugServerEnabled(bool debugServerEnabled); - void setTcpServerConfiguration(ServerConfiguration *configuration) const; - void setWebsocketServerConfiguration(ServerConfiguration *configuration) const; + bool cloudEnabled() const; + void setCloudEnabled(bool cloudEnabled); + + ServerConfigurations *tcpServerConfigurations() const; + ServerConfigurations *webSocketServerConfigurations() const; + ServerConfigurations *mqttServerConfigurations() const; + + MqttBrokerConfiguration *mqttBrokerConfiguration() const; + + Q_INVOKABLE ServerConfiguration* createServerConfiguration(const QString &address = "0.0.0.0", int port = 0, bool authEnabled = false, bool sslEnabled = false); + + Q_INVOKABLE void setTcpServerConfiguration(ServerConfiguration *configuration); + Q_INVOKABLE void setWebSocketServerConfiguration(ServerConfiguration *configuration); + Q_INVOKABLE void setMqttServerConfiguration(ServerConfiguration *configuration); Q_INVOKABLE void deleteTcpServerConfiguration(const QString &id); - Q_INVOKABLE void deleteWebsocketServerConfiguration(const QString &id); + Q_INVOKABLE void deleteWebSocketServerConfiguration(const QString &id); + Q_INVOKABLE void deleteMqttServerConfiguration(const QString &id); void init(); @@ -67,8 +80,12 @@ private: Q_INVOKABLE void getAvailableLanguagesResponse(const QVariantMap ¶ms); Q_INVOKABLE void getTimezonesResponse(const QVariantMap ¶ms); Q_INVOKABLE void setTimezoneResponse(const QVariantMap ¶ms); + Q_INVOKABLE void setTcpConfigReply(const QVariantMap ¶ms); Q_INVOKABLE void deleteTcpConfigReply(const QVariantMap ¶ms); + Q_INVOKABLE void setWebSocketConfigReply(const QVariantMap ¶ms); Q_INVOKABLE void deleteWebSocketConfigReply(const QVariantMap ¶ms); + Q_INVOKABLE void setMqttConfigReply(const QVariantMap ¶ms); + Q_INVOKABLE void deleteMqttConfigReply(const QVariantMap ¶ms); Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); @@ -83,6 +100,7 @@ signals: private: JsonRpcClient* m_client = nullptr; + bool m_debugServerEnabled = false; QString m_serverName; QString m_language; @@ -92,7 +110,10 @@ private: bool m_cloudEnabled = false; ServerConfigurations *m_tcpServerConfigurations = nullptr; - ServerConfigurations *m_websocketServerConfigurations = nullptr; + ServerConfigurations *m_webSocketServerConfigurations = nullptr; + ServerConfigurations *m_mqttServerConfigurations = nullptr; + + MqttBrokerConfiguration *m_mqttBrokerConfiguration = nullptr; }; -#endif // BASICCONFIGURATION_H +#endif // NYMEACONFIGURATION_H diff --git a/libnymea-app-core/configuration/serverconfiguration.cpp b/libnymea-app-core/configuration/serverconfiguration.cpp index 1c30454c..030731b0 100644 --- a/libnymea-app-core/configuration/serverconfiguration.cpp +++ b/libnymea-app-core/configuration/serverconfiguration.cpp @@ -21,17 +21,55 @@ QString ServerConfiguration::address() const return m_hostAddress.toString(); } +void ServerConfiguration::setAddress(const QString &address) +{ + if (m_hostAddress != QHostAddress(address)) { + m_hostAddress = QHostAddress(address); + emit addressChanged(); + } +} + int ServerConfiguration::port() const { return m_port; } +void ServerConfiguration::setPort(int port) +{ + if (m_port != port) { + m_port = port; + emit portChanged(); + } +} + bool ServerConfiguration::authenticationEnabled() const { return m_authEnabled; } +void ServerConfiguration::setAuthenticationEnabled(bool authenticationEnabled) +{ + if (m_authEnabled != authenticationEnabled) { + m_authEnabled = authenticationEnabled; + emit authenticationEnabledChanged(); + } +} + bool ServerConfiguration::sslEnabled() const { return m_sslEnabled; } + +void ServerConfiguration::setSslEnabled(bool sslEnabled) +{ + if (m_sslEnabled != sslEnabled) { + m_sslEnabled = sslEnabled; + emit sslEnabledChanged(); + } +} + +ServerConfiguration *ServerConfiguration::clone() const +{ + ServerConfiguration *ret = new ServerConfiguration(m_id, m_hostAddress, m_port, m_authEnabled, m_sslEnabled); + return ret; +} diff --git a/libnymea-app-core/configuration/serverconfiguration.h b/libnymea-app-core/configuration/serverconfiguration.h index 2f0c1d0f..2d067928 100644 --- a/libnymea-app-core/configuration/serverconfiguration.h +++ b/libnymea-app-core/configuration/serverconfiguration.h @@ -9,18 +9,35 @@ class ServerConfiguration : public QObject { Q_OBJECT Q_PROPERTY(QString id READ id CONSTANT) - Q_PROPERTY(QString address READ address CONSTANT) - Q_PROPERTY(int port READ port CONSTANT) - Q_PROPERTY(bool authenticationEnabled READ authenticationEnabled CONSTANT) - Q_PROPERTY(bool sslEnabled READ sslEnabled CONSTANT) + Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged) + Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged) + Q_PROPERTY(bool authenticationEnabled READ authenticationEnabled WRITE setAuthenticationEnabled NOTIFY authenticationEnabledChanged) + Q_PROPERTY(bool sslEnabled READ sslEnabled WRITE setSslEnabled NOTIFY sslEnabledChanged) + public: - explicit ServerConfiguration(const QString &id, const QHostAddress &address, int port, bool authEnabled, bool sslEnabled, QObject *parent = nullptr); + explicit ServerConfiguration(const QString &id, const QHostAddress &address = QHostAddress(), int port = 0, bool authEnabled = false, bool sslEnabled = false, QObject *parent = nullptr); QString id() const; + QString address() const; + void setAddress(const QString &address); + int port() const; + void setPort(int port); + bool authenticationEnabled() const; + void setAuthenticationEnabled(bool authenticationEnabled); + bool sslEnabled() const; + void setSslEnabled(bool sslEnabled); + + Q_INVOKABLE ServerConfiguration* clone() const; + +signals: + void addressChanged(); + void portChanged(); + void authenticationEnabledChanged(); + void sslEnabledChanged(); private: QString m_id; diff --git a/libnymea-app-core/configuration/serverconfigurations.cpp b/libnymea-app-core/configuration/serverconfigurations.cpp index 40bf13d7..e2a2459d 100644 --- a/libnymea-app-core/configuration/serverconfigurations.cpp +++ b/libnymea-app-core/configuration/serverconfigurations.cpp @@ -45,10 +45,40 @@ void ServerConfigurations::addConfiguration(ServerConfiguration *configuration) configuration->setParent(this); beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); m_list.append(configuration); + + connect(configuration, &ServerConfiguration::addressChanged, this, [this, configuration]() { + QModelIndex idx = index(m_list.indexOf(configuration), 0); + emit dataChanged(idx, idx, {RoleAddress}); + }); + connect(configuration, &ServerConfiguration::portChanged, this, [this, configuration]() { + QModelIndex idx = index(m_list.indexOf(configuration), 0); + emit dataChanged(idx, idx, {RolePort}); + }); + connect(configuration, &ServerConfiguration::authenticationEnabledChanged, this, [this, configuration]() { + QModelIndex idx = index(m_list.indexOf(configuration), 0); + emit dataChanged(idx, idx, {RoleAuthenticationEnabled}); + }); + connect(configuration, &ServerConfiguration::sslEnabledChanged, this, [this, configuration]() { + QModelIndex idx = index(m_list.indexOf(configuration), 0); + emit dataChanged(idx, idx, {RoleSslEnabled}); + }); + endInsertRows(); emit countChanged(); } +void ServerConfigurations::removeConfiguration(const QString &id) +{ + for (int i = 0; i < m_list.count(); i++) { + if (m_list.at(i)->id() == id) { + beginRemoveRows(QModelIndex(), i, i); + m_list.takeAt(i)->deleteLater(); + endRemoveRows(); + return; + } + } +} + void ServerConfigurations::clear() { beginResetModel(); @@ -57,3 +87,11 @@ void ServerConfigurations::clear() endResetModel(); emit countChanged(); } + +ServerConfiguration *ServerConfigurations::get(int index) const +{ + if (index < 0 || index > m_list.count() - 1) { + return nullptr; + } + return m_list.at(index); +} diff --git a/libnymea-app-core/configuration/serverconfigurations.h b/libnymea-app-core/configuration/serverconfigurations.h index 8695d52b..c099ebd1 100644 --- a/libnymea-app-core/configuration/serverconfigurations.h +++ b/libnymea-app-core/configuration/serverconfigurations.h @@ -28,9 +28,12 @@ public: QHash roleNames() const override; void addConfiguration(ServerConfiguration *configuration); + void removeConfiguration(const QString &id); void clear(); + Q_INVOKABLE ServerConfiguration* get(int index) const; + signals: void countChanged(); diff --git a/libnymea-app-core/engine.cpp b/libnymea-app-core/engine.cpp index 44e19233..3f511097 100644 --- a/libnymea-app-core/engine.cpp +++ b/libnymea-app-core/engine.cpp @@ -23,7 +23,7 @@ #include "rulemanager.h" #include "logmanager.h" #include "tagsmanager.h" -#include "configuration/basicconfiguration.h" +#include "configuration/nymeaconfiguration.h" #include "connection/awsclient.h" #include "connection/tcpsockettransport.h" @@ -39,7 +39,7 @@ Engine::Engine(QObject *parent) : m_ruleManager(new RuleManager(m_jsonRpcClient, this)), m_logManager(new LogManager(m_jsonRpcClient, this)), m_tagsManager(new TagsManager(m_jsonRpcClient, this)), - m_basicConfiguration(new BasicConfiguration(m_jsonRpcClient, this)) + m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)) { m_connection->registerTransport(new TcpSocketTransportFactory()); m_connection->registerTransport(new WebsocketTransportFactory()); @@ -92,16 +92,11 @@ LogManager *Engine::logManager() const return m_logManager; } -BasicConfiguration *Engine::basicConfiguration() const +NymeaConfiguration *Engine::nymeaConfiguration() const { - return m_basicConfiguration; + return m_nymeaConfiguration; } -//AWSClient *Engine::awsClient() const -//{ -// return m_aws; -//} - void Engine::deployCertificate() { if (!m_jsonRpcClient->connected()) { @@ -133,7 +128,7 @@ void Engine::onConnectedChanged() if (!m_jsonRpcClient->initialSetupRequired() && !m_jsonRpcClient->authenticationRequired()) { m_deviceManager->init(); m_ruleManager->init(); - m_basicConfiguration->init(); + m_nymeaConfiguration->init(); } } } diff --git a/libnymea-app-core/engine.h b/libnymea-app-core/engine.h index 9f90a4a8..7d41310e 100644 --- a/libnymea-app-core/engine.h +++ b/libnymea-app-core/engine.h @@ -31,7 +31,7 @@ class RuleManager; class LogManager; class TagsManager; -class BasicConfiguration; +class NymeaConfiguration; class AWSClient; class Engine : public QObject @@ -42,8 +42,7 @@ class Engine : public QObject Q_PROPERTY(RuleManager* ruleManager READ ruleManager CONSTANT) Q_PROPERTY(TagsManager* tagsManager READ tagsManager CONSTANT) Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT) - Q_PROPERTY(BasicConfiguration* basicConfiguration READ basicConfiguration CONSTANT) -// Q_PROPERTY(AWSClient* awsClient READ awsClient CONSTANT) + Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT) public: explicit Engine(QObject *parent = nullptr); @@ -57,8 +56,7 @@ public: TagsManager *tagsManager() const; JsonRpcClient *jsonRpcClient() const; LogManager *logManager() const; - BasicConfiguration *basicConfiguration() const; -// AWSClient* awsClient() const; + NymeaConfiguration *nymeaConfiguration() const; Q_INVOKABLE void deployCertificate(); @@ -69,8 +67,7 @@ private: RuleManager *m_ruleManager; LogManager *m_logManager; TagsManager *m_tagsManager; - BasicConfiguration *m_basicConfiguration; -// AWSClient *m_aws; + NymeaConfiguration *m_nymeaConfiguration; private slots: void onConnectedChanged(); diff --git a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp index 69656d5d..7478668e 100644 --- a/libnymea-app-core/jsonrpc/jsonrpcclient.cpp +++ b/libnymea-app-core/jsonrpc/jsonrpcclient.cpp @@ -356,7 +356,6 @@ void JsonRpcClient::dataReceived(const QByteArray &data) m_pushButtonAuthAvailable = dataMap.value("pushButtonAuthAvailable").toBool(); emit pushButtonAuthAvailableChanged(); - qDebug() << "Handshake received" << "initRequired:" << m_initialSetupRequired << "authRequired:" << m_authenticationRequired << "pushButtonAvailable:" << m_pushButtonAuthAvailable;; m_serverUuid = dataMap.value("uuid").toString(); m_serverVersion = dataMap.value("version").toString(); @@ -366,6 +365,8 @@ void JsonRpcClient::dataReceived(const QByteArray &data) } m_jsonRpcVersion = QVersionNumber::fromString(protoVersionString); + qDebug() << "Handshake reply:" << "Protocol version:" << protoVersionString << "InitRequired:" << m_initialSetupRequired << "AuthRequired:" << m_authenticationRequired << "PushButtonAvailable:" << m_pushButtonAuthAvailable;; + QVersionNumber minimumRequiredVersion = QVersionNumber(1, 0); if (m_jsonRpcVersion < minimumRequiredVersion) { qWarning() << "Nymea box doesn't support minimum required version. Required:" << minimumRequiredVersion << "Found:" << m_jsonRpcVersion; diff --git a/libnymea-app-core/libnymea-app-core.h b/libnymea-app-core/libnymea-app-core.h index 650259ce..2b1efae7 100644 --- a/libnymea-app-core/libnymea-app-core.h +++ b/libnymea-app-core/libnymea-app-core.h @@ -35,7 +35,10 @@ #include "models/logsmodelng.h" #include "models/valuelogsproxymodel.h" #include "models/interfacesproxy.h" -#include "configuration/basicconfiguration.h" +#include "configuration/nymeaconfiguration.h" +#include "configuration/serverconfiguration.h" +#include "configuration/serverconfigurations.h" +#include "configuration/mqttbrokerconfiguration.h" #include "wifisetup/networkmanagercontroller.h" #include "wifisetup/wirelessaccesspoint.h" #include "wifisetup/wirelessaccesspoints.h" @@ -143,14 +146,16 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager."); qmlRegisterType(uri, 1, 0, "PluginsProxy"); - qmlRegisterUncreatableType(uri, 1, 0, "BasicConfiguration", "Uncreatable"); + qmlRegisterUncreatableType(uri, 1, 0, "NymeaConfiguration", "Get it from Engine"); + qmlRegisterUncreatableType(uri, 1, 0, "ServerConfiguration", "Get it from NymeaConfiguration"); + qmlRegisterUncreatableType(uri, 1, 0, "ServerConfigurations", "Get it from NymeaConfiguration"); + qmlRegisterUncreatableType(uri, 1, 0, "MqttBrokerConfiguration", "Get it from NymeaConfiguration"); qmlRegisterType(uri, 1, 0, "NymeaDiscovery"); qmlRegisterUncreatableType(uri, 1, 0, "DiscoveryModel", "Get it from NymeaDiscovery"); qmlRegisterUncreatableType(uri, 1, 0, "DiscoveryDevice", "Get it from DiscoveryModel"); qmlRegisterUncreatableType(uri, 1, 0, "Connection", "Get it from DiscoveryDevice"); - qmlRegisterType(uri, 1, 0, "LogsModel"); qmlRegisterType(uri, 1, 0, "LogsModelNg"); qmlRegisterType(uri, 1, 0, "ValueLogsProxyModel"); diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro index 514e2cce..8f6aebd4 100644 --- a/libnymea-app-core/libnymea-app-core.pro +++ b/libnymea-app-core/libnymea-app-core.pro @@ -55,7 +55,6 @@ SOURCES += \ models/valuelogsproxymodel.cpp \ discovery/nymeadiscovery.cpp \ logmanager.cpp \ - configuration/basicconfiguration.cpp \ wifisetup/bluetoothdevice.cpp \ wifisetup/bluetoothdeviceinfo.cpp \ wifisetup/bluetoothdeviceinfos.cpp \ @@ -80,7 +79,9 @@ SOURCES += \ connection/sigv4utils.cpp \ ruletemplates/ruleactionparamtemplate.cpp \ configuration/serverconfiguration.cpp \ - configuration/serverconfigurations.cpp + configuration/serverconfigurations.cpp \ + configuration/mqttbrokerconfiguration.cpp \ + configuration/nymeaconfiguration.cpp HEADERS += \ engine.h \ @@ -115,7 +116,6 @@ HEADERS += \ models/valuelogsproxymodel.h \ discovery/nymeadiscovery.h \ logmanager.h \ - configuration/basicconfiguration.h \ wifisetup/bluetoothdevice.h \ wifisetup/bluetoothdeviceinfo.h \ wifisetup/bluetoothdeviceinfos.h \ @@ -140,7 +140,9 @@ HEADERS += \ connection/cloudtransport.h \ ruletemplates/ruleactionparamtemplate.h \ configuration/serverconfiguration.h \ - configuration/serverconfigurations.h + configuration/serverconfigurations.h \ + configuration/mqttbrokerconfiguration.h \ + configuration/nymeaconfiguration.h unix { target.path = /usr/lib diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc index 7c5b0ec3..92a8f823 100644 --- a/nymea-app/images.qrc +++ b/nymea-app/images.qrc @@ -157,5 +157,7 @@ ui/images/lighting/concentrate.svg ui/images/lighting/reading.svg ui/images/lighting/relax.svg + ui/images/messaging-app-symbolic.svg + ui/images/mqtt.svg diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index e3ef4ff8..bd781020 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -136,5 +136,7 @@ ui/customviews/GenericTypeGraph.qml ui/devicepages/SmartMeterDevicePage.qml ui/devicelistpages/SmartMeterDeviceListPage.qml + ui/system/MqttBrokerSettingsPage.qml + ui/system/ServerConfigurationDialog.qml diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 2ef02af4..5a948bfe 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -158,7 +158,7 @@ ApplicationWindow { case "gateway": return Qt.resolvedUrl("images/network-wired-symbolic.svg") case "notifications": - return Qt.resolvedUrl("images/notification.svg") + return Qt.resolvedUrl("images/messaging-app-symbolic.svg") case "inputtrigger": return Qt.resolvedUrl("images/attention.svg") case "outputtrigger": diff --git a/nymea-app/ui/RootItem.qml b/nymea-app/ui/RootItem.qml index 0ef4a56f..f7b8b3f0 100644 --- a/nymea-app/ui/RootItem.qml +++ b/nymea-app/ui/RootItem.qml @@ -276,7 +276,7 @@ Item { delegate: TabButton { id: hostTabButton property var engine: mainRepeater.itemAt(index)._engine - property string serverName: engine.basicConfiguration.serverName + property string serverName: engine.nymeaConfiguration.serverName Material.elevation: index contentItem: RowLayout { diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 1df641fa..df24ac24 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -62,12 +62,12 @@ Page { TextField { id: nameTextField Layout.fillWidth: true - text: engine.basicConfiguration.serverName + text: engine.nymeaConfiguration.serverName } Button { text: qsTr("OK") - visible: nameTextField.displayText !== engine.basicConfiguration.serverName - onClicked: engine.basicConfiguration.serverName = nameTextField.displayText + visible: nameTextField.displayText !== engine.nymeaConfiguration.serverName + onClicked: engine.nymeaConfiguration.serverName = nameTextField.displayText } } @@ -81,10 +81,10 @@ Page { text: qsTr("Language") } ComboBox { - model: engine.basicConfiguration.availableLanguages - currentIndex: model.indexOf(engine.basicConfiguration.language) + model: engine.nymeaConfiguration.availableLanguages + currentIndex: model.indexOf(engine.nymeaConfiguration.language) onActivated: { - engine.basicConfiguration.language = currentText; + engine.nymeaConfiguration.language = currentText; } } } @@ -100,10 +100,10 @@ Page { } ComboBox { Layout.minimumWidth: 200 - model: engine.basicConfiguration.timezones - currentIndex: model.indexOf(engine.basicConfiguration.timezone) + model: engine.nymeaConfiguration.timezones + currentIndex: model.indexOf(engine.nymeaConfiguration.timezone) onActivated: { - engine.basicConfiguration.timezone = currentText; + engine.nymeaConfiguration.timezone = currentText; } } } @@ -122,8 +122,8 @@ Page { } Switch { id: debugServerEnabledSwitch - checked: engine.basicConfiguration.debugServerEnabled - onClicked: engine.basicConfiguration.debugServerEnabled = checked + checked: engine.nymeaConfiguration.debugServerEnabled + onClicked: engine.nymeaConfiguration.debugServerEnabled = checked } } @@ -138,6 +138,12 @@ Page { } + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/logs.svg" + text: qsTr("Log viewer") + onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) + } MeaListItemDelegate { Layout.fillWidth: true iconName: "../images/cloud.svg" @@ -145,24 +151,25 @@ Page { visible: engine.jsonRpcClient.ensureServerVersion("1.9") onClicked: pageStack.push(Qt.resolvedUrl("system/CloudSettingsPage.qml")) } - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/plugin.svg" - text: qsTr("Plugins") - onClicked:pageStack.push(Qt.resolvedUrl("system/PluginsPage.qml")) - } - MeaListItemDelegate { - Layout.fillWidth: true - iconName: "../images/logs.svg" - text: qsTr("Log viewer") - onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) - } MeaListItemDelegate { Layout.fillWidth: true iconName: "../images/network-vpn.svg" text: qsTr("Server interfaces") onClicked: pageStack.push(Qt.resolvedUrl("system/ConnectionInterfacesPage.qml")) } + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/mqtt.svg" + text: qsTr("MQTT broker") + visible: engine.jsonRpcClient.ensureServerVersion("1.11") + onClicked: pageStack.push(Qt.resolvedUrl("system/MqttBrokerSettingsPage.qml")) + } + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/plugin.svg" + text: qsTr("Plugins") + onClicked:pageStack.push(Qt.resolvedUrl("system/PluginsPage.qml")) + } MeaListItemDelegate { Layout.fillWidth: true iconName: "../images/info.svg" diff --git a/nymea-app/ui/components/MeaListItemDelegate.qml b/nymea-app/ui/components/MeaListItemDelegate.qml index a243ab2d..e93839a1 100644 --- a/nymea-app/ui/components/MeaListItemDelegate.qml +++ b/nymea-app/ui/components/MeaListItemDelegate.qml @@ -5,6 +5,7 @@ import QtQuick.Controls.Material 2.2 SwipeDelegate { id: root + implicitWidth: 200 property string subText property bool progressive: true diff --git a/nymea-app/ui/images/messaging-app-symbolic.svg b/nymea-app/ui/images/messaging-app-symbolic.svg new file mode 100644 index 00000000..7f6d4219 --- /dev/null +++ b/nymea-app/ui/images/messaging-app-symbolic.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/mqtt.svg b/nymea-app/ui/images/mqtt.svg new file mode 100644 index 00000000..29419932 --- /dev/null +++ b/nymea-app/ui/images/mqtt.svg @@ -0,0 +1,72 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + MQTT + + + + + diff --git a/nymea-app/ui/system/CloudSettingsPage.qml b/nymea-app/ui/system/CloudSettingsPage.qml index cb5c74d3..04ee5808 100644 --- a/nymea-app/ui/system/CloudSettingsPage.qml +++ b/nymea-app/ui/system/CloudSettingsPage.qml @@ -49,9 +49,9 @@ Page { SwitchDelegate { Layout.fillWidth: true text: qsTr("Cloud connection enabled") - checked: engine.basicConfiguration.cloudEnabled + checked: engine.nymeaConfiguration.cloudEnabled onToggled: { - engine.basicConfiguration.cloudEnabled = checked; + engine.nymeaConfiguration.cloudEnabled = checked; } } diff --git a/nymea-app/ui/system/ConnectionInterfaceDelegate.qml b/nymea-app/ui/system/ConnectionInterfaceDelegate.qml index f28102f7..8f970feb 100644 --- a/nymea-app/ui/system/ConnectionInterfaceDelegate.qml +++ b/nymea-app/ui/system/ConnectionInterfaceDelegate.qml @@ -5,9 +5,9 @@ import Nymea 1.0 import "../components" MeaListItemDelegate { - text: model.address - subText: model.port - iconName: "../images/network-wifi-symbolic.svg" + text: qsTr("Interface: %1").arg(model.address === "0.0.0.0" ? qsTr("Any") : model.address === "127.0.0.1" ? qsTr("localhost") : model.address) + subText: qsTr("Port: %1").arg(model.port) + iconName: "../images/network-vpn.svg" progressive: false iconColor: { if ((engine.connection.hostAddress === model.address || model.address === "0.0.0.0") diff --git a/nymea-app/ui/system/ConnectionInterfacesPage.qml b/nymea-app/ui/system/ConnectionInterfacesPage.qml index 2fed94b1..ee7e0232 100644 --- a/nymea-app/ui/system/ConnectionInterfacesPage.qml +++ b/nymea-app/ui/system/ConnectionInterfacesPage.qml @@ -27,18 +27,52 @@ Page { Layout.topMargin: app.margins text: qsTr("TCP Server Interfaces") wrapMode: Text.WordWrap + color: app.accentColor } Repeater { - model: engine.basicConfiguration.tcpServerConfigurations + model: engine.nymeaConfiguration.tcpServerConfigurations delegate: ConnectionInterfaceDelegate { Layout.fillWidth: true + canDelete: true + onClicked: { + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: engine.nymeaConfiguration.tcpServerConfigurations.get(index).clone() }); + popup.accepted.connect(function() { + engine.nymeaConfiguration.setTcpServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } onDeleteClicked: { print("should delete") - engine.basicConfiguration.deleteTcpServerConfiguration(model.id) + engine.nymeaConfiguration.deleteTcpServerConfiguration(model.id) } } } + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Add") + onClicked: { + var config = engine.nymeaConfiguration.createServerConfiguration("0.0.0.0", 2222 + engine.nymeaConfiguration.tcpServerConfigurations.count, false, false); + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: config }); + popup.accepted.connect(function() { + engine.nymeaConfiguration.setTcpServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } + } + + ThinDivider {} Label { Layout.fillWidth: true Layout.leftMargin: app.margins @@ -46,18 +80,51 @@ Page { Layout.topMargin: app.margins text: qsTr("WebSocket Server Interfaces") wrapMode: Text.WordWrap + color: app.accentColor } Repeater { - model: engine.basicConfiguration.websocketServerConfigurations + model: engine.nymeaConfiguration.webSocketServerConfigurations delegate: ConnectionInterfaceDelegate { Layout.fillWidth: true + canDelete: true + onClicked: { + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: engine.nymeaConfiguration.webSocketServerConfigurations.get(index).clone() }); + popup.accepted.connect(function() { + print("configuring:", popup.serverConfiguration.port) + engine.nymeaConfiguration.setWebSocketServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } onDeleteClicked: { print("should delete", model.id) - engine.basicConfiguration.deleteWebsocketServerConfiguration(model.id) + engine.nymeaConfiguration.deleteWebSocketServerConfiguration(model.id) } } } + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Add") + onClicked: { + var config = engine.nymeaConfiguration.createServerConfiguration("0.0.0.0", 4444 + engine.nymeaConfiguration.webSocketServerConfigurations.count, false, false); + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: config }); + popup.accepted.connect(function() { + engine.nymeaConfiguration.setWebSocketServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } + } } } } diff --git a/nymea-app/ui/system/MqttBrokerSettingsPage.qml b/nymea-app/ui/system/MqttBrokerSettingsPage.qml new file mode 100644 index 00000000..87fe3e49 --- /dev/null +++ b/nymea-app/ui/system/MqttBrokerSettingsPage.qml @@ -0,0 +1,81 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 +import "../components" + +Page { + id: root + header: GuhHeader { + text: qsTr("MQTT broker") + onBackPressed: pageStack.pop(); + } + + Flickable { + anchors.fill: parent + contentHeight: connectionsColumn.implicitHeight + interactive: contentHeight > height + + ColumnLayout { + id: connectionsColumn + anchors { left: parent.left; top: parent.top; right: parent.right } + Label { + Layout.fillWidth: true + text: qsTr("Server password protection") + } + + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + text: qsTr("MQTT Server Interfaces") + wrapMode: Text.WordWrap + color: app.accentColor + } + + Repeater { + model: engine.nymeaConfiguration.mqttServerConfigurations + delegate: ConnectionInterfaceDelegate { + Layout.fillWidth: true + canDelete: true + onClicked: { + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: engine.nymeaConfiguration.mqttServerConfigurations.get(index).clone() }); + popup.accepted.connect(function() { + engine.nymeaConfiguration.setMqttServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } + + onDeleteClicked: { + print("should delete") + engine.nymeaConfiguration.deleteMqttServerConfiguration(model.id) + } + } + } + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Add") + onClicked: { + var config = engine.nymeaConfiguration.createServerConfiguration("0.0.0.0", 1883 + engine.nymeaConfiguration.mqttServerConfigurations.count, false, false); + var component = Qt.createComponent(Qt.resolvedUrl("ServerConfigurationDialog.qml")); + var popup = component.createObject(root, { serverConfiguration: config }); + popup.accepted.connect(function() { + engine.nymeaConfiguration.setMqttServerConfiguration(popup.serverConfiguration) + popup.serverConfiguration.destroy(); + }) + popup.rejected.connect(function() { + popup.serverConfiguration.destroy(); + }) + popup.open() + } + } + } + } +} diff --git a/nymea-app/ui/system/ServerConfigurationDialog.qml b/nymea-app/ui/system/ServerConfigurationDialog.qml new file mode 100644 index 00000000..b3837944 --- /dev/null +++ b/nymea-app/ui/system/ServerConfigurationDialog.qml @@ -0,0 +1,95 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.1 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.1 +import Nymea 1.0 + +Dialog { + id: root + title: qsTr("Server configuration") + width: parent.width * .8 + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + property ServerConfiguration serverConfiguration: null + standardButtons: Dialog.Ok | Dialog.Cancel + + ColumnLayout { + anchors { left: parent.left; top: parent.top; right: parent.right } + RowLayout { + Label { + text: qsTr("Interface") + Layout.fillWidth: true + } + ComboBox { + id: interfaceCombobox + model: [qsTr("Any"), qsTr("Localhost"), qsTr("Custom")] + Layout.fillWidth: true + currentIndex: !root.serverConfiguration + ? 0 : root.serverConfiguration.address === "0.0.0.0" + ? 0 + : root.serverConfiguration.address === "127.0.0.1" + ? 1 : 2 + onActivated: { + switch (index) { + case 0: + root.serverConfiguration.address = "0.0.0.0"; + break; + case 1: + root.serverConfiguration.address = "127.0.0.1"; + break; + } + } + } + } + RowLayout { + visible: interfaceCombobox.currentIndex === 2 + Label { + text: qsTr("Address:") + Layout.fillWidth: true + } + TextField { + id: addressTextField + Layout.fillWidth: true + inputMethodHints: Qt.ImhPreferNumbers + inputMask: "000.000.000.000" + text: root.serverConfiguration ? root.serverConfiguration.address : "" + onEditingFinished: root.serverConfiguration.address = text + } + } + + RowLayout { + Label { + text: qsTr("Port:") + Layout.fillWidth: true + } + TextField { + inputMethodHints: Qt.ImhDigitsOnly + text: root.serverConfiguration ? root.serverConfiguration.port : 0 + validator: IntValidator { bottom: 0; top: 65535 } + onEditingFinished: root.serverConfiguration.port = text + } + } + + RowLayout { + Label { + Layout.fillWidth: true + text: qsTr("SSL enabled") + } + CheckBox { + checkState: root.serverConfiguration && root.serverConfiguration.sslEnabled ? Qt.Checked : Qt.Unchecked + onClicked: root.serverConfiguration.sslEnabled = checked + } + } + RowLayout { + Label { + Layout.fillWidth: true + text: qsTr("Login required") + } + CheckBox { + checkState: root.serverConfiguration && root.serverConfiguration.authenticationEnabled ? Qt.Checked : Qt.Unchecked + onClicked: root.serverConfiguration.authenticationEnabled = checked + } + } + } +}