from __future__ import annotations import json import time from dataclasses import dataclass from pathlib import Path from modules.display_control import set_brightness ROOT = Path(__file__).resolve().parents[1] SCHEDULE_PATH = ROOT / "data" / "brightness_schedule.json" @dataclass(frozen=True, slots=True) class ScheduleItem: at: str # "HH:MM" 24h value: int def _load_schedule() -> list[ScheduleItem]: if not SCHEDULE_PATH.exists(): SCHEDULE_PATH.parent.mkdir(parents=True, exist_ok=True) SCHEDULE_PATH.write_text( json.dumps( { "enabled": True, "items": [ {"at": "07:00", "value": 80}, {"at": "22:00", "value": 30}, ], }, indent=2, ), encoding="utf-8", ) try: data = json.loads(SCHEDULE_PATH.read_text(encoding="utf-8")) except Exception: return [] if not bool(data.get("enabled", True)): return [] items = [] for it in data.get("items", []): at = str(it.get("at", "")).strip() if not at or ":" not in at: continue try: v = int(it.get("value", 50)) except Exception: v = 50 items.append(ScheduleItem(at=at, value=max(0, min(100, v)))) return sorted(items, key=lambda x: x.at) def run_loop(poll_seconds: int = 20) -> None: """Background scheduler. Applies brightness at the matching minute boundary.""" last_minute = "" while True: items = _load_schedule() if not items: time.sleep(max(5, int(poll_seconds))) continue now = time.localtime() minute = f"{now.tm_hour:02d}:{now.tm_min:02d}" if minute != last_minute: last_minute = minute for it in items: if it.at == minute: set_brightness(it.value) break time.sleep(max(5, int(poll_seconds)))