diff --git a/scheduler.py b/scheduler.py index 00a5fda..03b8d6d 100644 --- a/scheduler.py +++ b/scheduler.py @@ -180,8 +180,9 @@ class Scheduler: def _poll_screen(self, screen_id: str) -> tuple[str, object, bool]: cache = self._caches[screen_id] screen = self.screens[screen_id] + settings = self.config.get_screen_settings(screen_id) checked = False - if cache.is_stale(screen.poll_interval): + if cache.is_stale(screen.get_poll_interval(settings)): cache.state = self._check(screen_id) cache.checked_at = time.time() checked = True diff --git a/screens/base.py b/screens/base.py index f7e4c99..7d55050 100644 --- a/screens/base.py +++ b/screens/base.py @@ -26,3 +26,9 @@ class Screen(ABC): """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 diff --git a/screens/weather.py b/screens/weather.py index f5ec06f..743070b 100644 --- a/screens/weather.py +++ b/screens/weather.py @@ -22,10 +22,21 @@ WEEKDAY_ABBR_DE = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"] class WeatherScreen(Screen): id = "weather" display_name = "Weather" - poll_interval = 1800 # 30 minutes -- weather doesn't need to be fresher + poll_interval = 1800 # fallback default (30 min) if settings has no update_minutes yet def default_settings(self) -> dict: - return {"city": "", "latitude": None, "longitude": None, "forecast_days": 3} + return {"city": "", "latitude": None, "longitude": None, "forecast_days": 3, "update_minutes": 30} + + def get_poll_interval(self, settings: dict) -> int: + raw = settings.get("update_minutes") + try: + # `raw or 30` would also catch a legitimate 0 (falsy) and silently + # replace it with 30 instead of clamping to the 1-minute floor + # below -- only fall back to the default when it's genuinely unset. + minutes = int(raw) if raw is not None else 30 + except (TypeError, ValueError): + minutes = 30 + return max(1, minutes) * 60 def geocode(self, city: str): """Resolve a city name to coordinates via Open-Meteo's free geocoding diff --git a/web/app.py b/web/app.py index 106af70..3328f77 100644 --- a/web/app.py +++ b/web/app.py @@ -68,6 +68,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: forecast_days = int(request.form.get("forecast_days", 3) or 3) if forecast_days not in (3, 5, 7): forecast_days = 3 + update_minutes = max(1, int(request.form.get("update_minutes", 30) or 30)) if city: try: @@ -82,6 +83,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: "latitude": result["latitude"], "longitude": result["longitude"], "forecast_days": forecast_days, + "update_minutes": update_minutes, }) return redirect(url_for("settings_weather", saved=1)) else: @@ -90,6 +92,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: "latitude": float(lat_raw) if lat_raw else None, "longitude": float(lon_raw) if lon_raw else None, "forecast_days": forecast_days, + "update_minutes": update_minutes, }) return redirect(url_for("settings_weather", saved=1)) diff --git a/web/templates/settings_weather.html b/web/templates/settings_weather.html index eeb0c00..ba98486 100644 --- a/web/templates/settings_weather.html +++ b/web/templates/settings_weather.html @@ -29,6 +29,11 @@ +
+ + +

Weather itself only refreshes the panel when something actually changed, so a shorter interval here mostly just means fresher data, not more flashing.

+