From 2db03510c8831ad5acb55924af3bf5a4d1dc2718 Mon Sep 17 00:00:00 2001 From: ppfeiffer Date: Thu, 19 Feb 2026 16:18:15 +0100 Subject: [PATCH] v0.8.4: NINA Sofortabfrage nach Speichern + Zeitstempel letzte Abfrage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Konfiguration speichern löst sofort eine NINA-Abfrage aus (trigger_poll) - Frontend lädt Config 5s nach Save neu um last_poll-Zeitstempel zu zeigen - Unterhalb Abfrageintervall-Feld: Datum/Uhrzeit der letzten Abfrage Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 10 ++++++++++ config.yaml | 2 +- meshbot/nina.py | 15 ++++++++++++++- meshbot/webserver.py | 1 + static/js/nina.js | 13 +++++++++++++ static/nina.html | 2 +- 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c78d3..7436bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.8.4] - 2026-02-19 + +### Added +- **NINA Sofortabfrage nach Speichern**: Nach dem Speichern der Konfiguration wird + unmittelbar eine Warnmeldungsabfrage gestartet (kein Warten auf den nächsten + Intervall-Zyklus). Das Frontend lädt die Konfiguration 5 Sekunden nach dem Speichern + automatisch neu, um den Zeitstempel der letzten Abfrage zu aktualisieren. +- **Letzte Abfrage anzeigen**: Unterhalb des Abfrageintervall-Felds wird Datum und Uhrzeit + der letzten erfolgreichen NINA-Abfrage angezeigt (`last_poll`-Feld im Config-Response). + ## [0.8.3] - 2026-02-19 ### Added diff --git a/config.yaml b/config.yaml index 984203b..10832f4 100644 --- a/config.yaml +++ b/config.yaml @@ -1,4 +1,4 @@ -version: "0.8.3" +version: "0.8.4" bot: name: "MeshDD-Bot" diff --git a/meshbot/nina.py b/meshbot/nina.py index 75b5524..3e7ae16 100644 --- a/meshbot/nina.py +++ b/meshbot/nina.py @@ -1,6 +1,7 @@ import asyncio import logging import os +from datetime import datetime, timezone from typing import Callable, Awaitable import aiohttp @@ -111,6 +112,7 @@ class NinaBot: self._running = False self._task: asyncio.Task | None = None self._resend_task: asyncio.Task | None = None + self._last_poll: str = "" self._load() # ── Config ────────────────────────────────────────────────────────────── @@ -152,7 +154,7 @@ class NinaBot: logger.exception("Error saving nina.yaml") def get_config(self) -> dict: - return self.config + return {**self.config, "last_poll": self._last_poll} def update_config(self, updates: dict) -> dict: if "sources" in updates: @@ -199,11 +201,22 @@ class NinaBot: # ── Polling ────────────────────────────────────────────────────────────── + async def trigger_poll(self) -> None: + """Run _check_alerts immediately (e.g. triggered after config save).""" + if not self.config.get("enabled"): + return + try: + await self._check_alerts() + self._last_poll = datetime.now(timezone.utc).isoformat() + except Exception: + logger.exception("NINA triggered poll error") + async def _poll_loop(self): while self._running: try: if self.config.get("enabled"): await self._check_alerts() + self._last_poll = datetime.now(timezone.utc).isoformat() except Exception: logger.exception("NINA polling error") interval = max(60, int(self.config.get("poll_interval", 300))) diff --git a/meshbot/webserver.py b/meshbot/webserver.py index 454740a..27bf3cd 100644 --- a/meshbot/webserver.py +++ b/meshbot/webserver.py @@ -219,6 +219,7 @@ class WebServer: return web.json_response({"error": "NINA not available"}, status=503) updates = await request.json() cfg = self.nina.update_config(updates) + asyncio.create_task(self.nina.trigger_poll()) return web.json_response(cfg) async def _api_scheduler_get(self, request: web.Request) -> web.Response: diff --git a/static/js/nina.js b/static/js/nina.js index ae54c89..5f997ab 100644 --- a/static/js/nina.js +++ b/static/js/nina.js @@ -120,6 +120,16 @@ function applyConfig(cfg) { document.getElementById('srcDwd').checked = src.dwd !== false; document.getElementById('srcLhp').checked = src.lhp !== false; document.getElementById('srcPolice').checked = !!src.police; + + const lpEl = document.getElementById('lastPoll'); + if (lpEl) { + if (cfg.last_poll) { + const d = new Date(cfg.last_poll); + lpEl.textContent = 'Letzte Abfrage: ' + d.toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'medium' }); + } else { + lpEl.textContent = ''; + } + } } function updateStatusBadge(cfg) { @@ -166,10 +176,13 @@ document.getElementById('btnSaveNina').addEventListener('click', async () => { if (resp.ok) { const cfg = await resp.json(); updateStatusBadge(cfg); + applyConfig(cfg); statusEl.textContent = 'Gespeichert ✓'; statusEl.className = 'align-self-center small text-success'; statusEl.classList.remove('d-none'); setTimeout(() => statusEl.classList.add('d-none'), 3000); + // Config nach kurzer Pause nachladen, damit last_poll den abgeschlossenen Poll zeigt + setTimeout(loadConfig, 5000); } else { statusEl.textContent = 'Fehler beim Speichern'; statusEl.className = 'align-self-center small text-danger'; diff --git a/static/nina.html b/static/nina.html index 3e8e066..15a5c66 100644 --- a/static/nina.html +++ b/static/nina.html @@ -75,7 +75,7 @@ -
Neue Warnmeldungen
+
Neue Warnmeldungen