Read battery percentage and charging state. Tries (in order): 1. /sys/class/power_supply/battery/ (fast, no subprocess) 2. termux-battery-status (Termux API, ~200ms subprocess) Returns (percentage or None, is_charging).
(self)
| 251 | return best |
| 252 | |
| 253 | def _read_battery(self) -> Tuple[Optional[int], bool]: |
| 254 | """ |
| 255 | Read battery percentage and charging state. |
| 256 | |
| 257 | Tries (in order): |
| 258 | 1. /sys/class/power_supply/battery/ (fast, no subprocess) |
| 259 | 2. termux-battery-status (Termux API, ~200ms subprocess) |
| 260 | |
| 261 | Returns (percentage or None, is_charging). |
| 262 | """ |
| 263 | # Fast path: sysfs |
| 264 | try: |
| 265 | batt = Path("/sys/class/power_supply/battery") |
| 266 | if batt.exists(): |
| 267 | pct = int((batt / "capacity").read_text().strip()) |
| 268 | status = (batt / "status").read_text().strip().lower() |
| 269 | return pct, status in ("charging", "full") |
| 270 | except Exception: |
| 271 | pass |
| 272 | # Fallback: termux-battery-status (JSON output) |
| 273 | try: |
| 274 | out = subprocess.run( |
| 275 | ["termux-battery-status"], |
| 276 | capture_output=True, text=True, timeout=2, |
| 277 | ) |
| 278 | if out.returncode == 0 and out.stdout.strip(): |
| 279 | data = json.loads(out.stdout) |
| 280 | pct = data.get("percentage") |
| 281 | status = data.get("status", "").lower() |
| 282 | return pct, status in ("charging", "full") |
| 283 | except Exception: |
| 284 | pass |
| 285 | return None, False |
| 286 | |
| 287 | |
| 288 | # ── helpers ─────────────────────────────────────────────────────────────────── |
no test coverage detected