Dotfiles/desktopenvs/hyprdrive/station-bar/battery.py

55 lines
1.7 KiB
Python

"""Battery presence + percentage via sysfs — no upower dependency (that daemon
isn't guaranteed running; sysfs always is on real hardware). Mirrors the icon
tiers already established in scripts/batteryperc (the eww bar's battery poll)
so a laptop that switches between hyprlua and hyprdrive sees the same glyphs.
"""
from __future__ import annotations
from pathlib import Path
from typing import NamedTuple, Optional
_POWER_SUPPLY = Path("/sys/class/power_supply")
# (floor percentage, glyph) — first match wins, checked high to low.
_DISCHARGING_TIERS = [
(95, "󰁹"), (90, "󰂂"), (80, "󰂁"), (70, "󰂀"), (60, "󰁿"),
(50, "󰁾"), (40, "󰁽"), (30, "󰁼"), (20, "󰁻"), (10, "󰁺"), (0, "󰂎"),
]
_CHARGING_ICON = "󰂄"
class BatteryState(NamedTuple):
percent: int
charging: bool
icon: str
def _find_battery() -> Optional[Path]:
if not _POWER_SUPPLY.is_dir():
return None
for entry in sorted(_POWER_SUPPLY.iterdir()):
if entry.name.startswith("BAT"):
return entry
return None
def read() -> Optional[BatteryState]:
"""Returns None when no battery is present (desktop machine) — callers
should hide the widget entirely in that case, per spec."""
bat = _find_battery()
if bat is None:
return None
try:
percent = int((bat / "capacity").read_text().strip())
status = (bat / "status").read_text().strip().lower()
except (OSError, ValueError):
return None
charging = status == "charging"
if charging:
icon = _CHARGING_ICON
else:
icon = next(g for floor, g in _DISCHARGING_TIERS if percent >= floor)
return BatteryState(percent=percent, charging=charging, icon=icon)