Files
Honey 889c062212 Make weather update interval configurable, was hardcoded to 30 min
Screen.poll_interval was a fixed class attribute the scheduler read
directly -- added Screen.get_poll_interval(settings) so a screen can make
it settings-driven instead. WeatherScreen overrides it to read a new
"update_minutes" field (default 30, matching the old hardcoded value).
New number input on the Weather settings page.

Caught a real edge case while testing: `raw or 30` treats an explicit 0
as falsy and silently replaces it with 30 instead of clamping to the
1-minute floor. Not reachable via the UI (min="1" on the input) but the
method should still be correct standalone -- fixed with an explicit
None-check instead.
2026-07-22 20:14:46 +02:00

35 lines
1.3 KiB
Python

"""Base interface every screen implements."""
from abc import ABC, abstractmethod
from typing import Any
from PIL import Image
class Screen(ABC):
id: str
display_name: str
poll_interval: int = 60 # seconds between check() calls
@abstractmethod
def check(self, settings: dict) -> Any:
"""Cheap call (ideally a single small request) that returns whatever
state this screen needs to render. Returning None means "nothing to
show" (only meaningful for preemptive screens like Navidrome)."""
@abstractmethod
def render(self, state: Any, settings: dict, resolution: tuple[int, int]) -> Image.Image:
"""Full draw. Only called when this screen is actually about to be
shown, so it's fine for this to be more expensive than check()."""
def default_settings(self) -> dict:
"""Settings this screen needs, with defaults, merged under config.json's
settings[self.id] on first run."""
return {}
def get_poll_interval(self, settings: dict) -> int:
"""Seconds between check() calls. Override to make it configurable
via settings (e.g. a user-facing "update every N minutes" field);
defaults to the fixed class-level poll_interval."""
return self.poll_interval