Commit ff30d69e authored by David Redondo's avatar David Redondo 🏎
Browse files

Add new lmsensors plugin

The names are still not good because that is what we get from libsensors.
But it now also handles minimium and maximum if possible.
To not show the same sensors that we already handle in other plugins,
I use a simple blacklist for now for the ones we want to exclude.
parent 679deb4b
......@@ -15,3 +15,7 @@ add_subdirectory(memory)
if(UDev_FOUND)
add_subdirectory(gpu)
endif()
if(SENSORS_FOUND)
add_subdirectory(lmsensors)
endif()
# SPDX-License-Identifier: BSD-2-Clause
# SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
add_library(ksysguard_plugin_lmsensors MODULE lmsensors.cpp SensorsFeatureSensor.cpp)
target_include_directories(ksysguard_plugin_lmsensors PRIVATE ${SENSORS_INCLUDE_DIR})
target_link_libraries(ksysguard_plugin_lmsensors PRIVATE Qt5::Core KF5::CoreAddons KF5::I18n KSysGuard::SystemStats ${SENSORS_LIBRARIES})
install(TARGETS ksysguard_plugin_lmsensors DESTINATION ${KDE_INSTALL_PLUGINDIR}/ksysguard)
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "SensorsFeatureSensor.h"
#include <systemstats/SensorObject.h>
#include <KLocalizedString>
#include <QRegularExpression>
#include <sensors/sensors.h>
static QString prettyName(const sensors_chip_name * const chipName, const sensors_feature * const feature)
{
std::unique_ptr<char, decltype(&free)> label(sensors_get_label(chipName, feature), &free);
const QString labelString = QString::fromUtf8(label.get());
switch (feature->type) {
case SENSORS_FEATURE_IN:
{
static QRegularExpression inRegex(QStringLiteral("in(\\d+)"));
auto inMatch = inRegex.match(labelString);
if (inMatch.hasMatch()) {
return i18nc("@title %1 is a number", "Voltage %1", inMatch.captured(1));
}
break;
}
case SENSORS_FEATURE_FAN:
{
static QRegularExpression fanRegex(QStringLiteral("fan(\\d+)"));
auto fanMatch = fanRegex.match(labelString);
if (fanMatch.hasMatch()) {
return i18nc("@title %1 is a number", "Fan %1", fanMatch.captured(1));
}
break;
}
case SENSORS_FEATURE_TEMP:
{
static QRegularExpression tempRegex(QStringLiteral("temp(\\d+)"));
auto tempMatch = tempRegex.match(labelString);
if (tempMatch.hasMatch()) {
return i18nc("@title %1 is a number", "Temperature %1", tempMatch.captured(1));
}
break;
}
default:
break;
}
return labelString;
}
SensorsFeatureSensor* makeSensorsFeatureSensor(const sensors_chip_name * const chipName,
const sensors_feature * const feature,
KSysGuard::SensorObject *parent)
{
if (parent->sensor(QString::fromUtf8(feature->name))) {
return nullptr;
}
const sensors_subfeature * valueFeature = nullptr;
double minimum = 0;
double maximum = 0;
KSysGuard::Unit unit;
auto getValueOfFirstExisting = [chipName, feature] (std::initializer_list<sensors_subfeature_type> subfeatureTypes) {
double value;
for (auto subfeatureType : subfeatureTypes) {
const sensors_subfeature * const subfeature = sensors_get_subfeature(chipName, feature, subfeatureType);
if (subfeature && sensors_get_value(chipName, subfeature->number, &value) == 0) {
return value;
}
}
return 0.0;
};
switch (feature->type) {
case SENSORS_FEATURE_IN:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_IN_INPUT);
unit = KSysGuard::UnitVolt;
minimum = getValueOfFirstExisting({SENSORS_SUBFEATURE_IN_LCRIT, SENSORS_SUBFEATURE_IN_MIN});
maximum = getValueOfFirstExisting({SENSORS_SUBFEATURE_IN_CRIT, SENSORS_SUBFEATURE_IN_MAX});
break;
case SENSORS_FEATURE_FAN:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_FAN_INPUT);
unit = KSysGuard::UnitRpm;
minimum = getValueOfFirstExisting({SENSORS_SUBFEATURE_FAN_MIN});
maximum = getValueOfFirstExisting({SENSORS_SUBFEATURE_FAN_MAX});
break;
case SENSORS_FEATURE_TEMP:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
unit = KSysGuard::UnitCelsius;
minimum = getValueOfFirstExisting({SENSORS_SUBFEATURE_TEMP_LCRIT, SENSORS_SUBFEATURE_TEMP_MIN});
maximum = getValueOfFirstExisting({SENSORS_SUBFEATURE_TEMP_EMERGENCY, SENSORS_SUBFEATURE_TEMP_CRIT, SENSORS_SUBFEATURE_TEMP_MAX});
break;
case SENSORS_FEATURE_POWER:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_POWER_INPUT);
unit = KSysGuard::UnitWatt;
maximum = getValueOfFirstExisting({SENSORS_SUBFEATURE_POWER_CRIT, SENSORS_SUBFEATURE_POWER_MAX});
break;
case SENSORS_FEATURE_ENERGY:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_ENERGY_INPUT);
unit = KSysGuard::UnitWattHour;
break;
case SENSORS_FEATURE_CURR:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_CURR_INPUT);
unit = KSysGuard::UnitAmpere;
minimum = getValueOfFirstExisting({SENSORS_SUBFEATURE_CURR_LCRIT, SENSORS_SUBFEATURE_CURR_MIN});
maximum = getValueOfFirstExisting({SENSORS_SUBFEATURE_CURR_CRIT, SENSORS_SUBFEATURE_CURR_MAX});
break;
case SENSORS_FEATURE_HUMIDITY:
valueFeature = sensors_get_subfeature(chipName, feature, SENSORS_SUBFEATURE_HUMIDITY_INPUT);
unit = KSysGuard::UnitPercent;
break;
default:
return nullptr;
}
auto sensor = new SensorsFeatureSensor(QString::fromUtf8(feature->name), chipName, valueFeature, parent);
sensor->setName(prettyName(chipName, feature));
sensor->setUnit(unit);
sensor->setMax(maximum);
sensor->setMin(minimum);
return sensor;
}
SensorsFeatureSensor::SensorsFeatureSensor(const QString &id, const sensors_chip_name * const chipName,
const sensors_subfeature * const valueFeature, KSysGuard::SensorObject *parent)
: SensorProperty(id, parent)
, m_chipName(chipName)
, m_valueFeature(valueFeature)
{
}
void SensorsFeatureSensor::update()
{
double value;
if(sensors_get_value(m_chipName, m_valueFeature->number, &value) < 0) {
setValue(QVariant());
}
setValue(value);
}
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef SENSORSFEATURESENSOR_H
#define SENSORSFEATURESENSOR_H
#include <systemstats/SensorProperty.h>
struct sensors_chip_name;
struct sensors_feature;
struct sensors_subfeature;
class SensorsFeatureSensor : public KSysGuard::SensorProperty
{
Q_OBJECT
public:
void update() override;
private:
SensorsFeatureSensor(const QString &id, const sensors_chip_name * const chipName,
const sensors_subfeature * const valueFeature, KSysGuard::SensorObject *parent);
const sensors_chip_name * m_chipName;
const sensors_subfeature * m_valueFeature;
friend SensorsFeatureSensor* makeSensorsFeatureSensor(const sensors_chip_name * const, const sensors_feature * const, KSysGuard::SensorObject*);
};
SensorsFeatureSensor* makeSensorsFeatureSensor(const sensors_chip_name * const chipName,
const sensors_feature * const feature,
KSysGuard::SensorObject *parent);
#endif
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "lmsensors.h"
#include "SensorsFeatureSensor.h"
#include <systemstats/SensorContainer.h>
#include <systemstats/SensorObject.h>
#include <KLocalizedString>
#include <KPluginFactory>
#include <sensors/sensors.h>
LmSensorsPlugin::LmSensorsPlugin(QObject *parent, const QVariantList &args)
: KSysGuard::SensorPlugin(parent, args)
{
auto container = new KSysGuard::SensorContainer(QStringLiteral("lmsensors"), i18n( "Hardware Sensors" ), this);
if (sensors_init(nullptr) != 0) {
return;
}
const std::array<QByteArray, 3> blacklist{"coretemp","k10temp","amdgpu"}; //already handled by other plugins
int chipNumber = 0;
while (const sensors_chip_name * const chipName = sensors_get_detected_chips(nullptr, &chipNumber)) {
if (std::find(blacklist.cbegin(), blacklist.cend(), chipName->prefix) != blacklist.cend()) {
continue;
}
int requiredBytes = sensors_snprintf_chip_name(nullptr, 0, chipName) + 1;
QByteArray name;
name.resize(requiredBytes);
sensors_snprintf_chip_name(name.data(), name.size(), chipName);
const QString nameString = QString::fromUtf8(name);
KSysGuard::SensorObject *sensorObject = container->object(nameString);
if (!sensorObject) {
sensorObject = new KSysGuard::SensorObject(nameString, nameString, container);
}
int featureNumber = 0;
while (const sensors_feature * const feature = sensors_get_features(chipName, &featureNumber)) {
if (auto sensor = makeSensorsFeatureSensor(chipName, feature, sensorObject)) {
m_sensors.push_back(sensor);
}
}
}
}
LmSensorsPlugin::~LmSensorsPlugin()
{
sensors_cleanup();
}
QString LmSensorsPlugin::providerName() const
{
return QStringLiteral("lmsensors");
}
void LmSensorsPlugin::update()
{
for (auto sensor : qAsConst(m_sensors)) {
sensor->update();
}
}
K_PLUGIN_CLASS_WITH_JSON(LmSensorsPlugin, "metadata.json")
#include "lmsensors.moc"
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef LMSENSORS_H
#define LMSENSORS_H
#include <systemstats/SensorPlugin.h>
class SensorsFeatureSensor;
class LmSensorsPlugin : public KSysGuard::SensorPlugin
{
Q_OBJECT
public:
LmSensorsPlugin(QObject *parent, const QVariantList &args);
~LmSensorsPlugin() override;
QString providerName() const override;
void update() override;
private:
QVector<SensorsFeatureSensor*> m_sensors;
};
#endif
{
"providerName": "lmsensors"
}
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