v0.8.4: NINA Sofortabfrage nach Speichern + Zeitstempel letzte Abfrage
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
f2ffe0fd9d
commit
2db03510c8
10
CHANGELOG.md
10
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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version: "0.8.3"
|
||||
version: "0.8.4"
|
||||
|
||||
bot:
|
||||
name: "MeshDD-Bot"
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<label for="pollInterval" class="form-label">Abfrage­intervall (Sek.)</label>
|
||||
<input type="number" class="form-control form-control-sm" id="pollInterval"
|
||||
min="60" max="3600" step="60" value="300">
|
||||
<div class="form-text">Neue Warnmeldungen</div>
|
||||
<div class="form-text">Neue Warnmeldungen<span id="lastPoll" class="d-block text-body-secondary"></span></div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<label for="resendInterval" class="form-label">Wieder­holungsintervall (Sek.)</label>
|
||||
|
|
|
|||
Loading…
Reference in a new issue