File indexing completed on 2024-05-12 17:00:17
0001 /* 0002 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "power.h" 0008 0009 #include <KLocalizedString> 0010 #include <KPluginFactory> 0011 #include <Solid/Device> 0012 #include <Solid/DeviceNotifier> 0013 #include <Solid/Battery> 0014 0015 #include <systemstats/AggregateSensor.h> 0016 #include <systemstats/SensorContainer.h> 0017 #include <systemstats/SensorObject.h> 0018 #include <systemstats/SensorProperty.h> 0019 0020 K_PLUGIN_CLASS_WITH_JSON(PowerPlugin, "metadata.json") 0021 0022 QString idHelper(const Solid::Device battery) 0023 { 0024 const QString serial = battery.as<Solid::Battery>()->serial(); 0025 if (!serial.isEmpty()) { 0026 return serial; 0027 } 0028 return battery.udi().mid(battery.udi().lastIndexOf(QLatin1Char('/')) + 1); 0029 } 0030 0031 class Battery : public KSysGuard::SensorObject { 0032 public: 0033 Battery(const Solid::Device &device, const QString &name, KSysGuard::SensorContainer *parent); 0034 }; 0035 0036 Battery::Battery(const Solid::Device &device, const QString &name, KSysGuard::SensorContainer *parent) 0037 : SensorObject(idHelper(device), name, parent) 0038 { 0039 auto n = new KSysGuard::SensorProperty("name", i18nc("@title", "Name"), name, this); 0040 n->setVariantType(QVariant::String); 0041 0042 const auto * const battery = device.as<Solid::Battery>(); 0043 0044 auto designCapacity = new KSysGuard::SensorProperty("design", i18nc("@title", "Design Capacity"), battery->energyFullDesign(), this); 0045 designCapacity->setShortName(i18nc("@title", "Design Capacity")); 0046 designCapacity->setPrefix(name); 0047 designCapacity->setDescription(i18n("Amount of energy that the Battery was designed to hold")); 0048 designCapacity->setUnit(KSysGuard::UnitWattHour); 0049 designCapacity->setVariantType(QVariant::Double);; 0050 designCapacity->setMin(battery->energyFullDesign()); 0051 designCapacity->setMax(battery->energyFullDesign()); 0052 0053 auto currentCapacity = new KSysGuard::SensorProperty("capacity", i18nc("@title", "Current Capacity"), battery->energyFull(), this); 0054 currentCapacity->setShortName(i18nc("@title", "Current Capacity")); 0055 currentCapacity->setPrefix(name); 0056 currentCapacity->setDescription(i18n("Amount of energy that the battery can currently hold")); 0057 currentCapacity->setUnit(KSysGuard::UnitWattHour); 0058 currentCapacity->setVariantType(QVariant::Double); 0059 currentCapacity->setMax(designCapacity); 0060 connect(battery, &Solid::Battery::energyFullChanged, currentCapacity, &KSysGuard::SensorProperty::setValue); 0061 0062 auto health = new KSysGuard::SensorProperty("health", i18nc("@title", "Health"), battery->capacity(), this); 0063 health->setShortName(i18nc("@title", "Health")); 0064 health->setPrefix(name); 0065 health->setDescription(i18n("Percentage of the design capacity that the battery can hold")); 0066 health->setUnit(KSysGuard::UnitPercent); 0067 health->setVariantType(QVariant::Int); 0068 health->setMax(100); 0069 connect(battery, &Solid::Battery::capacityChanged, health, &KSysGuard::SensorProperty::setValue); 0070 0071 auto charge = new KSysGuard::SensorProperty("charge", i18nc("@title", "Charge"), battery->energy(), this); 0072 charge->setShortName(i18nc("@title", "Current Capacity")); 0073 charge->setPrefix(name); 0074 charge->setDescription(i18n("Amount of energy that the battery is currently holding")); 0075 charge->setUnit(KSysGuard::UnitWattHour); 0076 charge->setVariantType(QVariant::Double); 0077 charge->setMax(currentCapacity); 0078 connect(battery, &Solid::Battery::energyChanged, charge, &KSysGuard::SensorProperty::setValue); 0079 0080 auto chargePercent = new KSysGuard::SensorProperty("chargePercentage", i18nc("@title", "Charge Percentage"), battery->chargePercent(), this); 0081 chargePercent->setShortName(i18nc("@title", "Charge Percentage")); 0082 chargePercent->setPrefix(name); 0083 chargePercent->setDescription(i18n("Percentage of the current capacity that the battery is currently holding")); 0084 chargePercent->setUnit(KSysGuard::UnitPercent); 0085 chargePercent->setVariantType(QVariant::Int); 0086 chargePercent->setMax(100); 0087 connect(battery, &Solid::Battery::chargePercentChanged, chargePercent, &KSysGuard::SensorProperty::setValue); 0088 0089 // Solid reports negative of charging and positive for discharging 0090 auto chargeRate = new KSysGuard::SensorProperty("chargeRate", i18nc("@title", "Charging Rate"), 0, this); 0091 chargeRate->setShortName(i18nc("@title", "Charging Rate")); 0092 chargeRate->setPrefix(name); 0093 chargeRate->setDescription(i18n("Power that the battery is being charged with (positive) or discharged (negative)")); 0094 chargeRate->setUnit(KSysGuard::UnitWatt); 0095 chargeRate->setVariantType(QVariant::Double); 0096 chargeRate->setValue(-battery->energyRate()); 0097 connect(battery, &Solid::Battery::energyRateChanged, chargeRate, [chargeRate] (double rate) { 0098 chargeRate->setValue(-rate); 0099 }); 0100 0101 } 0102 0103 PowerPlugin::PowerPlugin(QObject *parent, const QVariantList &args) 0104 : SensorPlugin(parent, args) 0105 { 0106 m_container = new KSysGuard::SensorContainer("power", i18nc("@title", "Power"), this); 0107 const auto batteries = Solid::Device::listFromType(Solid::DeviceInterface::Battery); 0108 0109 for (const auto &device : batteries) { 0110 auto battery = new Battery(device, device.displayName(), m_container); 0111 m_batteriesByUdi.insert(device.udi(), battery); 0112 } 0113 0114 connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded, this, [this] (const QString &udi) { 0115 const Solid::Device device(udi); 0116 if (device.isDeviceInterface(Solid::DeviceInterface::Battery)) { 0117 auto battery = new Battery(device, device.displayName(), m_container); 0118 m_batteriesByUdi.insert(udi, battery); 0119 } 0120 }); 0121 connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved, this, [this] (const QString &udi) { 0122 if (m_batteriesByUdi.contains(udi)) { 0123 m_container->removeObject(m_batteriesByUdi[udi]); 0124 m_batteriesByUdi.remove(udi); 0125 } 0126 }); 0127 } 0128 0129 #include "power.moc"