diff --git a/CMakeLists.txt b/CMakeLists.txt index 55cf5c5c2..6d2f14680 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ else() find_package(Qca-qt5 ${QCA_MIN_VERSION} REQUIRED) set(Qca_LIBRARY qca-qt5) - set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Kirigami2 People) + set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People) set(KF5_OPTIONAL_COMPONENTS DocTools) set_package_properties(KF5Kirigami2 PROPERTIES diff --git a/plugins/battery/CMakeLists.txt b/plugins/battery/CMakeLists.txt index 4c471d980..00c5477b6 100644 --- a/plugins/battery/CMakeLists.txt +++ b/plugins/battery/CMakeLists.txt @@ -8,5 +8,6 @@ kdeconnect_add_plugin(kdeconnect_battery JSON kdeconnect_battery.json SOURCES ${ target_link_libraries(kdeconnect_battery kdeconnectcore Qt5::DBus + KF5::Solid KF5::I18n ) diff --git a/plugins/battery/README b/plugins/battery/README index 8812ba1a1..6b28dd38a 100644 --- a/plugins/battery/README +++ b/plugins/battery/README @@ -11,9 +11,11 @@ thresholdEvent (int) [optional when = 0, see below]: This is an int so in the future we'll be able to subscribe to more events. (see BatteryPlugin.ThresholdBatteryEvent) - Symmetrically, it sends its own battery information in packages with the same -format. +format. We only look for the 'primary' battery of the system, if one is present. + + +Support for devices with multiple batteries isn't there yet. It also sends packages with type kdeconnect.battery and a field "request": true, diff --git a/plugins/battery/batteryplugin.cpp b/plugins/battery/batteryplugin.cpp index 5371be561..dc79e04a6 100644 --- a/plugins/battery/batteryplugin.cpp +++ b/plugins/battery/batteryplugin.cpp @@ -23,6 +23,10 @@ #include #include +#include +#include +#include + #include #include "batterydbusinterface.h" @@ -36,8 +40,8 @@ BatteryPlugin::BatteryPlugin(QObject* parent, const QVariantList& args) , batteryDbusInterface(new BatteryDbusInterface(device())) { - //TODO: Add battery reporting, could be based on: - // https://www.linux-apps.com/content/show.php/battery+plasmoid+with+remaining+time?content=120309 + //TODO: Our protocol should support a dynamic number of batteries. + //Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance(); } @@ -45,6 +49,76 @@ void BatteryPlugin::connected() { NetworkPacket np(PACKET_TYPE_BATTERY_REQUEST, {{QStringLiteral("request"),true}}); sendPacket(np); + + const auto batteryDevice = Solid::DeviceInterface::Type::Battery; + const auto primary = Solid::Battery::BatteryType::PrimaryBattery; + + QList batteries = Solid::Device::listFromQuery(Solid::Predicate(batteryDevice, QStringLiteral("type"), primary)); + + if (batteries.isEmpty()) { + qCWarning(KDECONNECT_PLUGIN_BATTERY) << "No Primary Battery detected on this system. This may be a bug."; + QList allBatteries = Solid::Device::listFromType(batteryDevice); + qCWarning(KDECONNECT_PLUGIN_BATTERY) << "Total quantity of batteries found: " << allBatteries.size(); + return; + } + + const Solid::Battery* chosen = batteries.first().as(); + + connect(chosen, &Solid::Battery::chargeStateChanged, this, &BatteryPlugin::chargeChanged); + connect(chosen, &Solid::Battery::chargePercentChanged, this, &BatteryPlugin::chargeChanged); + + // Explicitly send the current charge + chargeChanged(); +} + +void BatteryPlugin::chargeChanged() +{ + + bool isAnyBatteryCharging = false; + int batteryQuantity = 0; + int cumulativeCharge = 0; + + const auto batteryDevice = Solid::DeviceInterface::Type::Battery; + const auto primary = Solid::Battery::BatteryType::PrimaryBattery; + + QList batteries = Solid::Device::listFromQuery(Solid::Predicate(batteryDevice, QStringLiteral("type"), primary)); + + for (auto device : batteries) { + const Solid::Battery* battery = device.as(); + + // Don't look at batteries that have been detached + if (battery->isPresent()) { + batteryQuantity++; + cumulativeCharge += battery->chargePercent(); + if (battery->chargeState() == Solid::Battery::ChargeState::Charging) { + isAnyBatteryCharging = true; + } + } + } + + if (batteryQuantity == 0) { + qCWarning(KDECONNECT_PLUGIN_BATTERY) << "Primary Battery seems to have been removed. Suspending packets until it is reconnected."; + return; + } + + // Load a new Battery object to represent the first device in the list + Solid::Battery* chosen = batteries.first().as(); + + // Prepare an outgoing network packet + NetworkPacket status(PACKET_TYPE_BATTERY, {{}}); + status.set(QStringLiteral("isCharging"), isAnyBatteryCharging); + status.set(QStringLiteral("currentCharge"), cumulativeCharge / batteryQuantity); + // FIXME: In future, we should consider sending an array of battery objects + status.set(QStringLiteral("batteryQuantity"), batteryQuantity); + // We consider primary battery to be low if it will only last for 5 minutes or + // less. This doesn't necessarily work if (for example) Solid finds multiple + // batteries. + if (chosen->remainingTime() < 600 && chosen->chargeState() == Solid::Battery::ChargeState::Discharging) { + status.set(QStringLiteral("thresholdEvent"), (int)ThresholdBatteryLow); + } else { + status.set(QStringLiteral("thresholdEvent"), (int)ThresholdNone); + } + sendPacket(status); } BatteryPlugin::~BatteryPlugin() diff --git a/plugins/battery/batteryplugin.h b/plugins/battery/batteryplugin.h index 5eed972f5..c631e88d4 100644 --- a/plugins/battery/batteryplugin.h +++ b/plugins/battery/batteryplugin.h @@ -24,6 +24,7 @@ #include #include +#define PACKET_TYPE_BATTERY QStringLiteral("kdeconnect.battery") #define PACKET_TYPE_BATTERY_REQUEST QStringLiteral("kdeconnect.battery.request") Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_BATTERY) @@ -41,6 +42,11 @@ public: bool receivePacket(const NetworkPacket& np) override; void connected() override; + // NB: This may be connected to zero or two signals in Solid::Battery - + // chargePercentageChanged and chargeStatusChanged. + // See inline comments for further details + void chargeChanged(); + private: // Keep these values in sync with THRESHOLD* constants in // kdeconnect-android:BatteryPlugin.java diff --git a/plugins/battery/kdeconnect_battery.json b/plugins/battery/kdeconnect_battery.json index 84079c4ad..cc2a2b7d6 100644 --- a/plugins/battery/kdeconnect_battery.json +++ b/plugins/battery/kdeconnect_battery.json @@ -131,9 +131,11 @@ "Website": "https://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPacketType": [ + "kdeconnect.battery", "kdeconnect.battery.request" ], "X-KdeConnect-SupportedPacketType": [ - "kdeconnect.battery" + "kdeconnect.battery", + "kdeconnect.battery.request" ] }