diff --git a/libnymea-app-core/configuration/networkmanager.cpp b/libnymea-app-core/configuration/networkmanager.cpp new file mode 100644 index 00000000..4bbd4b72 --- /dev/null +++ b/libnymea-app-core/configuration/networkmanager.cpp @@ -0,0 +1,236 @@ +#include "networkmanager.h" +#include "types/networkdevices.h" +#include "types/networkdevice.h" +#include "types/wirelessaccesspoint.h" +#include "types/wirelessaccesspoints.h" + +#include "jsonrpc/jsonrpcclient.h" + +#include +#include + +NetworkManager::NetworkManager(JsonRpcClient *jsonClient, QObject *parent): + JsonHandler(parent), + m_jsonClient(jsonClient), + m_wiredNetworkDevices(new WiredNetworkDevices(this)), + m_wirelessNetworkDevices(new WirelessNetworkDevices(this)) +{ + m_jsonClient->registerNotificationHandler(this, "notificationReceived"); +} + +QString NetworkManager::nameSpace() const +{ + return "NetworkManager"; +} + +void NetworkManager::init() +{ + m_jsonClient->sendCommand("NetworkManager.GetNetworkStatus", QVariantMap(), this, "getStatusReply"); + m_jsonClient->sendCommand("NetworkManager.GetNetworkDevices", QVariantMap(), this, "getDevicesReply"); + m_jsonClient->sendCommand("NetworkManager.GetWirelessAccessPoints", QVariantMap(), this, "getAccessPointsReply"); +} + +NetworkManager::NetworkManagerState NetworkManager::state() const +{ + return m_state; +} + +bool NetworkManager::networkingEnabled() const +{ + return m_networkingEnabled; +} + +bool NetworkManager::wirelessNetworkingEnabled() const +{ + return m_wirelessNetworkingEnabled; +} + +WiredNetworkDevices *NetworkManager::wiredNetworkDevices() const +{ + return m_wiredNetworkDevices; +} + +WirelessNetworkDevices *NetworkManager::wirelessNetworkDevices() const +{ + return m_wirelessNetworkDevices; +} + +void NetworkManager::enableNetworking(bool enable) +{ + QVariantMap params; + params.insert("enable", enable); + m_jsonClient->sendCommand("NetworkManager.EnableNetworking", params, this, "enableNetworkingReply"); +} + +void NetworkManager::enableWirelessNetworking(bool enable) +{ + QVariantMap params; + params.insert("enable", enable); + m_jsonClient->sendCommand("NetworkManager.EnableWirelessNetworking", params, this, "enableNetworkingReply"); +} + +void NetworkManager::refreshWifis(const QString &interface) +{ + QVariantMap params; + params.insert("interface", interface); + int requestId = m_jsonClient->sendCommand("NetworkManager.GetWirelessAccessPoints", params, this, "getAccessPointsReply"); + m_apRequests.insert(requestId, interface); +} + +void NetworkManager::connectToWiFi(const QString &interface, const QString &ssid, const QString &passphrase) +{ + QVariantMap params; + params.insert("interface", interface); + params.insert("ssid", ssid); + params.insert("password", passphrase); + m_jsonClient->sendCommand("NetworkManager.ConnectWifiNetwork", params, this, "connectToWiFiReply"); +} + +void NetworkManager::disconnectInterface(const QString &interface) +{ + QVariantMap params; + params.insert("interface", interface); + m_jsonClient->sendCommand("NetworkManager.DisconnectInterface", params, this, "disconnectReply"); +} + +void NetworkManager::getStatusReply(const QVariantMap ¶ms) +{ + qDebug() << "NetworkManager reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); + + QVariantMap statusMap = params.value("params").toMap().value("status").toMap(); + + QMetaEnum stateEnum = QMetaEnum::fromType(); + NetworkManagerState state = static_cast(stateEnum.keyToValue(params.value("params").toMap().value("status").toMap().value("state").toString().toUtf8())); + if (m_state != state) { + m_state = state; + emit stateChanged(); + } + + bool networkingEnabled = statusMap.value("networkingEnabled").toBool(); + if (m_networkingEnabled != networkingEnabled) { + m_networkingEnabled = networkingEnabled; + emit networkingEnabledChanged(); + } + bool wirelessNetworkingEnabled = statusMap.value("wirelessNetworkingEnabled").toBool(); + if (m_wirelessNetworkingEnabled != wirelessNetworkingEnabled) { + m_wirelessNetworkingEnabled = wirelessNetworkingEnabled; + emit wirelessNetworkingEnabledChanged(); + } +} + +void NetworkManager::getDevicesReply(const QVariantMap ¶ms) +{ + qDebug() << "Dwvices reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); + + foreach (const QVariant &deviceVariant, params.value("params").toMap().value("wiredNetworkDevices").toList()) { + QVariantMap deviceMap = deviceVariant.toMap(); + WiredNetworkDevice *device = new WiredNetworkDevice(deviceMap.value("macAddress").toString(), deviceMap.value("interface").toString(), this); + device->setBitRate(deviceMap.value("bitRate").toString()); + QMetaEnum stateEnum = QMetaEnum::fromType(); + device->setState(static_cast(stateEnum.keyToValue(deviceMap.value("state").toString().toUtf8()))); + device->setPluggedIn(deviceMap.value("pluggedIn").toBool()); + m_wiredNetworkDevices->addNetworkDevice(device); + } + foreach (const QVariant &deviceVariant, params.value("params").toMap().value("wirelessNetworkDevices").toList()) { + QVariantMap deviceMap = deviceVariant.toMap(); + WirelessNetworkDevice *device = new WirelessNetworkDevice(deviceMap.value("macAddress").toString(), deviceMap.value("interface").toString(), this); + device->setBitRate(deviceMap.value("bitRate").toString()); + QMetaEnum stateEnum = QMetaEnum::fromType(); + device->setState(static_cast(stateEnum.keyToValue(deviceMap.value("state").toString().toUtf8()))); + + QVariantMap currentApMap = deviceMap.value("currentAccessPoint").toMap(); + device->currentAccessPoint()->setSsid(currentApMap.value("ssid").toString()); + device->currentAccessPoint()->setMacAddress(currentApMap.value("macAddress").toString()); + device->currentAccessPoint()->setProtected(currentApMap.value("protected").toBool()); + device->currentAccessPoint()->setSignalStrength(currentApMap.value("signalStrength").toInt()); + m_wirelessNetworkDevices->addNetworkDevice(device); + } +} + +void NetworkManager::getAccessPointsReply(const QVariantMap ¶ms) +{ + qDebug() << "Access points reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); + + int requestId = params.value("id").toInt(); + if (!m_apRequests.contains(requestId)) { + qWarning() << "NetworkManager received a reply for a request we don't know!"; + return; + } + QString interface = m_apRequests.take(requestId); + + WirelessNetworkDevice *dev = m_wirelessNetworkDevices->getWirelessNetworkDevice(interface); + if (!dev) { + qWarning() << "NetworkManager received wifi list for" << interface << "but device disappeared"; + return; + } + + dev->accessPoints()->clearModel(); + + foreach (const QVariant &apVariant, params.value("params").toMap().value("wirelessAccessPoints").toList()) { + QVariantMap apMap = apVariant.toMap(); + WirelessAccessPoint* ap = new WirelessAccessPoint(this); + ap->setMacAddress(apMap.value("macAddress").toString()); + ap->setSsid(apMap.value("ssid").toString()); + ap->setProtected(apMap.value("protected").toBool()); + ap->setSignalStrength(apMap.value("signalStrength").toInt()); + dev->accessPoints()->addWirelessAccessPoint(ap); + } + +} + +void NetworkManager::connectToWiFiReply(const QVariantMap ¶ms) +{ + qDebug() << "connect to wifi reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); +} + +void NetworkManager::disconnectReply(const QVariantMap ¶ms) +{ + qDebug() << "disconnect reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); +} + +void NetworkManager::enableNetworkingReply(const QVariantMap ¶ms) +{ + qDebug() << "enable networking reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); +} + +void NetworkManager::notificationReceived(const QVariantMap ¶ms) +{ + QString notification = params.value("notification").toString(); + if (notification == "NetworkManager.WirelessNetworkDeviceChanged") { + QVariantMap deviceMap = params.value("params").toMap().value("wirelessNetworkDevice").toMap(); + WirelessNetworkDevice* device = m_wirelessNetworkDevices->getWirelessNetworkDevice(deviceMap.value("interface").toString()); + if (!device) { + qWarning() << "Received a notification for a WiFi device we don't know" << deviceMap; + return; + } + device->setBitRate(deviceMap.value("bitRate").toString()); + QMetaEnum stateEnum = QMetaEnum::fromType(); + device->setState(static_cast(stateEnum.keyToValue(deviceMap.value("state").toString().toUtf8()))); + + QVariantMap currentApMap = deviceMap.value("currentAccessPoint").toMap(); + device->currentAccessPoint()->setSsid(currentApMap.value("ssid").toString()); + device->currentAccessPoint()->setMacAddress(currentApMap.value("macAddress").toString()); + device->currentAccessPoint()->setProtected(currentApMap.value("protected").toBool()); + device->currentAccessPoint()->setSignalStrength(currentApMap.value("signalStrength").toInt()); + } else if (notification == "NetworkManager.NetworkStatusChanged") { + QMetaEnum stateEnum = QMetaEnum::fromType(); + NetworkManagerState state = static_cast(stateEnum.keyToValue(params.value("params").toMap().value("status").toMap().value("state").toString().toUtf8())); + bool networkingEnabled = params.value("params").toMap().value("status").toMap().value("networkingEnabled").toBool(); + bool wirelessNetworkingEnabled = params.value("params").toMap().value("status").toMap().value("wirelessNetworkingEnabled").toBool(); + if (m_state != state) { + m_state = state; + emit stateChanged(); + } + if (m_networkingEnabled != networkingEnabled) { + m_networkingEnabled = networkingEnabled; + emit networkingEnabledChanged(); + } + if (m_wirelessNetworkingEnabled != wirelessNetworkingEnabled) { + m_wirelessNetworkingEnabled = wirelessNetworkingEnabled; + emit wirelessNetworkingEnabledChanged(); + } + + } else { + qDebug() << "notification received" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented)); + } +} diff --git a/libnymea-app-core/configuration/networkmanager.h b/libnymea-app-core/configuration/networkmanager.h new file mode 100644 index 00000000..a322677e --- /dev/null +++ b/libnymea-app-core/configuration/networkmanager.h @@ -0,0 +1,86 @@ +#ifndef NETWORKMANAGER_H +#define NETWORKMANAGER_H + +#include +#include + +#include "jsonrpc/jsonhandler.h" + +class JsonRpcClient; +class NetworkDevices; +class WiredNetworkDevices; +class WirelessNetworkDevices; + +class NetworkManager : public JsonHandler +{ + Q_OBJECT + Q_PROPERTY(NetworkManagerState state READ state NOTIFY stateChanged) + Q_PROPERTY(bool networkingEnabled READ networkingEnabled NOTIFY networkingEnabledChanged) + Q_PROPERTY(bool wirelessNetworkingEnabled READ wirelessNetworkingEnabled NOTIFY wirelessNetworkingEnabledChanged) + + Q_PROPERTY(WiredNetworkDevices* wiredNetworkDevices READ wiredNetworkDevices CONSTANT) + Q_PROPERTY(WirelessNetworkDevices* wirelessNetworkDevices READ wirelessNetworkDevices CONSTANT) + +public: + enum NetworkManagerState { + NetworkManagerStateUnknown = 0, + NetworkManagerStateAsleep = 10, + NetworkManagerStateDisconnected = 20, + NetworkManagerStateDisconnecting = 30, + NetworkManagerStateConnecting = 40, + NetworkManagerStateConnectedLocal = 50, + NetworkManagerStateConnectedSite = 60, + NetworkManagerStateConnectedGlobal = 70 + }; + Q_ENUM(NetworkManagerState) + + explicit NetworkManager(JsonRpcClient *jsonClient, QObject *parent = nullptr); + + QString nameSpace() const override; + + void init(); + + NetworkManagerState state() const; + bool networkingEnabled() const; + bool wirelessNetworkingEnabled() const; + + WiredNetworkDevices* wiredNetworkDevices() const; + WirelessNetworkDevices* wirelessNetworkDevices() const; + + Q_INVOKABLE void enableNetworking(bool enable); + Q_INVOKABLE void enableWirelessNetworking(bool enable); + + Q_INVOKABLE void refreshWifis(const QString &interface); + + Q_INVOKABLE void connectToWiFi(const QString &interface, const QString &ssid, const QString &passphrase); + Q_INVOKABLE void disconnectInterface(const QString &interface); + +private slots: + void getStatusReply(const QVariantMap ¶ms); + void getDevicesReply(const QVariantMap ¶ms); + void getAccessPointsReply(const QVariantMap ¶ms); + void connectToWiFiReply(const QVariantMap ¶ms); + void disconnectReply(const QVariantMap ¶ms); + void enableNetworkingReply(const QVariantMap ¶ms); + + void notificationReceived(const QVariantMap ¶ms); + +signals: + void stateChanged(); + void networkingEnabledChanged(); + void wirelessNetworkingEnabledChanged(); + +private: + JsonRpcClient *m_jsonClient = nullptr; + + NetworkManagerState m_state = NetworkManagerStateUnknown; + bool m_networkingEnabled = false; + bool m_wirelessNetworkingEnabled = false; + + WiredNetworkDevices* m_wiredNetworkDevices = nullptr; + WirelessNetworkDevices* m_wirelessNetworkDevices = nullptr; + + QHash m_apRequests; // requestId, interface +}; + +#endif // NETWORKMANAGER_H diff --git a/libnymea-app-core/engine.cpp b/libnymea-app-core/engine.cpp index cceb8a1c..2c521b9f 100644 --- a/libnymea-app-core/engine.cpp +++ b/libnymea-app-core/engine.cpp @@ -26,6 +26,7 @@ #include "configuration/nymeaconfiguration.h" #include "connection/awsclient.h" #include "system/systemcontroller.h" +#include "configuration/networkmanager.h" #include "connection/tcpsockettransport.h" #include "connection/websockettransport.h" @@ -41,7 +42,8 @@ Engine::Engine(QObject *parent) : m_logManager(new LogManager(m_jsonRpcClient, this)), m_tagsManager(new TagsManager(m_jsonRpcClient, this)), m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)), - m_systemController(new SystemController(m_jsonRpcClient, this)) + m_systemController(new SystemController(m_jsonRpcClient, this)), + m_networkManager(new NetworkManager(m_jsonRpcClient, this)) { m_connection->registerTransport(new TcpSocketTransportFactory()); m_connection->registerTransport(new WebsocketTransportFactory()); @@ -104,6 +106,11 @@ SystemController *Engine::systemController() const return m_systemController; } +NetworkManager *Engine::networkManager() const +{ + return m_networkManager; +} + void Engine::deployCertificate() { if (!m_jsonRpcClient->connected()) { @@ -137,6 +144,7 @@ void Engine::onConnectedChanged() m_ruleManager->init(); m_nymeaConfiguration->init(); m_systemController->init(); + m_networkManager->init(); } } } diff --git a/libnymea-app-core/engine.h b/libnymea-app-core/engine.h index 8184b3ad..d890533f 100644 --- a/libnymea-app-core/engine.h +++ b/libnymea-app-core/engine.h @@ -33,6 +33,7 @@ class LogManager; class TagsManager; class NymeaConfiguration; class SystemController; +class NetworkManager; class Engine : public QObject { @@ -44,6 +45,7 @@ class Engine : public QObject Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT) Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT) Q_PROPERTY(SystemController* systemController READ systemController CONSTANT) + Q_PROPERTY(NetworkManager* networkManager READ networkManager CONSTANT) public: explicit Engine(QObject *parent = nullptr); @@ -59,6 +61,7 @@ public: LogManager *logManager() const; NymeaConfiguration *nymeaConfiguration() const; SystemController *systemController() const; + NetworkManager *networkManager() const; Q_INVOKABLE void deployCertificate(); @@ -71,6 +74,7 @@ private: TagsManager *m_tagsManager; NymeaConfiguration *m_nymeaConfiguration; SystemController *m_systemController; + NetworkManager *m_networkManager; private slots: void onConnectedChanged(); diff --git a/libnymea-app-core/libnymea-app-core.h b/libnymea-app-core/libnymea-app-core.h index 03e45ce4..7e2d2a46 100644 --- a/libnymea-app-core/libnymea-app-core.h +++ b/libnymea-app-core/libnymea-app-core.h @@ -41,9 +41,9 @@ #include "configuration/mqttpolicy.h" #include "configuration/mqttpolicies.h" #include "wifisetup/networkmanagercontroller.h" -#include "wifisetup/wirelessaccesspoint.h" -#include "wifisetup/wirelessaccesspoints.h" -#include "wifisetup/wirelessaccesspointsproxy.h" +#include "types/wirelessaccesspoint.h" +#include "types/wirelessaccesspoints.h" +#include "models/wirelessaccesspointsproxy.h" #include "tagsmanager.h" #include "models/tagsproxymodel.h" #include "types/tag.h" @@ -62,6 +62,9 @@ #include "types/repository.h" #include "types/repositories.h" #include "models/packagesfiltermodel.h" +#include "configuration/networkmanager.h" +#include "types/networkdevices.h" +#include "types/networkdevice.h" #include @@ -212,6 +215,14 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "Repositories", "Get it from SystemController"); qmlRegisterUncreatableType(uri, 1, 0, "Repository", "Get it from Repositories"); qmlRegisterType(uri, 1, 0, "PackagesFilterModel"); + + qmlRegisterUncreatableType(uri, 1, 0, "NetworkManager", "Get it from Engine"); + qmlRegisterUncreatableType(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager"); + qmlRegisterUncreatableType(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager"); + qmlRegisterUncreatableType(uri, 1, 0, "WirelessNetworkDevices", "Get it from NetworkManager"); + qmlRegisterUncreatableType(uri, 1, 0, "NetworkDevice", "Get it from NetworkDevices"); + qmlRegisterUncreatableType(uri, 1, 0, "WiredNetworkDevice", "Get it from NetworkDevices"); + qmlRegisterUncreatableType(uri, 1, 0, "WirelessNetworkDevice", "Get it from NetworkDevices"); } #endif // LIBNYMEAAPPCORE_H diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro index c548e068..07c479db 100644 --- a/libnymea-app-core/libnymea-app-core.pro +++ b/libnymea-app-core/libnymea-app-core.pro @@ -24,6 +24,7 @@ INCLUDEPATH += $$top_srcdir/libnymea-common \ $$top_srcdir/qmqtt/src/mqtt/ SOURCES += \ + configuration/networkmanager.cpp \ engine.cpp \ connection/nymeahost.cpp \ connection/nymeahosts.cpp \ @@ -59,15 +60,13 @@ SOURCES += \ wifisetup/bluetoothdeviceinfo.cpp \ wifisetup/bluetoothdeviceinfos.cpp \ wifisetup/bluetoothdiscovery.cpp \ - wifisetup/wirelessaccesspoint.cpp \ - wifisetup/wirelessaccesspoints.cpp \ wifisetup/wirelesssetupmanager.cpp \ wifisetup/networkmanagercontroller.cpp \ models/logsmodelng.cpp \ models/interfacesproxy.cpp \ models/tagsproxymodel.cpp \ tagsmanager.cpp \ - wifisetup/wirelessaccesspointsproxy.cpp \ + models/wirelessaccesspointsproxy.cpp \ ruletemplates/ruletemplate.cpp \ ruletemplates/ruletemplates.cpp \ ruletemplates/eventdescriptortemplate.cpp \ @@ -86,6 +85,7 @@ SOURCES += \ system/systemcontroller.cpp HEADERS += \ + configuration/networkmanager.h \ engine.h \ connection/nymeahost.h \ connection/nymeahosts.h \ @@ -122,8 +122,6 @@ HEADERS += \ wifisetup/bluetoothdeviceinfo.h \ wifisetup/bluetoothdeviceinfos.h \ wifisetup/bluetoothdiscovery.h \ - wifisetup/wirelessaccesspoint.h \ - wifisetup/wirelessaccesspoints.h \ wifisetup/wirelesssetupmanager.h \ wifisetup/networkmanagercontroller.h \ libnymea-app-core.h \ @@ -131,7 +129,7 @@ HEADERS += \ models/interfacesproxy.h \ tagsmanager.h \ models/tagsproxymodel.h \ - wifisetup/wirelessaccesspointsproxy.h \ + models/wirelessaccesspointsproxy.h \ ruletemplates/ruletemplate.h \ ruletemplates/ruletemplates.h \ ruletemplates/eventdescriptortemplate.h \ diff --git a/libnymea-app-core/wifisetup/wirelessaccesspointsproxy.cpp b/libnymea-app-core/models/wirelessaccesspointsproxy.cpp similarity index 96% rename from libnymea-app-core/wifisetup/wirelessaccesspointsproxy.cpp rename to libnymea-app-core/models/wirelessaccesspointsproxy.cpp index f76da4c4..ec4a6ee5 100644 --- a/libnymea-app-core/wifisetup/wirelessaccesspointsproxy.cpp +++ b/libnymea-app-core/models/wirelessaccesspointsproxy.cpp @@ -22,8 +22,8 @@ #include "wirelessaccesspointsproxy.h" -#include "wirelessaccesspoint.h" -#include "wirelessaccesspoints.h" +#include "types/wirelessaccesspoint.h" +#include "types/wirelessaccesspoints.h" #include diff --git a/libnymea-app-core/wifisetup/wirelessaccesspointsproxy.h b/libnymea-app-core/models/wirelessaccesspointsproxy.h similarity index 100% rename from libnymea-app-core/wifisetup/wirelessaccesspointsproxy.h rename to libnymea-app-core/models/wirelessaccesspointsproxy.h diff --git a/libnymea-app-core/wifisetup/wirelesssetupmanager.cpp b/libnymea-app-core/wifisetup/wirelesssetupmanager.cpp index ddeb07e1..84cf284c 100644 --- a/libnymea-app-core/wifisetup/wirelesssetupmanager.cpp +++ b/libnymea-app-core/wifisetup/wirelesssetupmanager.cpp @@ -21,9 +21,9 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "wirelesssetupmanager.h" -#include "wirelessaccesspoint.h" -#include "wirelessaccesspoints.h" -#include "wirelessaccesspointsproxy.h" +#include "types/wirelessaccesspoint.h" +#include "types/wirelessaccesspoints.h" +#include "models/wirelessaccesspointsproxy.h" #include diff --git a/libnymea-common/libnymea-common.pro b/libnymea-common/libnymea-common.pro index 33bda42a..7b90c204 100644 --- a/libnymea-common/libnymea-common.pro +++ b/libnymea-common/libnymea-common.pro @@ -8,6 +8,8 @@ QT -= gui QT += network HEADERS += \ + types/networkdevice.h \ + types/networkdevices.h \ types/package.h \ types/packages.h \ types/repositories.h \ @@ -55,9 +57,13 @@ HEADERS += \ types/calendaritems.h \ types/repeatingoption.h \ types/tag.h \ - types/tags.h + types/tags.h \ + types/wirelessaccesspoint.h \ + types/wirelessaccesspoints.h \ SOURCES += \ + types/networkdevice.cpp \ + types/networkdevices.cpp \ types/package.cpp \ types/packages.cpp \ types/repositories.cpp \ @@ -104,4 +110,6 @@ SOURCES += \ types/calendaritems.cpp \ types/repeatingoption.cpp \ types/tag.cpp \ - types/tags.cpp + types/tags.cpp \ + types/wirelessaccesspoint.cpp \ + types/wirelessaccesspoints.cpp \ diff --git a/libnymea-common/types/networkdevice.cpp b/libnymea-common/types/networkdevice.cpp new file mode 100644 index 00000000..3bfeb0a5 --- /dev/null +++ b/libnymea-common/types/networkdevice.cpp @@ -0,0 +1,84 @@ +#include "networkdevice.h" + +#include "wirelessaccesspoints.h" +#include "wirelessaccesspoint.h" + +NetworkDevice::NetworkDevice(const QString &macAddress, const QString &interface, QObject *parent): + QObject (parent), + m_macAddress(macAddress), + m_interface(interface) +{ + +} + +QString NetworkDevice::macAddress() const +{ + return m_macAddress; +} + +QString NetworkDevice::interface() const +{ + return m_interface; +} + +QString NetworkDevice::bitRate() const +{ + return m_bitRate; +} + +void NetworkDevice::setBitRate(const QString &bitRate) +{ + if (m_bitRate != bitRate) { + m_bitRate = bitRate; + emit bitRateChanged(); + } +} + +NetworkDevice::NetworkDeviceState NetworkDevice::state() const +{ + return m_state; +} + +void NetworkDevice::setState(NetworkDevice::NetworkDeviceState state) +{ + if (m_state != state) { + m_state = state; + emit stateChanged(); + } +} + +WiredNetworkDevice::WiredNetworkDevice(const QString &macAddress, const QString &interface, QObject *parent): + NetworkDevice (macAddress, interface, parent) +{ + +} + +bool WiredNetworkDevice::pluggedIn() const +{ + return m_pluggedIn; +} + +void WiredNetworkDevice::setPluggedIn(bool pluggedIn) +{ + if (m_pluggedIn != pluggedIn) { + m_pluggedIn = pluggedIn; + emit pluggedInChanged(); + } +} + +WirelessNetworkDevice::WirelessNetworkDevice(const QString &macAddress, const QString &interface, QObject *parent): + NetworkDevice (macAddress, interface, parent) +{ + m_accessPoints = new WirelessAccessPoints(this); + m_currentAccessPoint = new WirelessAccessPoint(this); +} + +WirelessAccessPoints *WirelessNetworkDevice::accessPoints() const +{ + return m_accessPoints; +} + +WirelessAccessPoint *WirelessNetworkDevice::currentAccessPoint() const +{ + return m_currentAccessPoint; +} diff --git a/libnymea-common/types/networkdevice.h b/libnymea-common/types/networkdevice.h new file mode 100644 index 00000000..ff13e021 --- /dev/null +++ b/libnymea-common/types/networkdevice.h @@ -0,0 +1,91 @@ +#ifndef NETWORKDEVICE_H +#define NETWORKDEVICE_H + +#include + +class WirelessAccessPoint; +class WirelessAccessPoints; + +class NetworkDevice : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString macAddress READ macAddress CONSTANT) + Q_PROPERTY(QString interface READ interface CONSTANT) + Q_PROPERTY(QString bitRate READ bitRate NOTIFY bitRateChanged) + Q_PROPERTY(NetworkDeviceState state READ state NOTIFY stateChanged) + +public: + enum NetworkDeviceState { + NetworkDeviceStateUnknown = 0, + NetworkDeviceStateUnmanaged = 10, + NetworkDeviceStateUnavailable = 20, + NetworkDeviceStateDisconnected = 30, + NetworkDeviceStatePrepare = 40, + NetworkDeviceStateConfig = 50, + NetworkDeviceStateNeedAuth = 60, + NetworkDeviceStateIpConfig = 70, + NetworkDeviceStateIpCheck = 80, + NetworkDeviceStateSecondaries = 90, + NetworkDeviceStateActivated = 100, + NetworkDeviceStateDeactivating = 110, + NetworkDeviceStateFailed = 120 + }; + Q_ENUM(NetworkDeviceState) + + explicit NetworkDevice(const QString &macAddress, const QString &interface, QObject *parent = nullptr); + virtual ~NetworkDevice() = default; + + QString macAddress() const; + QString interface() const; + + QString bitRate() const; + void setBitRate(const QString &bitRate); + + NetworkDeviceState state() const; + void setState(NetworkDeviceState state); + +signals: + void bitRateChanged(); + void stateChanged(); + +private: + QString m_macAddress; + QString m_interface; + QString m_bitRate; + NetworkDeviceState m_state; +}; + +class WiredNetworkDevice: public NetworkDevice { + Q_OBJECT + Q_PROPERTY(bool pluggedIn READ pluggedIn NOTIFY pluggedInChanged) + +public: + explicit WiredNetworkDevice(const QString &macAddress, const QString &interface, QObject *parent = nullptr); + + bool pluggedIn() const; + void setPluggedIn(bool pluggedIn); + +signals: + void pluggedInChanged(); + +private: + bool m_pluggedIn = false; +}; + +class WirelessNetworkDevice: public NetworkDevice +{ + Q_OBJECT + Q_PROPERTY(WirelessAccessPoints* accessPoints READ accessPoints CONSTANT) + Q_PROPERTY(WirelessAccessPoint* currentAccessPoint READ currentAccessPoint CONSTANT) + +public: + explicit WirelessNetworkDevice(const QString &macAddress, const QString &interface, QObject *parent = nullptr); + + WirelessAccessPoints* accessPoints() const; + WirelessAccessPoint* currentAccessPoint() const; + +private: + WirelessAccessPoints *m_accessPoints = nullptr; + WirelessAccessPoint *m_currentAccessPoint = nullptr; +}; +#endif // NETWORKDEVICE_H diff --git a/libnymea-common/types/networkdevices.cpp b/libnymea-common/types/networkdevices.cpp new file mode 100644 index 00000000..85088375 --- /dev/null +++ b/libnymea-common/types/networkdevices.cpp @@ -0,0 +1,148 @@ +#include "networkdevices.h" +#include "networkdevice.h" + +NetworkDevices::NetworkDevices(QObject *parent): QAbstractListModel(parent) +{ + +} + +int NetworkDevices::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_list.count(); +} + +QVariant NetworkDevices::data(const QModelIndex &index, int role) const +{ + switch (role) { + case RoleMacAddress: + return m_list.at(index.row())->macAddress(); + case RoleInterface: + return m_list.at(index.row())->interface(); + case RoleBitRate: + return m_list.at(index.row())->bitRate(); + case RoleState: + return m_list.at(index.row())->state(); + } + return QVariant(); +} + +QHash NetworkDevices::roleNames() const +{ + QHash roles; + roles.insert(RoleMacAddress, "macAddress"); + roles.insert(RoleInterface, "interface"); + roles.insert(RoleBitRate, "bitRate"); + roles.insert(RoleState, "state"); + return roles; +} + +void NetworkDevices::addNetworkDevice(NetworkDevice *networkDevice) +{ + networkDevice->setParent(this); + beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); + m_list.append(networkDevice); + connect(networkDevice, &NetworkDevice::bitRateChanged, this, [this, networkDevice](){ + emit dataChanged(index(m_list.indexOf(networkDevice)), index(m_list.indexOf(networkDevice)), {RoleBitRate}); + emit countChanged(); + }); + connect(networkDevice, &NetworkDevice::stateChanged, this, [this, networkDevice](){ + emit dataChanged(index(m_list.indexOf(networkDevice)), index(m_list.indexOf(networkDevice)), {RoleState}); + emit countChanged(); + }); + endInsertRows(); + emit countChanged(); +} + +void NetworkDevices::removeNetworkDevice(const QString &interface) +{ + int idx = -1; + for (int i = 0; i < m_list.count(); i++) { + if (m_list.at(i)->interface() == interface) { + idx = i; + break; + } + } + if (idx < 0) { + return; + } + + beginRemoveRows(QModelIndex(), idx, idx); + m_list.takeAt(idx)->deleteLater(); + endRemoveRows(); + emit countChanged(); +} + +NetworkDevice *NetworkDevices::get(int index) const +{ + if (index >= 0 && index < m_list.count()) { + return m_list.at(index); + } + return nullptr; +} + +NetworkDevice *NetworkDevices::getNetworkDevice(const QString &interface) +{ + foreach (NetworkDevice *p, m_list) { + if (p->interface() == interface) { + return p; + } + } + return nullptr; +} + +void NetworkDevices::clear() +{ + beginResetModel(); + qDeleteAll(m_list); + m_list.clear(); + endResetModel(); + emit countChanged(); +} + +WiredNetworkDevices::WiredNetworkDevices(QObject *parent): + NetworkDevices(parent) +{ + +} + +QVariant WiredNetworkDevices::data(const QModelIndex &index, int role) const +{ + if (role == RolePluggedIn) { + WiredNetworkDevice *dev = qobject_cast(m_list.at(index.row())); + return dev->pluggedIn(); + } + return NetworkDevices::data(index, role); +} + +void WiredNetworkDevices::addNetworkDevice(NetworkDevice *device) +{ + NetworkDevices::addNetworkDevice(device); + WiredNetworkDevice *wiredDev = qobject_cast(device); + if (wiredDev) { + connect(wiredDev, &WiredNetworkDevice::pluggedInChanged, [this, wiredDev](){ + emit dataChanged(index(m_list.indexOf(wiredDev)), index(m_list.indexOf(wiredDev)), {RolePluggedIn}); + emit countChanged(); + }); + } +} + +QHash WiredNetworkDevices::roleNames() const +{ + QHash roles = NetworkDevices::roleNames(); + roles.insert(RolePluggedIn, "pluggedIn"); + return roles; +} + +WirelessNetworkDevices::WirelessNetworkDevices(QObject *parent): + NetworkDevices (parent) +{ + +} + +#include + +WirelessNetworkDevice *WirelessNetworkDevices::getWirelessNetworkDevice(const QString &interface) +{ + return dynamic_cast(NetworkDevices::getNetworkDevice(interface)); +} diff --git a/libnymea-common/types/networkdevices.h b/libnymea-common/types/networkdevices.h new file mode 100644 index 00000000..c271e09f --- /dev/null +++ b/libnymea-common/types/networkdevices.h @@ -0,0 +1,71 @@ +#ifndef NETWORKDEVICES_H +#define NETWORKDEVICES_H + +#include + +class NetworkDevice; +class WiredNetworkDevice; +class WirelessNetworkDevice; + +class NetworkDevices: public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) +public: + enum Roles { + RoleMacAddress, + RoleInterface, + RoleBitRate, + RoleState, + }; + Q_ENUM(Roles) + + explicit NetworkDevices(QObject *parent = nullptr); + virtual ~NetworkDevices() override = default; + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + virtual QHash roleNames() const override; + + virtual void addNetworkDevice(NetworkDevice *networkDevice); + void removeNetworkDevice(const QString &interface); + + Q_INVOKABLE virtual NetworkDevice* get(int index) const; + Q_INVOKABLE virtual NetworkDevice* getNetworkDevice(const QString &interface); + + void clear(); + +signals: + void countChanged(); + +protected: + QList m_list; +}; + +class WiredNetworkDevices: public NetworkDevices +{ + Q_OBJECT +public: + enum Roles { + RolePluggedIn = 1000 + }; + + explicit WiredNetworkDevices(QObject *parent = nullptr); + QVariant data(const QModelIndex &index, int role) const override; + + void addNetworkDevice(NetworkDevice *device) override; + + QHash roleNames() const override; +}; + +class WirelessNetworkDevices: public NetworkDevices +{ + Q_OBJECT +public: + explicit WirelessNetworkDevices(QObject *parent = nullptr); + + Q_INVOKABLE WirelessNetworkDevice* getWirelessNetworkDevice(const QString &interface); + +}; + +#endif // NETWORKDEVICES_H diff --git a/libnymea-app-core/wifisetup/wirelessaccesspoint.cpp b/libnymea-common/types/wirelessaccesspoint.cpp similarity index 100% rename from libnymea-app-core/wifisetup/wirelessaccesspoint.cpp rename to libnymea-common/types/wirelessaccesspoint.cpp diff --git a/libnymea-app-core/wifisetup/wirelessaccesspoint.h b/libnymea-common/types/wirelessaccesspoint.h similarity index 100% rename from libnymea-app-core/wifisetup/wirelessaccesspoint.h rename to libnymea-common/types/wirelessaccesspoint.h diff --git a/libnymea-app-core/wifisetup/wirelessaccesspoints.cpp b/libnymea-common/types/wirelessaccesspoints.cpp similarity index 100% rename from libnymea-app-core/wifisetup/wirelessaccesspoints.cpp rename to libnymea-common/types/wirelessaccesspoints.cpp diff --git a/libnymea-app-core/wifisetup/wirelessaccesspoints.h b/libnymea-common/types/wirelessaccesspoints.h similarity index 100% rename from libnymea-app-core/wifisetup/wirelessaccesspoints.h rename to libnymea-common/types/wirelessaccesspoints.h diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index 6bcfd6bd..c37e432e 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -183,5 +183,6 @@ ui/system/SystemUpdatePage.qml ui/components/UpdateRunningOverlay.qml ui/connection/SetupWizard.qml + ui/system/NetworkSettingsPage.qml diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index c54a0802..c2b2a71e 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -47,12 +47,12 @@ Page { padding: 0 MeaListItemDelegate { width: parent.width - iconName: "../images/logs.svg" - text: qsTr("Log viewer") - subText: qsTr("View system log") + iconName: "../images/network-wifi.svg" + text: qsTr("Networking") + subText: qsTr("Configure the box's network connection") prominentSubText: false wrapTexts: false - onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) + onClicked: pageStack.push(Qt.resolvedUrl("system/NetworkSettingsPage.qml")) } } @@ -172,6 +172,22 @@ Page { } } + Pane { + Layout.fillWidth: true + Material.elevation: layout.isGrid ? 1 : 0 + + padding: 0 + MeaListItemDelegate { + width: parent.width + iconName: "../images/logs.svg" + text: qsTr("Log viewer") + subText: qsTr("View system log") + prominentSubText: false + wrapTexts: false + onClicked: pageStack.push(Qt.resolvedUrl("system/LogViewerPage.qml")) + } + } + Pane { Layout.fillWidth: true Material.elevation: layout.isGrid ? 1 : 0 diff --git a/nymea-app/ui/components/EmptyViewPlaceholder.qml b/nymea-app/ui/components/EmptyViewPlaceholder.qml index ad81094f..aad3a618 100644 --- a/nymea-app/ui/components/EmptyViewPlaceholder.qml +++ b/nymea-app/ui/components/EmptyViewPlaceholder.qml @@ -4,7 +4,7 @@ import QtQuick.Layouts 1.3 ColumnLayout { id: root - spacing: app.margins * 2 + spacing: app.margins property alias title: titleLabel.text property alias text: textLabel.text diff --git a/nymea-app/ui/components/MeaListItemDelegate.qml b/nymea-app/ui/components/MeaListItemDelegate.qml index e93839a1..1ac96205 100644 --- a/nymea-app/ui/components/MeaListItemDelegate.qml +++ b/nymea-app/ui/components/MeaListItemDelegate.qml @@ -25,9 +25,12 @@ SwipeDelegate { property alias tertiaryIconColor: tertiaryIcon.color property alias tertiaryIconKeyColor: tertiaryIcon.keyColor + property alias additionalItem: additionalItemContainer.children + signal deleteClicked() contentItem: RowLayout { + id: innerLayout spacing: app.margins ColorIcon { id: icon @@ -85,6 +88,13 @@ SwipeDelegate { name: "../images/next.svg" visible: root.progressive } + + Item { + id: additionalItemContainer + Layout.fillHeight: true + Layout.preferredWidth: childrenRect.width + visible: children.length > 0 + } } swipe.enabled: canDelete diff --git a/nymea-app/ui/connection/ConnectingPage.qml b/nymea-app/ui/connection/ConnectingPage.qml index 7d4c49f6..40258b07 100644 --- a/nymea-app/ui/connection/ConnectingPage.qml +++ b/nymea-app/ui/connection/ConnectingPage.qml @@ -49,6 +49,7 @@ Page { } Label { Layout.fillWidth: true + Layout.preferredHeight: 150 text: { var errorMessage; switch (engine.connection.connectionStatus) { @@ -96,7 +97,7 @@ Page { Button { text: qsTr("Cancel") - anchors { left: parent.left; top: columnLayout.bottom; right: parent.right } + anchors { left: parent.left; bottom: parent.bottom; right: parent.right } anchors.margins: app.margins onClicked: root.cancel() } diff --git a/nymea-app/ui/devicepages/GenericDevicePage.qml b/nymea-app/ui/devicepages/GenericDevicePage.qml index 79041414..3be7f3db 100644 --- a/nymea-app/ui/devicepages/GenericDevicePage.qml +++ b/nymea-app/ui/devicepages/GenericDevicePage.qml @@ -1,7 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.2 -import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.1 import Nymea 1.0 import "../components" diff --git a/nymea-app/ui/system/NetworkSettingsPage.qml b/nymea-app/ui/system/NetworkSettingsPage.qml new file mode 100644 index 00000000..617d02ab --- /dev/null +++ b/nymea-app/ui/system/NetworkSettingsPage.qml @@ -0,0 +1,406 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.1 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.1 +import Nymea 1.0 +import "../components" + +Page { + id: root + header: GuhHeader { + text: qsTr("Network settings") + onBackPressed: { + pageStack.pop(); + } + } + + readonly property NetworkManager networkManager: engine.networkManager + + function networkStateToString(networkState) { + switch (networkState) { + case NetworkDevice.NetworkDeviceStateUnknown: + return qsTr("Unknown") + case NetworkDevice.NetworkDeviceStateUnmanaged: + return qsTr("Unmanaged") + case NetworkDevice.NetworkDeviceStateUnavailable: + return qsTr("Unavailable") + case NetworkDevice.NetworkDeviceStateDisconnected: + return qsTr("Disconnected") + case NetworkDevice.NetworkDeviceStateDeactivating: + return qsTr("Deactivating") + case NetworkDevice.NetworkDeviceStateFailed: + return qsTr("Failed") + case NetworkDevice.NetworkDeviceStatePrepare: + return qsTr("Preparing") + case NetworkDevice.NetworkDeviceStateConfig: + return qsTr("Configuring") + case NetworkDevice.NetworkDeviceStateNeedAuth: + return qsTr("Waiting for password") + case NetworkDevice.NetworkDeviceStateIpConfig: + return qsTr("Setting IP configuration") + case NetworkDevice.NetworkDeviceStateIpCheck: + return qsTr("Checking IP configuration") + case NetworkDevice.NetworkDeviceStateSecondaries: + return qsTr("Secondaries") + case NetworkDevice.NetworkDeviceStateActivated: + return qsTr("Connected"); + } + } + + ColumnLayout { + anchors.fill: parent + + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Current connection state") + prominentSubText: false + subText: { + switch (networkManager.state) { + case NetworkManager.NetworkManagerStateUnknown: + return qsTr("Unknown"); + case NetworkManager.NetworkManagerStateAsleep: + return qsTr("Asleep"); + case NetworkManager.NetworkManagerStateDisconnected: + return qsTr("Disconnected") + case NetworkManager.NetworkManagerStateDisconnecting: + return qsTr("Disconnecting") + case NetworkManager.NetworkManagerStateConnecting: + return qsTr("Connecting") + case NetworkManager.NetworkManagerStateConnectedLocal: + return qsTr("Locally connected") + case NetworkManager.NetworkManagerStateConnectedSite: + return qsTr("Site connected") + case NetworkManager.NetworkManagerStateConnectedGlobal: + return qsTr("Globally connected") + + } + } + progressive: false + additionalItem: Led { + state: { + switch (networkManager.state) { + case NetworkManager.NetworkManagerStateUnknown: + case NetworkManager.NetworkManagerStateAsleep: + return "off"; + case NetworkManager.NetworkManagerStateDisconnected: + case NetworkManager.NetworkManagerStateDisconnecting: + return "red" + case NetworkManager.NetworkManagerStateConnecting: + case NetworkManager.NetworkManagerStateConnectedLocal: + case NetworkManager.NetworkManagerStateConnectedSite: + return "orange" + case NetworkManager.NetworkManagerStateConnectedGlobal: + return "green"; + + } + } + } + } + + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Networking enabled") + subText: qsTr("Enable or disable networking altogether") + prominentSubText: false + progressive: false + additionalItem: Switch { + checked: networkManager.networkingEnabled + onClicked: { + if (!checked) { + var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml")); + var text = qsTr("Disabling networking will disconnect all connected clients. Be aware that you will not be able to interact remotely with this %1 box any more. Do not proceed unless you know what your are doing.").arg(app.systemName) + + "\n\n" + + qsTr("\nDo you want to proceed?") + var popup = dialog.createObject(app, + { + headerIcon: "../images/dialog-warning-symbolic.svg", + title: qsTr("Disable networking?"), + text: text, + standardButtons: Dialog.Ok | Dialog.Cancel + }); + popup.open(); + popup.accepted.connect(function() { + networkManager.enableNetworking(false); + }) + popup.rejected.connect(function() { + checked = true; + }) + } else { + networkManager.enableNetworking(true); + } + } + } + } + ThinDivider {} + + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Wired network") + subText: qsTr("Shows the current ethernet status") + progressive: false + prominentSubText: false + } + + Repeater { + model: networkManager.wiredNetworkDevices + MeaListItemDelegate { + Layout.fillWidth: true + iconName: model.pluggedIn ? "../images/network-wired.svg" : "../images/network-wired-offline.svg" + text: model.interface + " (" + model.macAddress + ")" + subText: { + var ret = model.pluggedIn ? qsTr("Plugged in") : qsTr("Unplugged") + ret += " - " + ret += networkStateToString(model.state) + return ret; + } + progressive: false + } + } + + ThinDivider {} + + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Wireless network") + subText: qsTr("Enable or disable WiFi") + progressive: false + prominentSubText: false + additionalItem: Switch { + checked: networkManager.wirelessNetworkingEnabled + onClicked: { + if (!checked) { + var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml")); + var text = qsTr("Disabling WiFi will disconnect all clients connected via WiFi. Be aware that you will not be able to interact remotely with this %1 box any more unless a LAN cable is connected.").arg(app.systemName) + + "\n\n" + + qsTr("\nDo you want to proceed?") + var popup = dialog.createObject(app, + { + headerIcon: "../images/dialog-warning-symbolic.svg", + title: qsTr("Disable WiFi?"), + text: text, + standardButtons: Dialog.Ok | Dialog.Cancel + }); + popup.open(); + popup.accepted.connect(function() { + networkManager.enableWirelessNetworking(false); + }) + popup.rejected.connect(function() { + checked = true; + }) + } else { + networkManager.enableWirelessNetworking(true); + } + } + } + } + + Repeater { + model: networkManager.wirelessNetworkDevices + MeaListItemDelegate { + Layout.fillWidth: true + iconName: { + switch (model.state) { + case NetworkDevice.NetworkDeviceStateUnknown: + case NetworkDevice.NetworkDeviceStateUnmanaged: + case NetworkDevice.NetworkDeviceStateUnavailable: + case NetworkDevice.NetworkDeviceStateDisconnected: + case NetworkDevice.NetworkDeviceStateDeactivating: + case NetworkDevice.NetworkDeviceStateFailed: + return "../images/network-wifi-offline.svg" + case NetworkDevice.NetworkDeviceStatePrepare: + return "../images/network-wifi.svg"; + case NetworkDevice.NetworkDeviceStateConfig: + return "../images/network-wifi-offline.svg" + case NetworkDevice.NetworkDeviceStateNeedAuth: + return "../images/network-wifi.svg"; + case NetworkDevice.NetworkDeviceStateIpConfig: + return "../images/network-wifi-offline.svg" + case NetworkDevice.NetworkDeviceStateIpCheck: + return "../images/network-wifi.svg"; + case NetworkDevice.NetworkDeviceStateSecondaries: + return "../images/network-wifi-offline.svg" + case NetworkDevice.NetworkDeviceStateActivated: + return "../images/network-wifi.svg"; + + } + console.warn("Unhandled enum", model.state) + } + text: model.interface + " (" + model.macAddress + ")" + subText: networkStateToString(model.state) + onClicked: { + var wirelessNetworkDevice = networkManager.wirelessNetworkDevices.getWirelessNetworkDevice(model.interface); + if (wirelessNetworkDevice.state === NetworkDevice.NetworkDeviceStateDisconnected) { + networkManager.refreshWifis(model.interface) + pageStack.push(wirelessAccessPointsPageComponent, {wirelessNetworkDevice: wirelessNetworkDevice}) + } else { + pageStack.push(currentApPageComponent, {wirelessNetworkDevice: wirelessNetworkDevice}) + } + } + } + } + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + Component { + id: wirelessAccessPointsPageComponent + Page { + id: wirelessAccessPointsPage + header: GuhHeader { + text: qsTr("WiFi networks") + onBackPressed: { + pageStack.pop(); + } + } + + property var wirelessNetworkDevice: null + + WirelessAccessPointsProxy { + id: apProxy + accessPoints: wirelessAccessPointsPage.wirelessNetworkDevice.accessPoints + } + + ListView { + id: listView + anchors.fill: parent + model: apProxy + ScrollBar.vertical: ScrollBar {} + delegate: MeaListItemDelegate { + width: parent.width + text: model.ssid + subText: model.macAddress + iconName: { + var ret = "../images/nm-signal-"; + if (model.signalStrength > 90) { + ret += "100"; + } else if (model.signalStrength > 60) { + ret += "75"; + } else if (model.signalStrength > 40) { + ret += "50"; + } else if (model.signalStrength > 20) { + ret += "25"; + } else { + ret += "00"; + } + if (model.isProtected) { + ret += "-secure" + } + ret += ".svg"; + return ret; + } + + progressive: false + prominentSubText: false + onClicked: { + print("pushing", wirelessAccessPointsPage.wirelessNetworkDevice.state) + pageStack.push(authPageComponent, {wirelessNetworkDevice: wirelessAccessPointsPage.wirelessNetworkDevice, wirelessAccessPoint: apProxy.get(index)}) + } + } + } + } + } + + Component { + id: authPageComponent + Page { + id: authPage + + header: GuhHeader { + text: qsTr("Authenticate") + onBackPressed: pageStack.pop() + } + + property var wirelessNetworkDevice: null + property var wirelessAccessPoint: null + + ColumnLayout { + anchors { left: parent.left; top: parent.top; right: parent.right } + + Label { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Enter the password for %1").arg(authPage.wirelessAccessPoint.ssid) + wrapMode: Text.WordWrap + } + RowLayout { + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + TextField { + id: passwordTextField + Layout.fillWidth: true + property bool showPassword: false + echoMode: showPassword ? TextInput.Normal : TextInput.Password + } + + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/eye.svg" + color: passwordTextField.showPassword ? app.accentColor : keyColor + MouseArea { + anchors.fill: parent + onClicked: passwordTextField.showPassword = !passwordTextField.showPassword + } + } + } + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("OK") + enabled: passwordTextField.displayText.length >= 8 + onClicked: { + networkManager.connectToWiFi(authPage.wirelessNetworkDevice.interface, authPage.wirelessAccessPoint.ssid, passwordTextField.text) + pageStack.pop(root); + } + } + } + } + } + + Component { + id: currentApPageComponent + Page { + id: currentApPage + header: GuhHeader { + text: qsTr("Current connection") + onBackPressed: pageStack.pop(); + } + + property WirelessNetworkDevice wirelessNetworkDevice: null + + GridLayout { + anchors { left: parent.left; top: parent.top; right: parent.right } + columns: 1 + + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("SSID") + subText: currentApPage.wirelessNetworkDevice.currentAccessPoint.ssid + progressive: false + } + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("MAC Address") + subText: currentApPage.wirelessNetworkDevice.currentAccessPoint.macAddress + progressive: false + } + MeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Signal strength") + subText: currentApPage.wirelessNetworkDevice.currentAccessPoint.signalStrength + progressive: false + } + + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Disconnect") + onClicked: { + networkManager.disconnectInterface(currentApPage.wirelessNetworkDevice.interface) + pageStack.pop(root); + } + } + } + } + } +} diff --git a/nymea-app/ui/system/SystemUpdatePage.qml b/nymea-app/ui/system/SystemUpdatePage.qml index c4b72b09..20641f56 100644 --- a/nymea-app/ui/system/SystemUpdatePage.qml +++ b/nymea-app/ui/system/SystemUpdatePage.qml @@ -265,7 +265,7 @@ Page { property Package pkg: null header: GuhHeader { - text: qsTr("Package inforation") + text: qsTr("Package information") onBackPressed: pageStack.pop() }