diff --git a/modules/core/battery-upower.py b/modules/core/battery-upower.py new file mode 100644 index 0000000..7619651 --- /dev/null +++ b/modules/core/battery-upower.py @@ -0,0 +1,271 @@ +# UPowerManger Class Copyright (C) 2017 Oscar Svensson (wogscpar) under MIT licence from upower-python + +"""Displays battery status, remaining percentage and charging information. + +Parameters: + * battery-upower.warning : Warning threshold in % of remaining charge (defaults to 20) + * battery-upower.critical : Critical threshold in % of remaining charge (defaults to 10) + * battery-upower.showremaining : If set to true (default) shows the remaining time until the batteries are completely discharged +""" + +import dbus +import logging + +import bumblebee.input +import bumblebee.output +import bumblebee.engine +import bumblebee.util + +class UPowerManager(): + + def __init__(self): + self.UPOWER_NAME = "org.freedesktop.UPower" + self.UPOWER_PATH = "/org/freedesktop/UPower" + + self.DBUS_PROPERTIES = "org.freedesktop.DBus.Properties" + self.bus = dbus.SystemBus() + + def detect_devices(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME) + + devices = upower_interface.EnumerateDevices() + return devices + + def get_display_device(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME) + + dispdev = upower_interface.GetDisplayDevice() + return dispdev + + def get_critical_action(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME) + + critical_action = upower_interface.GetCriticalAction() + return critical_action + + def get_device_percentage(self, battery): + battery_proxy = self.bus.get_object(self.UPOWER_NAME, battery) + battery_proxy_interface = dbus.Interface(battery_proxy, self.DBUS_PROPERTIES) + + return battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Percentage") + + def get_full_device_information(self, battery): + battery_proxy = self.bus.get_object(self.UPOWER_NAME, battery) + battery_proxy_interface = dbus.Interface(battery_proxy, self.DBUS_PROPERTIES) + + hasHistory = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "HasHistory") + hasStatistics = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "HasStatistics") + isPresent = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IsPresent") + isRechargable = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IsRechargeable") + online = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Online") + powersupply = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "PowerSupply") + capacity = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Capacity") + energy = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Energy") + energyempty = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyEmpty") + energyfull = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyFull") + energyfulldesign = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyFullDesign") + energyrate = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "EnergyRate") + luminosity = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Luminosity") + percentage = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Percentage") + temperature = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Temperature") + voltage = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Voltage") + timetoempty = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "TimeToEmpty") + timetofull = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "TimeToFull") + iconname = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "IconName") + model = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Model") + nativepath = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "NativePath") + serial = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Serial") + vendor = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Vendor") + state = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State") + technology = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Technology") + battype = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "Type") + warninglevel = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "WarningLevel") + updatetime = battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "UpdateTime") + + information_table = { + 'HasHistory': hasHistory, + 'HasStatistics': hasStatistics, + 'IsPresent': isPresent, + 'IsRechargeable': isRechargable, + 'Online': online, + 'PowerSupply': powersupply, + 'Capacity': capacity, + 'Energy': energy, + 'EnergyEmpty': energyempty, + 'EnergyFull': energyfull, + 'EnergyFullDesign': energyfulldesign, + 'EnergyRate': energyrate, + 'Luminosity': luminosity, + 'Percentage': percentage, + 'Temperature': temperature, + 'Voltage': voltage, + 'TimeToEmpty': timetoempty, + 'TimeToFull': timetofull, + 'IconName': iconname, + 'Model': model, + 'NativePath': nativepath, + 'Serial': serial, + 'Vendor': vendor, + 'State': state, + 'Technology': technology, + 'Type': battype, + 'WarningLevel': warninglevel, + 'UpdateTime': updatetime + } + + return information_table + + def is_lid_present(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) + + is_lid_present = bool(upower_interface.Get(self.UPOWER_NAME, 'LidIsPresent')) + return is_lid_present + + def is_lid_closed(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) + + is_lid_closed = bool(upower_interface.Get(self.UPOWER_NAME, 'LidIsClosed')) + return is_lid_closed + + def on_battery(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH) + upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) + + on_battery = bool(upower_interface.Get(self.UPOWER_NAME, 'OnBattery')) + return on_battery + + def has_wakeup_capabilities(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") + upower_interface = dbus.Interface(upower_proxy, self.DBUS_PROPERTIES) + + has_wakeup_capabilities = bool(upower_interface.Get(self.UPOWER_NAME + '.Wakeups', 'HasCapability')) + return has_wakeup_capabilities + + def get_wakeups_data(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + '.Wakeups') + + data = upower_interface.GetData() + return data + + def get_wakeups_total(self): + upower_proxy = self.bus.get_object(self.UPOWER_NAME, self.UPOWER_PATH + "/Wakeups") + upower_interface = dbus.Interface(upower_proxy, self.UPOWER_NAME + '.Wakeups') + + data = upower_interface.GetTotal() + return data + + def is_loading(self, battery): + battery_proxy = self.bus.get_object(self.UPOWER_NAME, battery) + battery_proxy_interface = dbus.Interface(battery_proxy, self.DBUS_PROPERTIES) + + state = int(battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State")) + + if (state == 1): + return True + else: + return False + + def get_state(self, battery): + battery_proxy = self.bus.get_object(self.UPOWER_NAME, battery) + battery_proxy_interface = dbus.Interface(battery_proxy, self.DBUS_PROPERTIES) + + state = int(battery_proxy_interface.Get(self.UPOWER_NAME + ".Device", "State")) + + if (state == 0): + return "Unknown" + elif (state == 1): + return "Loading" + elif (state == 2): + return "Discharging" + elif (state == 3): + return "Empty" + elif (state == 4): + return "Fully charged" + elif (state == 5): + return "Pending charge" + elif (state == 6): + return "Pending discharge" + + +class Module(bumblebee.engine.Module): + def __init__(self, engine, config): + super(Module, self).__init__(engine, config, bumblebee.output.Widget(full_text=self.capacity)) + try: + self.power = UPowerManager() + self.device = self.power.get_display_device() + except Exception as e: + logging.exception("unable to get battery display device: {}".format(str(e))) + engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, + cmd="gnome-power-statistics") + + self._showremaining = bumblebee.util.asbool( + self.parameter("showremaining", True)) + + def capacity(self, widget): + widget.set("capacity", -1) + widget.set("ac", False) + output = "n/a" + try: + capacity = int(self.power.get_device_percentage(self.device)) + capacity = capacity if capacity < 100 else 100 + widget.set("capacity", capacity) + output = "{}%".format(capacity) + widget.set("theme.minwidth", "100%") + except Exception as e: + logging.exception("unable to get battery capacity: {}".format(str(e))) + + if self._showremaining: + try: + p = self.power # an alias to make each line of code shorter + proxy = p.bus.get_object(p.UPOWER_NAME, self.device) + interface = dbus.Interface(proxy, p.DBUS_PROPERTIES) + state = int(interface.Get(p.UPOWER_NAME+".Device", "State")) + # state: 1 => charging, 2 => discharging, other => don't care + remain = int(interface.Get( + p.UPOWER_NAME+".Device", ["TimeToFull", "TimeToEmpty"][state-1])) + remain = bumblebee.util.durationfmt(remain, shorten=True, suffix=True) + output = "{} {}".format(output, remain) + except IndexError: + pass + except Exception as e: + logging.exception("unable to get battery remaining time: {}".format(str(e))) + + return output + + def state(self, widget): + state = [] + capacity = widget.get("capacity", -1) + if capacity < 0: + return ["critical", "unknown"] + + if capacity < int(self.parameter("critical", 10)): + state.append("critical") + elif capacity < int(self.parameter("warning", 20)): + state.append("warning") + + if widget.get("ac"): + state.append("AC") + else: + charge = "Unknown" + try: + charge = self.power.get_state(self.device) + except Exception as e: + logging.exception("unable to get charge value: {}".format(str(e))) + if charge == "Discharging": + state.append("discharging-{}".format(min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)))) + elif charge == "Unknown": + state.append("unknown-{}".format(min([10, 25, 50, 80, 100], key=lambda i: abs(i - capacity)))) + else: + if capacity > 95: + state.append("charged") + else: + state.append("charging") + return state + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4