Commit 484c86a3 authored by Arjen Hiemstra's avatar Arjen Hiemstra
Browse files

Introduce a plugin that exposes network devices and their sensors

It is set up to be able to handle different backends, though for the
moment only the NetworkManager backend is functional.
parent 90a2314a
......@@ -39,6 +39,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
NewStuff
Notifications
WindowSystem
NetworkManagerQt
)
find_package(KSysGuard REQUIRED)
......
......@@ -2,3 +2,4 @@ add_definitions(-DTRANSLATION_DOMAIN=\"ksysguard_plugins_global\")
add_subdirectory(nvidia)
add_subdirectory(ksgrd)
add_subdirectory(osinfo)
add_subdirectory(network)
set(KSYSGUARD_NETWORK_PLUGIN_SOURCES
NetworkPlugin.cpp
NetworkDevice.cpp
NetworkBackend.cpp
NetworkManagerBackend.cpp
)
add_library(ksysguard_globalplugin_network MODULE ${KSYSGUARD_NETWORK_PLUGIN_SOURCES})
target_link_libraries(ksysguard_globalplugin_network Qt5::Core Qt5::Gui Qt5::DBus KSysGuard::StatsBackend KF5::CoreAddons KF5::I18n KF5::NetworkManagerQt)
install(TARGETS ksysguard_globalplugin_network DESTINATION ${KDE_INSTALL_PLUGINDIR}/ksysguard)
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "NetworkBackend.h"
FileBackend::FileBackend(QObject* parent)
{
}
bool FileBackend::isSupported()
{
return false;
}
void FileBackend::start()
{
}
void FileBackend::stop()
{
}
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include <QObject>
#include <QHash>
class NetworkDevice;
class NetworkBackend : public QObject
{
Q_OBJECT
public:
NetworkBackend(QObject* parent = nullptr) : QObject(parent) { }
~NetworkBackend() override = default;
virtual bool isSupported() = 0;
virtual void start() = 0;
virtual void stop() = 0;
Q_SIGNAL void deviceAdded(NetworkDevice *device);
Q_SIGNAL void deviceRemoved(NetworkDevice *device);
};
class FileBackend : public NetworkBackend
{
Q_OBJECT
public:
FileBackend(QObject *parent = nullptr);
bool isSupported() override;
void start() override;
void stop() override;
};
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "NetworkDevice.h"
#include <KLocalizedString>
NetworkDevice::NetworkDevice(const QString &id, const QString &name)
: SensorObject(id, name, nullptr)
{
m_networkSensor = new SensorProperty(QStringLiteral("network"), i18nc("@title", "Network Name"), this);
m_networkSensor->setShortName(i18nc("@title Short of Network Name", "Name"));
m_signalSensor = new SensorProperty(QStringLiteral("signal"), i18nc("@title", "Signal Strength"), this);
m_signalSensor->setShortName(i18nc("@title Short of Signal Strength", "Signal"));
m_signalSensor->setUnit(KSysGuard::utils::UnitPercent);
m_signalSensor->setMin(0);
m_signalSensor->setMax(100);
m_ipv4Sensor = new SensorProperty(QStringLiteral("ipv4address"), i18nc("@title", "IPv4 Address"), this);
m_ipv4Sensor->setShortName(i18nc("@title Short of IPv4 Address", "IPv4"));
m_ipv6Sensor = new SensorProperty(QStringLiteral("ipv6address"), i18nc("@title", "IPv6 Address"), this);
m_ipv6Sensor->setShortName(i18nc("@title Short of IPv6 Address", "IPv6"));
m_downloadSensor = new SensorProperty(QStringLiteral("download"), i18nc("@title", "Download Rate"), this);
m_downloadSensor->setShortName(i18nc("@title Short for Download Rate", "Download"));
m_downloadSensor->setUnit(KSysGuard::utils::UnitByteRate);
m_uploadSensor = new SensorProperty(QStringLiteral("upload"), i18nc("@title", "Upload Rate"), this);
m_uploadSensor->setShortName(i18nc("@title Short for Upload Rate", "Upload"));
m_uploadSensor->setUnit(KSysGuard::utils::UnitByteRate);
m_totalDownloadSensor = new SensorProperty(QStringLiteral("totalDownload"), i18nc("@title", "Total Downloaded"), this);
m_totalDownloadSensor->setShortName(i18nc("@title Short for Total Downloaded", "Downloaded"));
m_totalDownloadSensor->setUnit(KSysGuard::utils::UnitByte);
m_totalUploadSensor = new SensorProperty(QStringLiteral("totalUpload"), i18nc("@title", "Total Uploaded"), this);
m_totalUploadSensor->setShortName(i18nc("@title Short for Total Uploaded", "Uploaded"));
m_totalUploadSensor->setUnit(KSysGuard::utils::UnitByte);
}
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include "SensorObject.h"
class NetworkDevice : public SensorObject
{
Q_OBJECT
public:
NetworkDevice(const QString& id, const QString& name);
~NetworkDevice() override = default;
virtual void update() = 0;
protected:
SensorProperty *m_networkSensor;
SensorProperty *m_signalSensor;
SensorProperty *m_ipv4Sensor;
SensorProperty *m_ipv6Sensor;
SensorProperty *m_downloadSensor;
SensorProperty *m_uploadSensor;
SensorProperty *m_totalDownloadSensor;
SensorProperty *m_totalUploadSensor;
};
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "NetworkManagerBackend.h"
#include <QDebug>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/WirelessDevice>
#include <NetworkManagerQt/ModemDevice>
NetworkManagerDevice::NetworkManagerDevice(const QString &id, QSharedPointer<NetworkManager::Device> device)
: NetworkDevice(id, id)
, m_device(device)
{
connect(m_device.data(), &NetworkManager::Device::activeConnectionChanged, this, &NetworkManagerDevice::update);
connect(m_device.data(), &NetworkManager::Device::ipV4ConfigChanged, this, &NetworkManagerDevice::update);
connect(m_device.data(), &NetworkManager::Device::ipV6ConfigChanged, this, &NetworkManagerDevice::update);
connect(this, &NetworkManagerDevice::nameChanged, this, [this]() {
m_networkSensor->setPrefix(name());
m_signalSensor->setPrefix(name());
m_ipv4Sensor->setPrefix(name());
m_ipv6Sensor->setPrefix(name());
m_downloadSensor->setPrefix(name());
m_uploadSensor->setPrefix(name());
m_totalDownloadSensor->setPrefix(name());
m_totalUploadSensor->setPrefix(name());
});
auto statistics = m_device->deviceStatistics();
statistics->setRefreshRateMs(2000);
connect(statistics.data(), &NetworkManager::DeviceStatistics::rxBytesChanged, this, [this](qulonglong bytes) {
auto previousValue = m_totalDownloadSensor->value().toULongLong();
if (previousValue > 0) {
m_downloadSensor->setValue(bytes - previousValue);
}
m_totalDownloadSensor->setValue(bytes);
});
connect(statistics.data(), &NetworkManager::DeviceStatistics::txBytesChanged, this, [this](qulonglong bytes) {
auto previousValue = m_totalUploadSensor->value().toULongLong();
if (previousValue > 0) {
m_uploadSensor->setValue(bytes - previousValue);
}
m_totalUploadSensor->setValue(bytes);
});
update();
}
NetworkManagerDevice::~NetworkManagerDevice()
{
}
void NetworkManagerDevice::update()
{
if (m_device->activeConnection()) {
setName(m_device->activeConnection()->connection()->name());
m_networkSensor->setValue(name());
} else {
setName(m_device->ipInterfaceName());
m_networkSensor->setValue(QString{});
}
if (m_device->ipV4Config().isValid()) {
m_ipv4Sensor->setValue(m_device->ipV4Config().addresses().at(0).ip().toString());
} else {
m_ipv4Sensor->setValue(QString{});
}
if (m_device->ipV6Config().isValid()) {
m_ipv6Sensor->setValue(m_device->ipV6Config().addresses().at(0).ip().toString());
} else {
m_ipv4Sensor->setValue(QString{});
}
if (m_device->type() == NetworkManager::Device::Wifi) {
updateWifi(m_device->as<NetworkManager::WirelessDevice>());
} else {
m_signalSensor->setValue(0);
}
}
void NetworkManagerDevice::updateWifi(NetworkManager::WirelessDevice* device)
{
auto activeConnectionName = device->activeConnection()->connection()->name();
const auto networks = device->networks();
auto itr = std::find_if(networks.begin(), networks.end(), [this, activeConnectionName](QSharedPointer<NetworkManager::WirelessNetwork> network) {
if (network->ssid() == activeConnectionName) {
return true;
}
return false;
});
if (itr != networks.end()) {
m_signalSensor->setValue((*itr)->signalStrength());
}
}
NetworkManagerBackend::NetworkManagerBackend(QObject* parent)
: NetworkBackend(parent)
{
}
NetworkManagerBackend::~NetworkManagerBackend()
{
qDeleteAll(m_devices);
}
bool NetworkManagerBackend::isSupported()
{
if (NetworkManager::status() == NetworkManager::Unknown) {
return false;
} else {
return true;
}
}
void NetworkManagerBackend::start()
{
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &NetworkManagerBackend::onDeviceAdded);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &NetworkManagerBackend::onDeviceRemoved);
const auto devices = NetworkManager::networkInterfaces();
for (auto device : devices) {
onDeviceAdded(device->uni());
}
}
void NetworkManagerBackend::stop()
{
NetworkManager::notifier()->disconnect(this);
}
void NetworkManagerBackend::onDeviceAdded(const QString& uni)
{
auto device = NetworkManager::findNetworkInterface(uni);
if (!device) {
return;
}
switch (device->type()) {
case NetworkManager::Device::Ethernet:
case NetworkManager::Device::Wifi:
case NetworkManager::Device::Bluetooth:
case NetworkManager::Device::Modem:
case NetworkManager::Device::Adsl:
break;
default:
// Non-hardware devices, ignore them.
return;
}
auto nmDevice = new NetworkManagerDevice(device->ipInterfaceName(), device);
m_devices.insert(uni, nmDevice);
Q_EMIT deviceAdded(nmDevice);
}
void NetworkManagerBackend::onDeviceRemoved(const QString& uni)
{
if (!m_devices.contains(uni)) {
return;
}
auto device = m_devices.take(uni);
Q_EMIT deviceRemoved(device);
delete device;
}
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include <QHash>
#include "NetworkBackend.h"
#include "NetworkDevice.h"
namespace NetworkManager
{
class Device;
class WirelessDevice;
}
class NetworkManagerDevice : public NetworkDevice
{
public:
NetworkManagerDevice(const QString &id, QSharedPointer<NetworkManager::Device> device);
~NetworkManagerDevice() override;
void update() override;
private:
void updateWifi(NetworkManager::WirelessDevice *device);
QSharedPointer<NetworkManager::Device> m_device;
};
class NetworkManagerBackend : public NetworkBackend
{
Q_OBJECT
public:
NetworkManagerBackend(QObject *parent = nullptr);
~NetworkManagerBackend() override;
bool isSupported() override;
void start() override;
void stop() override;
private:
void onDeviceAdded(const QString &uni);
void onDeviceRemoved(const QString &uni);
QHash<QString, NetworkManagerDevice *> m_devices;
};
/*
Copyright (c) 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "NetworkPlugin.h"
#include <QDebug>
#include <KLocalizedString>
#include <KPluginFactory>
#include <SensorContainer.h>
#include "NetworkDevice.h"
#include "NetworkManagerBackend.h"
class NetworkPrivate
{
public:
SensorContainer *container = nullptr;
NetworkBackend *backend = nullptr;
QVector<NetworkDevice *> devices;
};
NetworkPlugin::NetworkPlugin(QObject *parent, const QVariantList &args)
: SensorPlugin(parent, args)
, d(std::make_unique<NetworkPrivate>())
{
d->container = new SensorContainer(QStringLiteral("network_new"), i18nc("@title", "Network Devices"), this);
d->backend = new NetworkManagerBackend(this);
if (!d->backend->isSupported()) {
delete d->backend;
d->backend = new FileBackend(this);
if (!d->backend->isSupported()) {
qWarning() << "Unable to start backend, network information not available.";
return;
}
}
connect(d->backend, &NetworkBackend::deviceAdded, this, &NetworkPlugin::onDeviceAdded);
connect(d->backend, &NetworkBackend::deviceRemoved, this, &NetworkPlugin::onDeviceRemoved);
d->backend->start();
}
void NetworkPlugin::onDeviceAdded(NetworkDevice *device)
{
qDebug() << device->id() << device->name() << device->path();
d->container->addObject(device);
}
void NetworkPlugin::onDeviceRemoved(NetworkDevice *device)
{
d->container->removeObject(device);
}
NetworkPlugin::~NetworkPlugin() = default;
K_PLUGIN_CLASS_WITH_JSON(NetworkPlugin, "metadata.json")
#include "NetworkPlugin.moc"
/*
* SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include "SensorPlugin.h"
class NetworkPrivate;
class NetworkDevice;
class NetworkPlugin : public SensorPlugin
{
Q_OBJECT
public:
NetworkPlugin(QObject *parent, const QVariantList &args);
~NetworkPlugin() override;
QString providerName() const override
{
return QStringLiteral("network");
}
void onDeviceAdded(NetworkDevice *device);
void onDeviceRemoved(NetworkDevice *device);
private:
std::unique_ptr<NetworkPrivate> d;
};
{
"providerName": "network"
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment