aboutsummaryrefslogblamecommitdiffstats
path: root/xpybar/config/mybattery.py
blob: 3a8e167377f63faac94d2d37272f875f58faac77 (plain) (tree)


































































































































































                                                                                                                         
# -*- python -*-
from plugins.powersupply import PowerSupply

from common import *

class MyBattery(Entry):
    COMPACT  = 0
    NORMAL   = 1
    DETAILED = 2
    
    def __init__(self, *args, show_all = False, show_battery = 0, details = 1, batteries = None, **kwargs):
        self.show_all = show_all
        self.show_battery = show_battery
        self.supply_filter = batteries
        self.details = details
        self.supplies = None
        self.batteries = None
        self.reload()
        Entry.__init__(self, *args, **kwargs)
    
    def reload(self):
        name = None
        newsupplies = {}
        newbatteries = []
        if self.batteries is not None:
            if isinstance(self.batteries, int):
                name = self.batteries[self.show_battery]
            else:
                name = self.show_battery
        for supply in PowerSupply.supplies():
            if self.supply_filter is not None:
                if supply not in self.supply_filter:
                    continue
            supply = PowerSupply(supply)
            if supply.type != 'Battery':
                continue
            newsupplies[supply.name] = supply
            newbatteries.append(supply.name)
        if self.supply_filter is not None:
            newbatteries = [b for b in self.supply_filter if b in newsupplies]
        if name is None:
            index = 0
        elif isinstance(name, int):
            index = name % len(newbatteries) if len(newbatteries) > 0 else 0
        elif name in self.batteries:
            index = self.batteries.index(index)
        else:
            index = 0
        self.supplies, self.batteries, self.show_battery = newsupplies, newbatteries, index
    
    def action(self, col, button, x, y):
        if button == LEFT_BUTTON:
            self.show_all = not self.show_all
            self.invalidate()
        elif button == MIDDLE_BUTTON:
            self.details += 1
            self.details %= 3
            self.invalidate()
        elif button == RIGHT_BUTTON:
            self.reload()
            self.invalidate()
        elif button == SCROLL_UP:
            if len(self.batteries) > 0:
                self.show_battery += 1
                self.show_battery %= len(self.batteries)
            self.invalidate()
        elif button == SCROLL_DOWN:
            if len(self.batteries) > 0:
                self.show_battery -= 1
                if self.show_battery < 0:
                    self.show_battery += len(self.batteries)
            self.invalidate()
    
    def colourise(self, text):
        try:
            value = text.replace(',', '.')
            value = float(value) if '.' in value else int(value)
            colour = '39'
            if value < 80:  colour = '32'
            if value < 50:  colour = '33'
            if value < 15:  colour = '31'
            if value <  5:  colour = '7;31'
            return '\033[%sm%s\033[0m' % (colour, text)
        except:
            return text
    
    def battery(self, bat):
        bat = self.supplies[bat]
        name = bat.name[:1].upper() + bat.name[1:].lower()
        if bat.is_online():
            try:
                charge   = (bat.get_charge(),  bat.get_charge_full(), bat.charge_full_design)
                current  = bat.get_current()
                status   = bat.get_status().lower()
                left     = None
                if charge[0] == charge[1]:
                    capacity = '100'
                else:
                    capacity = '%.1f' % (charge[0] / charge[1] * 100)
                capacity = self.colourise(capacity)
                
                if current > 0:
                    if status == 'charging':
                        left = (charge[1] - charge[0]) / current
                    elif status == 'discharging':
                        left = charge[0] / current
                    if left is not None:
                        hours = int(left)
                        minutes = int((left - hours) * 60 + 0.5)
                        if minutes >= 60:
                            minutes -= 60
                            hours += 1
                        left = '%ih%02im until %s' % (hours, minutes, status.replace('ing', 'ed'))
                
                if self.details == MyBattery.COMPACT:
                    if status == 'full':
                        return 'full'
                    elif status == 'charging':
                        status = '+'
                    elif status == 'discharging':
                        status = '-'
                    else:
                        status = '?'
                    if left is None:
                        return '%s%%%s' % (capacity, status)
                    else:
                        return '%s%%%s %s' % (capacity, status, left)
                elif self.details == MyBattery.NORMAL:
                    if left is None:
                        return '%s: %s%% %s' % (name, capacity, status)
                    else:
                        return '%s: %s%% %s %s' % (name, capacity, status, left)
                else:
                    if charge[1] == charge[2]:
                        health = '100'
                    else:
                        health = '%.1f' % (charge[1] / charge[2] * 100)
                    health = self.colourise(health)
                    volt = bat.get_voltage() / bat.voltage_min_design
                    if volt < 1:
                        volt = '\033[31m%.1f\033[0m' % volt
                    elif volt < 1.05:
                        volt = '\033[33m%.1f\033[0m' % volt
                    else:
                        volt = '%.1f' % volt
                    if left is None:
                        return '%s: %s%% %s, %s%% healthy, %sx voltage' % (name, capacity, status, health, volt)
                    else:
                        return '%s: %s%% %s %s, %s%% healthy, %sx voltage' % (name, capacity, status, left, health, volt)
            except Exception as e:
                return (repr(e))
                return ('%s: ???' % name) if self.details > 0 else '???'
        else:
            return ('%s: offline' % name) if self.details > 0 else 'offline'
    
    def function(self):
        if len(self.batteries) == 0:
            return 'no batteries available'
        
        if self.show_all:
            return SEPARATOR.join(self.battery(bat) for bat in self.batteries)
        else:
            return self.battery(self.batteries[self.show_battery])