diff --git a/sensors/Sensor.cpp b/sensors/Sensor.cpp index 0dddca0..371564a 100644 --- a/sensors/Sensor.cpp +++ b/sensors/Sensor.cpp @@ -1,249 +1,249 @@ /* Copyright (C) 2019 Vlad Zagorodniy Copyright (C) 2020 Arjen Hiemstra 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 #include "Sensor.h" #include "formatter/Formatter.h" #include "SensorInfo_p.h" #include "SensorDaemonInterface_p.h" using namespace KSysGuard; class Q_DECL_HIDDEN Sensor::Private { public: SensorInfo sensorInfo; Sensor::Status status = Sensor::Status::Unknown; QVariant value; bool usedByQml = false; bool componentComplete = false; QString pendingId; QString id; bool enabled = true; }; Sensor::Sensor(QObject *parent) : Sensor(QString{}, parent) { } Sensor::Sensor(const QString &id, QObject *parent) : QObject(parent) , d(new Private()) { connect(this, &Sensor::statusChanged, this, &Sensor::valueChanged); connect(this, &Sensor::statusChanged, this, &Sensor::metaDataChanged); connect(this, &Sensor::enabledChanged, this, &Sensor::onEnabledChanged); setSensorId(id); } bool Sensor::event(QEvent *event) { if (event->type() == QEvent::ParentAboutToChange && parent()) { parent()->disconnect(this); } else if (event->type() == QEvent::ParentChange && parent()) { if(parent()->metaObject()->indexOfSignal("enabledChanged()") != -1) { connect(parent(), SIGNAL(enabledChanged()), this, SIGNAL(enabledChanged())); } } return QObject::event(event); } Sensor::~Sensor() { SensorDaemonInterface::instance()->unsubscribe(d->id); } QString Sensor::sensorId() const { return d->id; } void Sensor::setSensorId(const QString &id) { if (id == d->id) { return; } if (d->usedByQml && !d->componentComplete) { d->pendingId = id; return; } d->id = id; d->status = Sensor::Status::Loading; if (!id.isEmpty()) { SensorDaemonInterface::instance()->requestMetaData(id); connect(SensorDaemonInterface::instance(), &SensorDaemonInterface::metaDataChanged, this, &Sensor::onMetaDataChanged, Qt::UniqueConnection); } if (enabled()) { SensorDaemonInterface::instance()->subscribe(id); SensorDaemonInterface::instance()->requestValue(id); connect(SensorDaemonInterface::instance(), &SensorDaemonInterface::valueChanged, this, &Sensor::onValueChanged, Qt::UniqueConnection); } Q_EMIT sensorIdChanged(); Q_EMIT statusChanged(); } Sensor::Status Sensor::status() const { return d->status; } QString Sensor::name() const { return d->sensorInfo.name; } QString Sensor::shortName() const { if (d->sensorInfo.shortName.isEmpty()) { return d->sensorInfo.name; } return d->sensorInfo.name; } QString Sensor::description() const { return d->sensorInfo.description; } Unit Sensor::unit() const { return d->sensorInfo.unit; } qreal Sensor::minimum() const { return d->sensorInfo.min; } qreal Sensor::maximum() const { return d->sensorInfo.max; } QVariant::Type Sensor::type() const { return d->sensorInfo.variantType; } QVariant Sensor::value() const { if (!d->value.isValid()) { - return QVariant{d->sensorInfo.type}; + return QVariant{d->sensorInfo.variantType}; } return d->value; } QString Sensor::formattedValue() const { return Formatter::formatValue(value(), unit(), MetricPrefixAutoAdjust, FormatOptionShowNull); } bool Sensor::enabled() const { if (d->enabled && parent()) { auto parentEnabled = parent()->property("enabled"); if (parentEnabled.isValid()) { return parentEnabled.toBool(); } } return d->enabled; } void Sensor::setEnabled(bool newEnabled) { if (newEnabled == d->enabled) { return; } d->enabled = newEnabled; Q_EMIT enabledChanged(); } void Sensor::classBegin() { d->usedByQml = true; } void Sensor::componentComplete() { d->componentComplete = true; setSensorId(d->pendingId); if(parent() && parent()->metaObject()->indexOfSignal("enabledChanged()") != -1) { connect(parent(), SIGNAL(enabledChanged()), this, SIGNAL(enabledChanged())); } } void Sensor::onMetaDataChanged(const QString &sensorId, const SensorInfo &metaData) { if (sensorId != d->id || !enabled()) { return; } d->sensorInfo = metaData; if (d->status == Sensor::Status::Loading) { d->status = Sensor::Status::Ready; Q_EMIT statusChanged(); } Q_EMIT metaDataChanged(); } void Sensor::onValueChanged(const QString &sensorId, const QVariant &value) { if (sensorId != d->id || !enabled()) { return; } d->value = value; Q_EMIT valueChanged(); } void Sensor::onEnabledChanged() { if (enabled()) { SensorDaemonInterface::instance()->subscribe(d->id); // Force an update of metadata and data, since that may have changed // while we were disabled. SensorDaemonInterface::instance()->requestMetaData(d->id); SensorDaemonInterface::instance()->requestValue(d->id); } else { SensorDaemonInterface::instance()->unsubscribe(d->id); } } diff --git a/sensors/SensorDaemonInterface.cpp b/sensors/SensorDaemonInterface.cpp index d37a247..01da0b8 100644 --- a/sensors/SensorDaemonInterface.cpp +++ b/sensors/SensorDaemonInterface.cpp @@ -1,145 +1,145 @@ /* Copyright (C) 2020 Arjen Hiemstra 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 "SensorDaemonInterface_p.h" #include #include "ksysguarddaemon.h" using namespace KSysGuard; class SensorDaemonInterface::Private { public: std::unique_ptr dbusInterface; static const QString SensorServiceName; static const QString SensorPath; }; const QString SensorDaemonInterface::Private::SensorServiceName = QStringLiteral("org.kde.kstats"); const QString SensorDaemonInterface::Private::SensorPath = QStringLiteral("/"); SensorDaemonInterface::SensorDaemonInterface(QObject *parent) : QObject(parent), d(new Private) { qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); d->dbusInterface = std::make_unique(Private::SensorServiceName, Private::SensorPath, QDBusConnection::sessionBus()); connect(d->dbusInterface.get(), &org::kde::KSysGuardDaemon::sensorMetaDataChanged, this, &SensorDaemonInterface::onMetaDataChanged); connect(d->dbusInterface.get(), &org::kde::KSysGuardDaemon::newSensorData, this, &SensorDaemonInterface::onValueChanged); connect(d->dbusInterface.get(), &org::kde::KSysGuardDaemon::sensorAdded, this, &SensorDaemonInterface::sensorAdded); connect(d->dbusInterface.get(), &org::kde::KSysGuardDaemon::sensorRemoved, this, &SensorDaemonInterface::sensorRemoved); } SensorDaemonInterface::~SensorDaemonInterface() { } void SensorDaemonInterface::requestMetaData(const QString &sensorId) { requestMetaData(QStringList{sensorId}); } void SensorDaemonInterface::requestMetaData(const QStringList& sensorIds) { auto watcher = new QDBusPendingCallWatcher{d->dbusInterface->sensors(sensorIds), this}; connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [=](QDBusPendingCallWatcher *self) { self->deleteLater(); const QDBusPendingReply reply = *self; if (reply.isError()) { return; } const auto infos = reply.value(); for (auto itr = infos.begin(); itr != infos.end(); ++itr) { Q_EMIT metaDataChanged(itr.key(), itr.value()); } }); } void SensorDaemonInterface::requestValue(const QString &sensorId) { auto watcher = new QDBusPendingCallWatcher{d->dbusInterface->sensorData({sensorId}), this}; connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [=](QDBusPendingCallWatcher *self) { self->deleteLater(); const QDBusPendingReply reply = *self; if (reply.isError()) { return; } const auto allData = reply.value(); for (auto data : allData) { Q_EMIT valueChanged(data.attribute, data.payload); } }); } QDBusPendingCallWatcher *SensorDaemonInterface::allSensors() const { return new QDBusPendingCallWatcher{d->dbusInterface->allSensors()}; } void SensorDaemonInterface::subscribe(const QString &sensorId) { subscribe(QStringList{sensorId}); } void KSysGuard::SensorDaemonInterface::subscribe(const QStringList& sensorIds) { d->dbusInterface->subscribe(sensorIds); } void SensorDaemonInterface::unsubscribe(const QString &sensorId) { unsubscribe(QStringList{sensorId}); } void KSysGuard::SensorDaemonInterface::unsubscribe(const QStringList& sensorIds) { d->dbusInterface->unsubscribe(sensorIds); } SensorDaemonInterface *SensorDaemonInterface::instance() { static SensorDaemonInterface instance; return &instance; } void SensorDaemonInterface::onMetaDataChanged(const QHash& metaData) { for (auto itr = metaData.begin(); itr != metaData.end(); ++itr) { Q_EMIT metaDataChanged(itr.key(), itr.value()); } } -void SensorDaemonInterface::onValueChanged(const QStringList &, const SensorDataList &values, const QStringList &) +void SensorDaemonInterface::onValueChanged(const SensorDataList &values) { for (auto entry : values) { Q_EMIT valueChanged(entry.attribute, entry.payload); } } diff --git a/sensors/SensorDaemonInterface_p.h b/sensors/SensorDaemonInterface_p.h index 2befd0e..7b4178f 100644 --- a/sensors/SensorDaemonInterface_p.h +++ b/sensors/SensorDaemonInterface_p.h @@ -1,70 +1,70 @@ /* Copyright (C) 2020 Arjen Hiemstra 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. */ #pragma once #include #include #include "SensorInfo_p.h" class QDBusPendingCallWatcher; namespace KSysGuard { /** * Internal helper class to communicate with the daemon. * * This is mostly for convenience on top of the auto-generated KSysGuardDaemon * D-Bus interface. */ class SensorDaemonInterface : public QObject { Q_OBJECT public: SensorDaemonInterface(QObject *parent = nullptr); ~SensorDaemonInterface() override; void requestMetaData(const QString &sensorId); void requestMetaData(const QStringList &sensorIds); Q_SIGNAL void metaDataChanged(const QString &sensorId, const SensorInfo &info); void requestValue(const QString &sensorId); Q_SIGNAL void valueChanged(const QString &sensorId, const QVariant &value); QDBusPendingCallWatcher *allSensors() const; void subscribe(const QString &sensorId); void subscribe(const QStringList &sensorIds); void unsubscribe(const QString &sensorId); void unsubscribe(const QStringList &sensorIds); Q_SIGNAL void sensorAdded(const QString &sensorId); Q_SIGNAL void sensorRemoved(const QString &sensorId); static SensorDaemonInterface *instance(); private: void onMetaDataChanged(const QHash &metaData); - void onValueChanged(const QStringList &, const SensorDataList &values, const QStringList &); + void onValueChanged(const SensorDataList &values); class Private; const std::unique_ptr d; }; } diff --git a/sensors/SensorInfo_p.h b/sensors/SensorInfo_p.h index 988dc79..3250b64 100644 --- a/sensors/SensorInfo_p.h +++ b/sensors/SensorInfo_p.h @@ -1,133 +1,115 @@ /* Copyright (c) 2019 David Edmundson 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. */ #pragma once #include #include #include #include #include #include "formatter/Unit.h" namespace KSysGuard { //Data that is static for the lifespan of the sensor class SensorInfo { public: - enum Type { - Singular, - List - }; SensorInfo() = default; QString name; //translated? QString shortName; // translated QString description; // translated QVariant::Type variantType = QVariant::Invalid; KSysGuard::Unit unit = KSysGuard::UnitInvalid; //Both a format hint and implies data type (i.e double/string) qreal min = 0; qreal max = 0; - Type type = Singular; }; // this stuff could come from .desktop files (for the DBus case) or hardcoded (eg. for example nvidia-smi case) or come from current "ksysgrd monitors" class Q_DECL_EXPORT SensorData { public: SensorData() = default; - SensorData(const QDateTime &_timeStamp, const QString &_attribute, const QString &_entity, const QVariant &_payload) - : timestamp(_timeStamp) - , attribute(_attribute) - , entity(_entity) + SensorData(const QString &_attribute, const QVariant &_payload) + : attribute(_attribute) , payload(_payload) { } - QDateTime timestamp; QString attribute; - QString entity; QVariant payload; }; typedef QHash SensorInfoMap; typedef QList SensorDataList; inline QDBusArgument &operator<<(QDBusArgument &argument, const SensorInfo &s) { argument.beginStructure(); argument << s.name; argument << s.shortName; argument << s.description; argument << s.variantType; argument << s.unit; argument << s.min; argument << s.max; - argument << s.type; argument.endStructure(); return argument; } inline const QDBusArgument &operator>>(const QDBusArgument &argument, SensorInfo &s) { argument.beginStructure(); argument >> s.name; argument >> s.shortName; argument >> s.description; uint32_t t; argument >> t; s.variantType = static_cast(t); argument >> t; s.unit = static_cast(t); argument >> s.min; argument >> s.max; - argument >> t; - s.type = static_cast(t); argument.endStructure(); return argument; } inline QDBusArgument &operator<<(QDBusArgument &argument, const SensorData &s) { argument.beginStructure(); - argument << s.timestamp.toMSecsSinceEpoch(); argument << s.attribute; - argument << s.entity; argument << QDBusVariant(s.payload); argument.endStructure(); return argument; } inline const QDBusArgument &operator>>(const QDBusArgument &argument, SensorData &s) { argument.beginStructure(); - qint64 t; - argument >> t; - s.timestamp = QDateTime::fromMSecsSinceEpoch(t, Qt::UTC); argument >> s.attribute; - argument >> s.entity; argument >> s.payload; argument.endStructure(); return argument; } } // namespace KSysGuard Q_DECLARE_METATYPE(KSysGuard::SensorInfo); Q_DECLARE_METATYPE(KSysGuard::SensorData); Q_DECLARE_METATYPE(KSysGuard::SensorDataList); diff --git a/sensors/org.kde.KSysGuardDaemon.xml b/sensors/org.kde.KSysGuardDaemon.xml index db6f620..b242333 100644 --- a/sensors/org.kde.KSysGuardDaemon.xml +++ b/sensors/org.kde.KSysGuardDaemon.xml @@ -1,41 +1,39 @@ - - - - + + - +