Implement network management

This commit is contained in:
Michael Zanetti 2019-05-24 03:19:58 +02:00
parent be28bb2b56
commit d78b12e24e
26 changed files with 1203 additions and 25 deletions

View File

@ -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 <QMetaEnum>
#include <QJsonDocument>
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 &params)
{
qDebug() << "NetworkManager reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
QVariantMap statusMap = params.value("params").toMap().value("status").toMap();
QMetaEnum stateEnum = QMetaEnum::fromType<NetworkManager::NetworkManagerState>();
NetworkManagerState state = static_cast<NetworkManager::NetworkManagerState>(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 &params)
{
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<NetworkDevice::NetworkDeviceState>();
device->setState(static_cast<NetworkDevice::NetworkDeviceState>(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<NetworkDevice::NetworkDeviceState>();
device->setState(static_cast<NetworkDevice::NetworkDeviceState>(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 &params)
{
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 &params)
{
qDebug() << "connect to wifi reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
}
void NetworkManager::disconnectReply(const QVariantMap &params)
{
qDebug() << "disconnect reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
}
void NetworkManager::enableNetworkingReply(const QVariantMap &params)
{
qDebug() << "enable networking reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
}
void NetworkManager::notificationReceived(const QVariantMap &params)
{
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<NetworkDevice::NetworkDeviceState>();
device->setState(static_cast<NetworkDevice::NetworkDeviceState>(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<NetworkManager::NetworkManagerState>();
NetworkManagerState state = static_cast<NetworkManager::NetworkManagerState>(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));
}
}

View File

@ -0,0 +1,86 @@
#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H
#include <QObject>
#include <QHash>
#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 &params);
void getDevicesReply(const QVariantMap &params);
void getAccessPointsReply(const QVariantMap &params);
void connectToWiFiReply(const QVariantMap &params);
void disconnectReply(const QVariantMap &params);
void enableNetworkingReply(const QVariantMap &params);
void notificationReceived(const QVariantMap &params);
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<int, QString> m_apRequests; // requestId, interface
};
#endif // NETWORKMANAGER_H

View File

@ -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();
}
}
}

View File

@ -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();

View File

@ -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 <QtQml/qqml.h>
@ -212,6 +215,14 @@ void registerQmlTypes() {
qmlRegisterUncreatableType<Repositories>(uri, 1, 0, "Repositories", "Get it from SystemController");
qmlRegisterUncreatableType<Repository>(uri, 1, 0, "Repository", "Get it from Repositories");
qmlRegisterType<PackagesFilterModel>(uri, 1, 0, "PackagesFilterModel");
qmlRegisterUncreatableType<NetworkManager>(uri, 1, 0, "NetworkManager", "Get it from Engine");
qmlRegisterUncreatableType<NetworkDevices>(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager");
qmlRegisterUncreatableType<WiredNetworkDevices>(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager");
qmlRegisterUncreatableType<WirelessNetworkDevices>(uri, 1, 0, "WirelessNetworkDevices", "Get it from NetworkManager");
qmlRegisterUncreatableType<NetworkDevice>(uri, 1, 0, "NetworkDevice", "Get it from NetworkDevices");
qmlRegisterUncreatableType<WiredNetworkDevice>(uri, 1, 0, "WiredNetworkDevice", "Get it from NetworkDevices");
qmlRegisterUncreatableType<WirelessNetworkDevice>(uri, 1, 0, "WirelessNetworkDevice", "Get it from NetworkDevices");
}
#endif // LIBNYMEAAPPCORE_H

View File

@ -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 \

View File

@ -22,8 +22,8 @@
#include "wirelessaccesspointsproxy.h"
#include "wirelessaccesspoint.h"
#include "wirelessaccesspoints.h"
#include "types/wirelessaccesspoint.h"
#include "types/wirelessaccesspoints.h"
#include <QDebug>

View File

@ -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 <QJsonDocument>

View File

@ -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 \

View File

@ -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;
}

View File

@ -0,0 +1,91 @@
#ifndef NETWORKDEVICE_H
#define NETWORKDEVICE_H
#include <QObject>
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

View File

@ -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<int, QByteArray> NetworkDevices::roleNames() const
{
QHash<int, QByteArray> 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<WiredNetworkDevice*>(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<WiredNetworkDevice*>(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<int, QByteArray> WiredNetworkDevices::roleNames() const
{
QHash<int, QByteArray> roles = NetworkDevices::roleNames();
roles.insert(RolePluggedIn, "pluggedIn");
return roles;
}
WirelessNetworkDevices::WirelessNetworkDevices(QObject *parent):
NetworkDevices (parent)
{
}
#include <QDebug>
WirelessNetworkDevice *WirelessNetworkDevices::getWirelessNetworkDevice(const QString &interface)
{
return dynamic_cast<WirelessNetworkDevice*>(NetworkDevices::getNetworkDevice(interface));
}

View File

@ -0,0 +1,71 @@
#ifndef NETWORKDEVICES_H
#define NETWORKDEVICES_H
#include <QAbstractListModel>
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<int, QByteArray> 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<NetworkDevice*> 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<int, QByteArray> 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

View File

@ -183,5 +183,6 @@
<file>ui/system/SystemUpdatePage.qml</file>
<file>ui/components/UpdateRunningOverlay.qml</file>
<file>ui/connection/SetupWizard.qml</file>
<file>ui/system/NetworkSettingsPage.qml</file>
</qresource>
</RCC>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()
}

View File

@ -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"

View File

@ -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);
}
}
}
}
}
}

View File

@ -265,7 +265,7 @@ Page {
property Package pkg: null
header: GuhHeader {
text: qsTr("Package inforation")
text: qsTr("Package information")
onBackPressed: pageStack.pop()
}