File: power.cpp

package info (click to toggle)
ksystemstats 6.5.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,528 kB
  • sloc: cpp: 4,881; makefile: 6; sh: 1
file content (141 lines) | stat: -rw-r--r-- 6,627 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
    SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>

    SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/

#include "power.h"

#include <KLocalizedString>
#include <KPluginFactory>
#include <Solid/Device>
#include <Solid/DeviceNotifier>
#include <Solid/Battery>

#include <systemstats/AggregateSensor.h>
#include <systemstats/SensorContainer.h>
#include <systemstats/SensorObject.h>
#include <systemstats/SensorProperty.h>

K_PLUGIN_CLASS_WITH_JSON(PowerPlugin, "metadata.json")

QString idHelper(const Solid::Device battery)
{
    const QString serial = battery.as<Solid::Battery>()->serial();
    if (!serial.isEmpty()) {
        return serial;
    }
    return battery.udi().mid(battery.udi().lastIndexOf(QLatin1Char('/')) + 1);
}

class Battery : public KSysGuard::SensorObject {
public:
    Battery(const Solid::Device &device, const QString &name, KSysGuard::SensorContainer *parent);
};

Battery::Battery(const Solid::Device &device, const QString &name, KSysGuard::SensorContainer *parent)
    : SensorObject(idHelper(device), name, parent)
{
    auto n = new KSysGuard::SensorProperty("name", i18nc("@title", "Name"), name, this);
    n->setVariantType(QVariant::String);

    const auto * const battery = device.as<Solid::Battery>();

    auto designCapacity = new KSysGuard::SensorProperty("design", i18nc("@title", "Design Capacity"), battery->energyFullDesign(), this);
    designCapacity->setShortName(i18nc("@title", "Design Capacity"));
    designCapacity->setPrefix(name);
    designCapacity->setDescription(i18n("Amount of energy that the Battery was designed to hold"));
    designCapacity->setUnit(KSysGuard::UnitWattHour);
    designCapacity->setVariantType(QVariant::Double);;
    designCapacity->setMin(battery->energyFullDesign());
    designCapacity->setMax(battery->energyFullDesign());

    auto currentCapacity = new KSysGuard::SensorProperty("capacity", i18nc("@title", "Current Capacity"), battery->energyFull(), this);
    currentCapacity->setShortName(i18nc("@title", "Current Capacity"));
    currentCapacity->setPrefix(name);
    currentCapacity->setDescription(i18n("Amount of energy that the battery can currently hold"));
    currentCapacity->setUnit(KSysGuard::UnitWattHour);
    currentCapacity->setVariantType(QVariant::Double);
    currentCapacity->setMax(designCapacity);
    connect(battery, &Solid::Battery::energyFullChanged, currentCapacity, &KSysGuard::SensorProperty::setValue);

    auto health = new KSysGuard::SensorProperty("health", i18nc("@title", "Health"), battery->capacity(), this);
    health->setShortName(i18nc("@title", "Health"));
    health->setPrefix(name);
    health->setDescription(i18n("Percentage of the design capacity that the battery can hold"));
    health->setUnit(KSysGuard::UnitPercent);
    health->setVariantType(QVariant::Int);
    health->setMax(100);
    connect(battery, &Solid::Battery::capacityChanged, health, &KSysGuard::SensorProperty::setValue);

    auto charge = new KSysGuard::SensorProperty("charge", i18nc("@title", "Charge"), battery->energy(), this);
    charge->setShortName(i18nc("@title", "Current Capacity"));
    charge->setPrefix(name);
    charge->setDescription(i18n("Amount of energy that the battery is currently holding"));
    charge->setUnit(KSysGuard::UnitWattHour);
    charge->setVariantType(QVariant::Double);
    charge->setMax(currentCapacity);
    connect(battery, &Solid::Battery::energyChanged, charge, &KSysGuard::SensorProperty::setValue);

    auto chargePercent = new KSysGuard::SensorProperty("chargePercentage", i18nc("@title", "Charge Percentage"), battery->chargePercent(), this);
    chargePercent->setShortName(i18nc("@title", "Charge Percentage"));
    chargePercent->setPrefix(name);
    chargePercent->setDescription(i18n("Percentage of the current capacity that the battery is currently holding"));
    chargePercent->setUnit(KSysGuard::UnitPercent);
    chargePercent->setVariantType(QVariant::Int);
    chargePercent->setMax(100);
    connect(battery, &Solid::Battery::chargePercentChanged, chargePercent, &KSysGuard::SensorProperty::setValue);

    // Solid reports negative of charging and positive for discharging
    auto chargeRate = new KSysGuard::SensorProperty("chargeRate", i18nc("@title", "Charging Rate"), 0, this);
    chargeRate->setShortName(i18nc("@title", "Charging  Rate"));
    chargeRate->setPrefix(name);
    chargeRate->setDescription(i18n("Power that the battery is being charged with (positive) or discharged (negative)"));
    chargeRate->setUnit(KSysGuard::UnitWatt);
    chargeRate->setVariantType(QVariant::Double);
    chargeRate->setValue(-battery->energyRate());
    connect(battery, &Solid::Battery::energyRateChanged, chargeRate, [battery, chargeRate] (double rate) {
        // According to the documentation, energyRate should be positive if discharging
        // and negative if charging. However, on some systems this turns out to be
        // incorrect and we get positive both when charging and discharging. So ensure
        // we have the right sign here by checking state.
        if (battery->chargeState() == Solid::Battery::Charging) {
            chargeRate->setValue(std::abs(rate));
        } else if (battery->chargeState() == Solid::Battery::Discharging) {
            chargeRate->setValue(-std::abs(rate));
        } else {
            chargeRate->setValue(rate);
        }
    });

}

PowerPlugin::PowerPlugin(QObject *parent, const QVariantList &args)
    : SensorPlugin(parent, args)
{
    m_container = new KSysGuard::SensorContainer("power", i18nc("@title", "Power"), this);
    const auto batteries = Solid::Device::listFromType(Solid::DeviceInterface::Battery);

    for (const auto &device : batteries) {
        auto battery = new Battery(device, device.displayName(), m_container);
        m_batteriesByUdi.insert(device.udi(), battery);
    }

    connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded, this, [this] (const QString &udi) {
        const Solid::Device device(udi);
        if (device.isDeviceInterface(Solid::DeviceInterface::Battery)) {
            auto battery = new Battery(device, device.displayName(), m_container);
            m_batteriesByUdi.insert(udi, battery);
        }
    });
    connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved, this, [this] (const QString &udi) {
        if (m_batteriesByUdi.contains(udi)) {
            m_container->removeObject(m_batteriesByUdi[udi]);
            m_batteriesByUdi.remove(udi);
        }
    });
}

#include "power.moc"

#include "moc_power.cpp"