From df0a8cf900795bcddd8633db714890151297888d Mon Sep 17 00:00:00 2001 From: Colin Date: Sat, 15 Jun 2024 09:46:58 +0000 Subject: [PATCH] refactor: sane-sysinfo: split out a BatteryInfo class --- pkgs/additional/sane-sysinfo/sane-sysinfo | 55 +++++++++++++---------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/pkgs/additional/sane-sysinfo/sane-sysinfo b/pkgs/additional/sane-sysinfo/sane-sysinfo index e9e65847..e199d512 100755 --- a/pkgs/additional/sane-sysinfo/sane-sysinfo +++ b/pkgs/additional/sane-sysinfo/sane-sysinfo @@ -70,6 +70,9 @@ class Formatter: @dataclass class ParsedPowerSupply: + """ + near-direct values from /sys/class/power_supply API endpoints + """ percent_charged: int | None = None # unitless: could be joules, could be something else charge_full: int | None = None @@ -81,25 +84,30 @@ class ParsedPowerSupply: self.charge_full is not None and \ self.charge_rate is not None - @property - def percent_discharged(self) -> int | None: - if self.percent_charged is not None: - return 100 - self.percent_charged +class BatteryInfo: + """ + higher-level battery info derived from the underlying power supply + """ + percent_charged: int #< always available + minutes_to_charged: int | None = None + minutes_to_discharged: int | None = None - @property - def discharge_rate(self) -> int | None: - if self.charge_rate is not None: - return -self.charge_rate + def __init__(self, p: ParsedPowerSupply): + assert p.percent_charged is not None + self.percent_charged = p.percent_charged - @property - def minutes_to_charged(self) -> int | None: - if self.percent_discharged is not None and self.charge_full and self.charge_rate > 0: - return int(self.charge_full * self.percent_discharged/100 / self.charge_rate * 60) - - @property - def minutes_to_discharged(self) -> int | None: - if self.percent_charged is not None and self.charge_full and self.charge_rate < 0: - return int(self.charge_full * self.percent_charged/100 / self.discharge_rate * 60) + if p.charge_rate is not None and p.charge_rate < 0: + self.minutes_to_discharged = int( + 60 + * p.charge_full * self.percent_charged/100 + / -p.charge_rate + ) + if p.charge_full is not None and p.charge_rate is not None and p.charge_rate > 0: + self.minutes_to_charged = int( + 60 + * p.charge_full * (100-self.percent_charged)/100 + / p.charge_rate * 60 + ) def render_icon(direction: ChargeDirection, percentage: float) -> str: @@ -167,7 +175,7 @@ def try_path(p: str) -> ParsedPowerSupply | None: return state if state.percent_charged is not None else None -def try_all_paths() -> ParsedPowerSupply | None: +def try_all_paths() -> BatteryInfo | None: p = try_path("/sys/class/power_supply/axp20x-battery") # Pinephone if p is None: p = try_path("/sys/class/power_supply/BAT0") # Thinkpad @@ -176,7 +184,8 @@ def try_all_paths() -> ParsedPowerSupply | None: logger.debug(f"full: {p.charge_full if p else None}, rate: {p.charge_rate if p else None}") logger.debug(" rate > 0 means charging, else discharging") - return p + if p.percent_charged is not None: + return BatteryInfo(p) def fmt_minutes(f: Formatter, icon: str, if_indefinite: str, minutes: int | None) -> str: logger.debug(f"charge/discharge time: {minutes} min") @@ -189,19 +198,19 @@ def fmt_minutes(f: Formatter, icon: str, if_indefinite: str, minutes: int | None logger.debug("charge/discharge duration > 1d") return f"{icon}{f.suffix_icon}{if_indefinite}" -def pretty_output(f: Formatter, p: ParsedPowerSupply) -> str: - if p.charge_rate > 0: +def pretty_output(f: Formatter, p: BatteryInfo) -> str: + if p.minutes_to_charged != None: logger.debug("charging") icon = render_icon(ChargeDirection.Charging, p.percent_charged) duration = p.minutes_to_charged else: logger.debug("discharging") - icon = render_icon(ChargeDirection.Discharging, p.percent_discharged) + icon = render_icon(ChargeDirection.Discharging, p.percent_charged) duration = p.minutes_to_discharged return fmt_minutes(f, icon, f"{p.percent_charged}{f.suffix_percent}", duration) -def main(): +def main() -> None: logging.basicConfig() logging.getLogger().setLevel(logging.INFO)