From 4c5dfbe4292d5d96a4c33aedaad1886a88be2dc6 Mon Sep 17 00:00:00 2001 From: enkore Date: Fri, 22 Feb 2013 21:04:33 +0100 Subject: [PATCH] Using uevent instead of the separate files reduces I/O... ...and makes the code a bit cleaner. Didn't touch much of the class logic, except that it just displays the charge if the state is "Unknown". --- i3pystatus/batterychecker.py | 68 +++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/i3pystatus/batterychecker.py b/i3pystatus/batterychecker.py index 0f927f8..b95da60 100644 --- a/i3pystatus/batterychecker.py +++ b/i3pystatus/batterychecker.py @@ -3,6 +3,47 @@ from i3pystatus import IntervalModule +class Battery: + """ + Simple interface to /sys/class/power_supply/BATx/uevent + + The data from uevent is transformed into attributes of this class, stripping + their prefix. (i.e. POWER_SUPPLY_NAME becomes the NAME attribute). + + Numbers are automatically converted to floats. + + Strings are stripped. + + (configparser would be a bit overkill for this) + """ + + prefix = "POWER_SUPPLY_" + + @staticmethod + def lchop(string, substring): + if string.startswith(substring): + return string[len(substring):] + + return string + + def __init__(self, file): + self.parse(file) + + def parse(self, file): + with open(file, "r") as file: + for line in file: + self.parse_line(line.strip()) + + def parse_line(self, line): + key, value = line.split("=", 2) + key = self.lchop(key, self.prefix) + value = value.strip() + + if value.isdecimal(): + value = float(value) + + setattr(self, key, value) + class BatteryChecker(IntervalModule): """ This class uses the /proc/acpi/battery interface to check for the @@ -11,22 +52,21 @@ class BatteryChecker(IntervalModule): def __init__(self, battery_ident="BAT0"): self.battery_ident = battery_ident - self.base_path = "/sys/class/power_supply/%s" % self.battery_ident + self.base_path = "/sys/class/power_supply/{0}/uevent".format(self.battery_ident) def run(self): urgent = False color = "#ffffff" - status = open('%s/status' % self.base_path, 'r').readline().strip() - energy_now = float(open('%s/energy_now' % self.base_path, 'r').readline()) - if status == 'Full': - full_text = 'fully charged' - elif status == 'Charging': - energy_full = float(open('%s/energy_full' % self.base_path, 'r').readline()) - energy_percentage = (energy_now / energy_full) * 100 - full_text = '%.2f%% charged' - elif status == 'Discharging': - power_now = float(open('%s/power_now' % self.base_path, 'r').readline()) + battery = Battery(self.base_path) + + status = battery.STATUS + energy_now = battery.ENERGY_NOW + + if status == "Full": + full_text = "fully charged" + elif status == "Discharging": + power_now = battery.POWER_NOW remaining_time_secs = (energy_now / power_now) * 3600 hours, remainder = divmod(remaining_time_secs, 3600) minutes, seconds = divmod(remainder, 60) @@ -34,8 +74,10 @@ class BatteryChecker(IntervalModule): if remaining_time_secs < (15*60): urgent = True color = "#ff0000" - else: - full_text = 'n/a' + else: # Charging, Unknown etc. (My thinkpad says Unknown if close to fully charged) + energy_full = battery.ENERGY_FULL + percentage = (energy_now / energy_full) * 100 + full_text = "%.2f%% charged" % percentage self.output = { "full_text": full_text,