docs: vollständige Bot-Beschreibung und 0.8.x Release-Notes hinzugefügt
- docs/bot-beschreibung.md: umfassende Dokumentation mit Architektur, Komponenten, API-Referenz, Konfiguration, Datenbank-Schema, Deployment und chronologischer Erweiterungshistorie (v0.1.0–v0.8.9) - docs/whats-new-0.8.md: Neuigkeiten der 0.8.x-Release-Serie (NINA, Paket-Log, Karte, Bugfixes, API-Endpunkte, Versionshistorie) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f36a126200
commit
79f80563c8
597
docs/bot-beschreibung.md
Normal file
597
docs/bot-beschreibung.md
Normal file
|
|
@ -0,0 +1,597 @@
|
||||||
|
# MeshDD-Bot — Vollständige Beschreibung
|
||||||
|
|
||||||
|
> Aktueller Stand: **v0.8.9** · Letztes Update: 2026-02-19
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inhaltsverzeichnis
|
||||||
|
|
||||||
|
1. [Überblick](#überblick)
|
||||||
|
2. [Architektur](#architektur)
|
||||||
|
3. [Komponenten im Detail](#komponenten-im-detail)
|
||||||
|
4. [Bot-Kommandos](#bot-kommandos)
|
||||||
|
5. [Weboberfläche & Seiten](#weboberfläche--seiten)
|
||||||
|
6. [REST-API-Referenz](#rest-api-referenz)
|
||||||
|
7. [Zugriffsrechte](#zugriffsrechte)
|
||||||
|
8. [Konfiguration](#konfiguration)
|
||||||
|
9. [Datenbank](#datenbank)
|
||||||
|
10. [Deployment](#deployment)
|
||||||
|
11. [Wichtige Erweiterungsschritte](#wichtige-erweiterungsschritte)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
**MeshDD-Bot** ist ein Python-basierter Bot für **Meshtastic**-Funknetze mit integriertem Web-Dashboard. Er verbindet sich per TCP mit einem lokalen Meshtastic-Node, empfängt und speichert alle Pakete im Netz, beantwortet Bot-Kommandos und stellt eine browserbasierte Oberfläche für Echtzeit-Monitoring, Verwaltung und Notfall-Warnsystem-Integration bereit.
|
||||||
|
|
||||||
|
**Hauptmerkmale:**
|
||||||
|
|
||||||
|
- Meshtastic TCP-Verbindung mit automatischem Reconnect
|
||||||
|
- Bot-Kommandos (Ping, Wetter, Node-Info, Mesh-Statistiken u.a.)
|
||||||
|
- Echtzeit-Web-Dashboard via WebSocket
|
||||||
|
- Interaktive Leaflet-Karte aller Nodes
|
||||||
|
- Zeitgesteuerter Scheduler (Cron-Ausdrücke)
|
||||||
|
- NINA BBK Warnmeldungs-Integration (warnung.bund.de)
|
||||||
|
- Benutzerverwaltung mit Rollen (public / user / admin)
|
||||||
|
- Hot-Reload für alle Konfigurationsdateien
|
||||||
|
- Paket-Log mit Typ-Filterung
|
||||||
|
- Docker-ready mit docker-compose
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architektur
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ main.py │
|
||||||
|
│ asyncio event loop + threading für Meshtastic │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||||
|
│ │ MeshBot │ │Scheduler │ │ NinaBot │ │
|
||||||
|
│ │ bot.py │ │scheduler │ │ nina.py │ │
|
||||||
|
│ └────┬─────┘ │ .py │ └────────┬─────────┘ │
|
||||||
|
│ │ └────┬─────┘ │ │
|
||||||
|
│ ┌────▼─────────────▼─────────────────▼──────────┐ │
|
||||||
|
│ │ WebSocketManager │ │
|
||||||
|
│ │ webserver.py (aiohttp) │ │
|
||||||
|
│ └───────────────────┬───────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ┌───────────────────▼───────────────────────────┐ │
|
||||||
|
│ │ Database (aiosqlite) │ │
|
||||||
|
│ │ database.py │ │
|
||||||
|
│ └───────────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
│ TCP │ HTTP
|
||||||
|
▼ ▼
|
||||||
|
Meshtastic-Node Browser-Client
|
||||||
|
(192.168.11.4:4403) (Bootstrap 5.3 / Tabler)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Technologie-Stack
|
||||||
|
|
||||||
|
| Schicht | Technologie |
|
||||||
|
|---|---|
|
||||||
|
| Sprache | Python 3.12 |
|
||||||
|
| Async-Framework | asyncio + aiohttp |
|
||||||
|
| Meshtastic | meshtastic-python (TCPInterface) |
|
||||||
|
| Event-Bus | PyPubSub |
|
||||||
|
| Datenbank | SQLite via aiosqlite |
|
||||||
|
| Web-Server | aiohttp + WebSocket |
|
||||||
|
| Auth | bcrypt, aiohttp-session, EncryptedCookieStorage |
|
||||||
|
| Frontend | Bootstrap 5.3, Tabler 1.4.0, Bootstrap Icons |
|
||||||
|
| Karte | Leaflet.js |
|
||||||
|
| Charts | Chart.js |
|
||||||
|
| NINA-API | aiohttp (async HTTP-Polling) |
|
||||||
|
| Konfiguration | YAML (config.yaml, scheduler.yaml, nina.yaml) |
|
||||||
|
| Deployment | systemd Service / Docker + docker-compose |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Komponenten im Detail
|
||||||
|
|
||||||
|
### `main.py` — Einstiegspunkt
|
||||||
|
|
||||||
|
Startet alle Subsysteme in der richtigen Reihenfolge:
|
||||||
|
|
||||||
|
1. SQLite-Datenbank verbinden
|
||||||
|
2. `WebSocketManager` erzeugen
|
||||||
|
3. `MeshBot` (mit Loop-Referenz)
|
||||||
|
4. `Scheduler` (referenziert Bot + WS-Manager)
|
||||||
|
5. `NinaBot` (referenziert Bot's `send_message` + WS-Manager)
|
||||||
|
6. `WebServer` starten
|
||||||
|
7. Meshtastic-Verbindung in separatem Thread starten
|
||||||
|
8. Config-Watcher, Scheduler-Watcher, NINA-Watcher als asyncio-Tasks
|
||||||
|
9. Auf SIGINT/SIGTERM warten → sauberer Shutdown
|
||||||
|
|
||||||
|
### `meshbot/bot.py` — MeshBot
|
||||||
|
|
||||||
|
Kernklasse für die Meshtastic-Integration:
|
||||||
|
|
||||||
|
- **Verbindung:** `TCPInterface` über Host/Port aus `config.yaml`
|
||||||
|
- **PubSub-Subscriptions** (registriert *vor* dem Konstruktor):
|
||||||
|
- `meshtastic.receive` → Paket empfangen
|
||||||
|
- `meshtastic.connection.established` → Verbindung hergestellt
|
||||||
|
- `meshtastic.connection.lost` → Verbindung verloren
|
||||||
|
- `meshtastic.node.updated` → Node-Update
|
||||||
|
- **Race-Condition-Fix:** `threading.Event` wartet nach dem Konstruktor bis zu 10 s auf `connection.established`; Fallback-Initialisierung nur bei echtem Ausbleiben
|
||||||
|
- **Paket-Handler:** Extrahiert portnum, from/to-IDs, SNR, RSSI, Hop-Infos; erstellt `payload_summary` je Pakettyp
|
||||||
|
- **Nachrichtenversand:** `_send_text()` teilt lange Nachrichten automatisch mit `[x/y]`-Nummerierung (max. 170 Byte); 3 Sekunden Pause zwischen Teilen
|
||||||
|
- **Node-Config:** `get_node_config()` liest LoRa, Device, Channels, Position, Power, Bluetooth, Network via Protobuf
|
||||||
|
|
||||||
|
**Unterstützte Pakettypen mit Payload-Zusammenfassung:**
|
||||||
|
|
||||||
|
| Portnum | Gespeicherte Felder |
|
||||||
|
|---|---|
|
||||||
|
| `TEXT_MESSAGE_APP` | Nachrichtentext |
|
||||||
|
| `POSITION_APP` | lat, lon, alt, Geschwindigkeit, Satelliten |
|
||||||
|
| `TELEMETRY_APP` | Akku, Spannung, CH-Util, TX-Util, Temp, Feuchte, Druck |
|
||||||
|
| `NODEINFO_APP` | long_name, short_name, hw_model |
|
||||||
|
| `ROUTING_APP` | Fehlercode |
|
||||||
|
| `TRACEROUTE_APP` | Hop-Anzahl, Route |
|
||||||
|
| `NEIGHBORINFO_APP` | Anzahl Nachbarn |
|
||||||
|
|
||||||
|
### `meshbot/nina.py` — NinaBot
|
||||||
|
|
||||||
|
Integration des **NINA Warn-App des BBK** (Bundesamt für Bevölkerungsschutz und Katastrophenhilfe):
|
||||||
|
|
||||||
|
- **API-Basis:** `https://warnung.bund.de/api31`
|
||||||
|
- **Duales Polling** pro Zyklus:
|
||||||
|
1. **Dashboard-Endpunkt** (`/dashboard/{AGS12}.json`) — regionale Filterung durch den BBK-Server; bevorzugt wenn AGS-Codes konfiguriert
|
||||||
|
2. **mapData-Endpunkt** (`/{quelle}/mapData.json`) — bundesweit, nur aktiv wenn **keine** AGS-Codes konfiguriert
|
||||||
|
- **De-Duplikation:** ID-Normalisierung verhindert Doppelmeldungen (`dwdmap.` → `dwd.`, `mow.` → `mowas.` usw.)
|
||||||
|
- **Schweregrade:** Minor / Moderate / Severe (Standard) / Extreme
|
||||||
|
- **Quellen:** Katwarn, BIWAPP, MoWaS, DWD, LHP, Polizei (einzeln aktivierbar)
|
||||||
|
- **Monitor-Modus:** `send_to_mesh=false` → Weboberfläche empfängt Warnungen, kein Funk-Versand
|
||||||
|
- **Resend-Loop:** Aktive Warnungen werden in konfigurierbarem Abstand erneut gesendet
|
||||||
|
- **Hot-Reload:** Konfigurationsänderungen in `nina.yaml` werden live übernommen
|
||||||
|
- **AGS-Unterstützung:** Alle 13 sächsischen Landkreise / kreisfreie Städte mit lesbaren Namen
|
||||||
|
|
||||||
|
**Mesh-Nachrichtenformat:**
|
||||||
|
```
|
||||||
|
[NINA] Schwerwiegend: Sturmböen (Dresden, Stadt)
|
||||||
|
Beschreibung des Ereignisses (max. 120 Zeichen)...
|
||||||
|
|
||||||
|
[NINA] Aufgehoben: Sturmböen (Dresden, Stadt)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `meshbot/scheduler.py` — Scheduler
|
||||||
|
|
||||||
|
Zeitgesteuerte Bot-Aktionen via Cron-Ausdrücke:
|
||||||
|
|
||||||
|
- **Cron-Parser:** eigene Implementierung (keine externen Abhängigkeiten)
|
||||||
|
- Format: `Minute Stunde Tag Monat Wochentag`
|
||||||
|
- Unterstützt `*`, `*/N`, Einzelwerte und Kommalisten
|
||||||
|
- **Job-Typen:** `command` (Bot-Kommando) oder `message` (freier Text)
|
||||||
|
- **Template-Variablen** für Nachrichten-Jobs:
|
||||||
|
- `{time}`, `{date}`, `{datetime}`, `{weekday}`
|
||||||
|
- `{nodes}`, `{nodes_24h}` (live aus der DB)
|
||||||
|
- **Hot-Reload:** Änderungen in `scheduler.yaml` werden alle 2 Sekunden erkannt
|
||||||
|
- **CRUD-API:** Jobs können über die Weboberfläche angelegt, bearbeitet und gelöscht werden
|
||||||
|
|
||||||
|
### `meshbot/webserver.py` — WebServer
|
||||||
|
|
||||||
|
aiohttp-basierter HTTP- und WebSocket-Server:
|
||||||
|
|
||||||
|
- **WebSocketManager:** trennt `clients` (alle) von `auth_clients` (authentifiziert)
|
||||||
|
- **Initial-Payload bei WS-Verbindung:** Nodes, Stats, Channels, my_node_id, Bot-Status, letzte 200 Pakete, letzte 50 Nachrichten (nur auth)
|
||||||
|
- **broadcast vs. broadcast_auth:** Nachrichten und Warnmeldungen nur an authentifizierte Clients
|
||||||
|
|
||||||
|
### `meshbot/auth.py` — Authentifizierung
|
||||||
|
|
||||||
|
Session-basierte Authentifizierung mit E-Mail-Verifikation:
|
||||||
|
|
||||||
|
- **Passwort-Hashing:** bcrypt, 12 Runden, Mindestlänge 8 Zeichen
|
||||||
|
- **Session-Storage:** `EncryptedCookieStorage` (Fernet, AES-128-CBC)
|
||||||
|
- **Token-System:** UUID-Tokens für Verifikation und Passwort-Reset (24h gültig)
|
||||||
|
- **E-Mail-Versand:** aiosmtplib (TLS Port 465), Fallback: Link ins Server-Log
|
||||||
|
- **Rollen:** `public` (nicht eingeloggt), `user`, `admin`
|
||||||
|
- **Admin kann:** Benutzer anlegen/bearbeiten/löschen, Rollen ändern, manuell verifizieren, Passwörter zurücksetzen, Info-Mails versenden
|
||||||
|
|
||||||
|
### `meshbot/database.py` — Datenbank
|
||||||
|
|
||||||
|
SQLite via aiosqlite mit WAL-Modus für bessere Nebenläufigkeit:
|
||||||
|
|
||||||
|
| Tabelle | Inhalt |
|
||||||
|
|---|---|
|
||||||
|
| `nodes` | Alle bekannten Meshtastic-Nodes (ID, Name, HW, Position, Batterie, SNR, Hops) |
|
||||||
|
| `messages` | Empfangene und gesendete Textnachrichten |
|
||||||
|
| `commands` | Bot-Kommando-Protokoll pro Kanal |
|
||||||
|
| `packets` | Alle empfangenen Pakete mit Typ und Payload |
|
||||||
|
| `users` | Registrierte Web-Benutzer |
|
||||||
|
| `tokens` | Verifikations- und Reset-Tokens |
|
||||||
|
| `email_logs` | E-Mail-Versandprotokoll |
|
||||||
|
|
||||||
|
Automatische DB-Migration bei Schema-Änderungen (z.B. `channel`-Spalte in `commands`).
|
||||||
|
|
||||||
|
### `meshbot/config.py` — Konfiguration
|
||||||
|
|
||||||
|
Live-Reload-fähige Konfiguration aus `config.yaml`:
|
||||||
|
|
||||||
|
- Datei-Watcher prüft alle 5 Sekunden auf Änderungen
|
||||||
|
- Umgebungsvariablen über `config.env()` (für Secrets wie AUTH_SECRET_KEY, SMTP)
|
||||||
|
- Verschachtelte Keys per Punkt-Notation: `config.get("meshtastic.host")`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bot-Kommandos
|
||||||
|
|
||||||
|
Alle Kommandos beginnen mit dem konfigurierten Präfix (Standard: `?`).
|
||||||
|
|
||||||
|
| Kommando | Beschreibung |
|
||||||
|
|---|---|
|
||||||
|
| `?ping` | Antwortet mit „Pong" und Hop-Anzahl des Absenders |
|
||||||
|
| `?nodes` | Anzahl bekannter Nodes im Netz |
|
||||||
|
| `?info` | Bot-Name, Version und Uptime |
|
||||||
|
| `?help` | Liste aller Kommandos |
|
||||||
|
| `?stats` | Gesamt-Nodes, aktive Nodes (24h), Anfragen-Zähler |
|
||||||
|
| `?uptime` | Laufzeit des Bots |
|
||||||
|
| `?me` | Eigene Node-Infos (Name, HW, Hops, SNR, RSSI, Batterie, Position) |
|
||||||
|
| `?weather` | Aktuelles Wetter am eigenen Standort (open-meteo.com) |
|
||||||
|
| `?weather plz:XXXXX` | Wetter für deutsche Postleitzahl |
|
||||||
|
| `?mesh` | Mesh-Netzwerk-Übersicht (Online-Nodes, Hop-Verteilung, Top-Hardware) |
|
||||||
|
|
||||||
|
Lange Antworten werden automatisch gesplittet (`[1/3] ... [2/3] ... [3/3]`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Weboberfläche & Seiten
|
||||||
|
|
||||||
|
Alle Seiten verwenden ein einheitliches Layout: Tabler 1.4.0 (Bootstrap 5.3), fixed Top-Navbar (46px), Sidebar (200px), Content-Wrapper. Theme-Toggle (Hell/Dunkel) auf allen Seiten. Sidebar-Einträge für Admin-Bereiche werden per JS ausgeblendet wenn nicht admin.
|
||||||
|
|
||||||
|
### `/` — Dashboard (public: Nodes/Stats, user: Nachrichten/Senden)
|
||||||
|
|
||||||
|
- **Info-Boxen:** Nodes gesamt, aktiv (24h), Anfragen (24h), Bot-Uptime
|
||||||
|
- **Nodes-Tabelle:** Name, ID, HW, Hops, SNR, RSSI, Batterie, Zuletzt gesehen; Suchfeld, Online-Filter, sortierbar
|
||||||
|
- **Node-Detail-Modal:** Klick auf Node-Zeile öffnet Modal mit allen Feldern + Leaflet-Minikarte
|
||||||
|
- **Kanalfilter** in der Nachrichtenliste
|
||||||
|
- **Sende-Card** (user): Kanal-Dropdown + Textfeld → `POST /api/send`
|
||||||
|
- **Charts** (3 + 1):
|
||||||
|
- Kanal-Anfragen (Doughnut)
|
||||||
|
- Hop-Verteilung (Bar)
|
||||||
|
- Hardware Top-5 (Bar)
|
||||||
|
- Pakettypen 24h (Doughnut)
|
||||||
|
|
||||||
|
### `/map` — Karte (public)
|
||||||
|
|
||||||
|
- Leaflet.js mit Node-Markierungen
|
||||||
|
- **Farb-Codierung nach Hop-Anzahl:** Direkt=Grün, 1 Hop=Blau, 2 Hops=Orange, ≥3 Hops=Rot, via MQTT=Lila
|
||||||
|
- **Transparenz nach Alter:** <24h=90%, 24–48h=45%, 48–72h=20%, >72h=ausgeblendet
|
||||||
|
- **Kartenlegende** (topleft): Theme-aware, kompaktes Design mit HOPS- und ALTER-Sektionen
|
||||||
|
- **Dark/Light Tiles:** CartoDB Dark Matter / OpenStreetMap, wechselt live mit Theme
|
||||||
|
- **Tooltip** mit Node-Name, HW, Hops, Batterie, SNR beim Hover
|
||||||
|
|
||||||
|
### `/packets` — Paket-Log (public)
|
||||||
|
|
||||||
|
- Echtzeit-Tabelle aller empfangenen Pakete (max. 300 Einträge im Browser)
|
||||||
|
- Spalten: Zeit, Von, An, Typ, Kanal, SNR, RSSI, Hops, Info
|
||||||
|
- **Typ-Filterleiste** (farbige Pills, aktiv/inaktiv)
|
||||||
|
- **Pause- und Löschen-Funktion**
|
||||||
|
- Eigene Telemetrie-Pakete werden unterdrückt (`my_node_id` oder FTLW-Fallback)
|
||||||
|
- Informativer Info-Payload je Pakettyp
|
||||||
|
|
||||||
|
### `/scheduler` — Scheduler (admin)
|
||||||
|
|
||||||
|
- Jobs-Tabelle: Name, Cron-Ausdruck, Typ, Kommando/Nachricht, Kanal, Aktiv
|
||||||
|
- CRUD-Modals für Anlegen/Bearbeiten/Löschen
|
||||||
|
- Variablen-Badges (`{time}`, `{date}`, ...) klickbar im Nachrichten-Modus
|
||||||
|
|
||||||
|
### `/nina` — NINA-Warnmeldungen (admin)
|
||||||
|
|
||||||
|
- **Konfigurationskarte** mit allen NINA-Einstellungen (aktiviert, Send-to-Mesh, Intervalle, Kanal, Schweregrad, AGS-Codes, Quellen)
|
||||||
|
- **AGS-Code-Tabelle** mit Ortsname und Lösch-Button; Combobox mit allen sächsischen AGS-Codes
|
||||||
|
- **Status-Badge** (Aktiv/Deaktiviert, Regions-Anzahl, Mesh+Web/Nur Web)
|
||||||
|
- **Warnmeldungs-Tabelle:** Schweregrad-Badge, Headline, Gebiet, Typ, Mesh-Icon, Zeitstempel
|
||||||
|
- Aktive Warnungen werden beim Seitenaufruf sofort geladen (`GET /api/nina/alerts`)
|
||||||
|
- Neue Warnungen erscheinen live via WebSocket
|
||||||
|
|
||||||
|
### `/settings` — Node-Einstellungen (admin)
|
||||||
|
|
||||||
|
- Liest aktuelle Konfiguration vom lokalen Meshtastic-Node
|
||||||
|
- Zeigt: Gerät (Name, Firmware, HW-Modell, Node-Num), LoRa (Region, Preset, Hops, TX-Power), Kanäle, Position, Power, Bluetooth, Netzwerk
|
||||||
|
|
||||||
|
### `/admin` — Benutzerverwaltung (admin)
|
||||||
|
|
||||||
|
- Benutzertabelle mit Rolle, Verifikationsstatus, Erstellt-Datum
|
||||||
|
- Aktionen: Anlegen, Bearbeiten, Rolle ändern, Passwort zurücksetzen, verifizieren, löschen, Info-Mail senden
|
||||||
|
- Passwort-Generator in der UI
|
||||||
|
|
||||||
|
### `/login` + `/register` — Authentifizierung (public)
|
||||||
|
|
||||||
|
- Login / Registrierung / Passwort vergessen auf einer Seite
|
||||||
|
- E-Mail-Verifikationsflow: Token → Passwort setzen → Login
|
||||||
|
- Passwort-Reset-Flow analog
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## REST-API-Referenz
|
||||||
|
|
||||||
|
### Öffentliche Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `GET` | `/api/nodes` | Alle Nodes |
|
||||||
|
| `GET` | `/api/stats` | Statistiken + Version + Uptime |
|
||||||
|
| `GET` | `/api/packets` | Letzte Pakete (limit-Parameter) |
|
||||||
|
| `GET` | `/ws` | WebSocket-Verbindung |
|
||||||
|
|
||||||
|
### User-Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `GET` | `/api/auth/me` | Eigene Benutzerdaten |
|
||||||
|
| `GET` | `/api/messages` | Letzte Nachrichten |
|
||||||
|
| `POST` | `/api/send` | Nachricht senden |
|
||||||
|
|
||||||
|
### Admin-Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `GET` | `/api/node/config` | Node-Konfiguration lesen |
|
||||||
|
| `GET/POST` | `/api/scheduler/jobs` | Jobs lesen / anlegen |
|
||||||
|
| `PUT/DELETE` | `/api/scheduler/jobs/{name}` | Job bearbeiten / löschen |
|
||||||
|
| `GET` | `/api/nina/config` | NINA-Konfiguration lesen |
|
||||||
|
| `PUT` | `/api/nina/config` | NINA-Konfiguration speichern + Poll auslösen |
|
||||||
|
| `GET` | `/api/nina/alerts` | Aktuell aktive Warnmeldungen |
|
||||||
|
| `GET/POST` | `/api/admin/users` | Alle Benutzer / Anlegen |
|
||||||
|
| `PUT` | `/api/admin/users/{id}` | Benutzer bearbeiten |
|
||||||
|
| `DELETE` | `/api/admin/users/{id}` | Benutzer löschen |
|
||||||
|
| `POST` | `/api/admin/users/{id}/role` | Rolle ändern |
|
||||||
|
| `POST` | `/api/admin/users/{id}/verify` | Manuell verifizieren |
|
||||||
|
| `POST` | `/api/admin/users/{id}/reset-password` | Passwort zurücksetzen |
|
||||||
|
| `POST` | `/api/admin/users/{id}/send-info` | Info-Mail senden |
|
||||||
|
|
||||||
|
### Auth-Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `POST` | `/auth/login` | Einloggen |
|
||||||
|
| `POST` | `/auth/register` | Registrieren |
|
||||||
|
| `GET` | `/auth/logout` | Ausloggen |
|
||||||
|
| `GET` | `/auth/verify` | Verifikations-Link |
|
||||||
|
| `POST` | `/auth/set-password` | Passwort nach Verifikation setzen |
|
||||||
|
| `POST` | `/auth/forgot-password` | Passwort-Reset anfordern |
|
||||||
|
| `GET/POST` | `/auth/reset-password` | Passwort zurücksetzen |
|
||||||
|
|
||||||
|
### WebSocket-Events (Server → Client)
|
||||||
|
|
||||||
|
| Event | Inhalt | Auth |
|
||||||
|
|---|---|---|
|
||||||
|
| `initial` | Alle Nodes | alle |
|
||||||
|
| `stats_update` | Statistiken | alle |
|
||||||
|
| `channels` | Kanäle | alle |
|
||||||
|
| `my_node_id` | Eigene Node-ID | alle |
|
||||||
|
| `bot_status` | connected + uptime | alle |
|
||||||
|
| `initial_packets` | Letzte 200 Pakete | alle |
|
||||||
|
| `node_update` | Node-Daten (ein Node) | alle |
|
||||||
|
| `packet` | Neues Paket | alle |
|
||||||
|
| `initial_messages` | Letzte 50 Nachrichten | auth |
|
||||||
|
| `new_message` | Neue Nachricht | auth |
|
||||||
|
| `scheduler_update` | Jobs-Liste | alle |
|
||||||
|
| `nina_alert` | Neue Warnmeldung | alle |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zugriffsrechte
|
||||||
|
|
||||||
|
| Bereich | Public | User | Admin |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Dashboard (Nodes, Stats, Karte) | Ja | Ja | Ja |
|
||||||
|
| Paket-Log | Ja | Ja | Ja |
|
||||||
|
| Dashboard (Nachrichten, Senden) | Nein | Ja | Ja |
|
||||||
|
| Scheduler | Nein | Nein | Ja |
|
||||||
|
| NINA-Verwaltung | Nein | Nein | Ja |
|
||||||
|
| Node-Einstellungen | Nein | Nein | Ja |
|
||||||
|
| Benutzerverwaltung | Nein | Nein | Ja |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
### `config.yaml` — Hauptkonfiguration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "0.8.9"
|
||||||
|
|
||||||
|
bot:
|
||||||
|
name: "MeshDD-Bot"
|
||||||
|
command_prefix: "?" # Präfix für Bot-Kommandos
|
||||||
|
|
||||||
|
meshtastic:
|
||||||
|
host: "192.168.11.4" # IP des Meshtastic-Nodes
|
||||||
|
port: 4403 # TCP-Port
|
||||||
|
|
||||||
|
web:
|
||||||
|
host: "0.0.0.0" # Web-Server-Bindung
|
||||||
|
port: 8081 # Web-Server-Port
|
||||||
|
|
||||||
|
database:
|
||||||
|
path: "meshdd.db" # Pfad zur SQLite-DB
|
||||||
|
|
||||||
|
auth:
|
||||||
|
session_max_age: 86400 # Session-Gültigkeit in Sekunden
|
||||||
|
```
|
||||||
|
|
||||||
|
### `.env` — Secrets (Umgebungsvariablen)
|
||||||
|
|
||||||
|
```
|
||||||
|
AUTH_SECRET_KEY=change-this-secret-key-32bytes!!
|
||||||
|
SMTP_HOST=ssl0.example.com
|
||||||
|
SMTP_PORT=465
|
||||||
|
SMTP_USER=bot@example.com
|
||||||
|
SMTP_PASSWORD=secret
|
||||||
|
SMTP_FROM=MeshDD-Bot <bot@example.com>
|
||||||
|
SMTP_APP_URL=http://192.168.11.x:8081
|
||||||
|
```
|
||||||
|
|
||||||
|
Ohne `SMTP_HOST` werden Verifikationslinks ins Server-Log ausgegeben (kein E-Mail-Versand).
|
||||||
|
|
||||||
|
### `scheduler.yaml` — Scheduler-Jobs
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
- name: "tagesinfo"
|
||||||
|
enabled: true
|
||||||
|
cron: "0 8 * * *" # täglich 08:00
|
||||||
|
type: "message"
|
||||||
|
command: "Guten Morgen! Heute {weekday}, {date}. Aktive Nodes: {nodes_24h}"
|
||||||
|
channel: 0
|
||||||
|
- name: "morgen-ping"
|
||||||
|
enabled: false
|
||||||
|
cron: "0 7 * * 1-5" # Mo–Fr 07:00
|
||||||
|
type: "command"
|
||||||
|
command: "?ping"
|
||||||
|
channel: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cron-Felder:** `Minute(0-59) Stunde(0-23) Tag(1-31) Monat(1-12) Wochentag(0-6, 0=Sonntag)`
|
||||||
|
|
||||||
|
**Template-Variablen:** `{time}` `{date}` `{datetime}` `{weekday}` `{nodes}` `{nodes_24h}`
|
||||||
|
|
||||||
|
### `nina.yaml` — NINA-Konfiguration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
enabled: false
|
||||||
|
send_to_mesh: true
|
||||||
|
poll_interval: 300 # Abfrageintervall in Sekunden (min. 60)
|
||||||
|
resend_interval: 3600 # Wiederholungsintervall aktiver Warnungen
|
||||||
|
channel: 0 # Meshtastic-Kanal 0–7
|
||||||
|
min_severity: Severe # Minor | Moderate | Severe | Extreme
|
||||||
|
ags_codes:
|
||||||
|
- "146120000000" # Dresden, Stadt
|
||||||
|
- "146270000000" # Meißen
|
||||||
|
- "146280000000" # Sächsische Schweiz-Osterzgebirge
|
||||||
|
- "146250000000" # Bautzen
|
||||||
|
- "146260000000" # Görlitz
|
||||||
|
sources:
|
||||||
|
katwarn: true
|
||||||
|
biwapp: true
|
||||||
|
mowas: true
|
||||||
|
dwd: true
|
||||||
|
lhp: true
|
||||||
|
police: false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Datenbank
|
||||||
|
|
||||||
|
SQLite-Datei `meshdd.db` (konfigurierbar). WAL-Modus für bessere Nebenläufigkeit.
|
||||||
|
|
||||||
|
### Tabelle `nodes`
|
||||||
|
|
||||||
|
```sql
|
||||||
|
node_id TEXT PRIMARY KEY, -- z.B. "!1a2b3c4d"
|
||||||
|
node_num INTEGER, -- Dezimalzahl
|
||||||
|
long_name TEXT, -- Langer Name
|
||||||
|
short_name TEXT, -- Kurzname (4 Zeichen)
|
||||||
|
hw_model TEXT, -- Hardware-Modell
|
||||||
|
lat REAL, lon REAL, -- Position
|
||||||
|
alt REAL, -- Höhe in Metern
|
||||||
|
battery INTEGER, -- Akkustand 0–100%
|
||||||
|
voltage REAL, -- Spannung in Volt
|
||||||
|
snr REAL, -- Signal-Rausch-Abstand
|
||||||
|
rssi INTEGER, -- Empfangsstärke in dBm
|
||||||
|
last_seen REAL, -- Unix-Timestamp
|
||||||
|
first_seen REAL, -- Unix-Timestamp
|
||||||
|
hop_count INTEGER, -- Hops vom Bot
|
||||||
|
via_mqtt INTEGER -- 0 oder 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tabelle `packets`
|
||||||
|
|
||||||
|
```sql
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
timestamp REAL,
|
||||||
|
from_id TEXT, to_id TEXT,
|
||||||
|
portnum TEXT, -- z.B. "TEXT_MESSAGE_APP"
|
||||||
|
channel INTEGER,
|
||||||
|
snr REAL, rssi INTEGER,
|
||||||
|
hop_limit INTEGER, hop_start INTEGER,
|
||||||
|
packet_id INTEGER,
|
||||||
|
payload TEXT -- JSON-Zusammenfassung je Typ
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Systemd-Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Service-Datei installieren
|
||||||
|
sudo cp meshdd-bot.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable meshdd-bot
|
||||||
|
sudo systemctl start meshdd-bot
|
||||||
|
|
||||||
|
# Logs live verfolgen
|
||||||
|
journalctl -u meshdd-bot -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker / docker-compose
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Bauen und starten
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Stoppen
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
`docker-compose.yml` verwendet Host-Netzwerk (direkter TCP-Zugriff auf Meshtastic-Node), Named Volume für SQLite, JSON-File-Logging (10 MB / 3 Dateien) und Health-Check (`/api/stats` alle 30s).
|
||||||
|
|
||||||
|
### Direkt (Entwicklung)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/peter/MeshDD-Bot
|
||||||
|
source venv/bin/activate
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wichtige Erweiterungsschritte
|
||||||
|
|
||||||
|
Die folgende Tabelle zeigt die wichtigsten Entwicklungsmeilensteine von der ersten Version bis heute:
|
||||||
|
|
||||||
|
| Version | Datum | Erweiterungsschritt |
|
||||||
|
|---|---|---|
|
||||||
|
| **0.1.0** | 2026-02-15 | **Grundgerüst:** Meshtastic TCP-Bot, SQLite-DB, Web-Dashboard mit WebSocket, Leaflet-Karte, Bot-Kommandos (ping, nodes, info, help, weather, stats, uptime) |
|
||||||
|
| **0.2.0** | 2026-02-15 | **Konfiguration & Karte:** Zentrale `config.yaml` mit Live-Reload, Hop-Farbcodierung auf der Karte, Theme-Toggle (Hell/Dunkel), Kanalnamen in Nachrichten |
|
||||||
|
| **0.2.5** | 2026-02-15 | **Nachrichten-Splitting:** Automatisches Aufteilen langer Nachrichten mit `[x/y]`-Nummerierung und Pause |
|
||||||
|
| **0.3.1** | 2026-02-15 | **Scheduler:** Zeitgesteuerte Bot-Kommandos via Cron-Ausdrücke, `scheduler.yaml` mit File-Watcher, REST-CRUD-API, Live-Updates via WebSocket |
|
||||||
|
| **0.3.2** | 2026-02-15 | **Nachrichten senden:** Direktes Senden aus dem Dashboard (`POST /api/send`); Scheduler-Typ „Nachricht" |
|
||||||
|
| **0.3.5** | 2026-02-15 | **AdminLTE-Layout:** Einheitliches Sidebar-Layout für alle Seiten mit Active-State |
|
||||||
|
| **0.3.6** | 2026-02-15 | **Node-Einstellungen:** `/settings`-Seite liest Gerät, LoRa, Kanäle, Position, Power, Bluetooth via Protobuf vom Node |
|
||||||
|
| **0.4.0** | 2026-02-16 | **UX-Verbesserungen:** `?me`-Kommando, Ping mit Hop-Anzahl, PLZ-Support fürs Wetter, Luftdruck & Taupunkt, gesendete Nachrichten im Dashboard |
|
||||||
|
| **0.5.0** | 2026-02-16 | **Benutzerverwaltung:** Session-Auth mit bcrypt, E-Mail-Verifikation, Rollen (public/user/admin), Admin-Panel, Passwort-Reset |
|
||||||
|
| **0.5.3** | 2026-02-16 | **Secrets in .env:** AUTH_SECRET_KEY und SMTP-Einstellungen aus config.yaml in Umgebungsvariablen ausgelagert |
|
||||||
|
| **0.5.4** | 2026-02-16 | **Admin erweitert:** Benutzer direkt anlegen mit Passwort, Bearbeiten-Modal, Passwort-Reset, Passwort-Generator |
|
||||||
|
| **0.6.0** | 2026-02-17 | **Node-Detail-Modal:** Klick auf Node → Modal mit allen Feldern + Leaflet-Minikarte |
|
||||||
|
| **0.6.1** | 2026-02-17 | **Docker-Support:** Dockerfile, docker-compose.yml, .dockerignore |
|
||||||
|
| **0.6.2** | 2026-02-17 | **Geteiltes app.js:** ~360 Zeilen duplizierten Frontend-Code in gemeinsames Modul extrahiert |
|
||||||
|
| **0.6.3** | 2026-02-17 | **WebSocket-Sicherheit:** `auth_clients` vs. `clients` — Nachrichten nur an authentifizierte WS-Clients |
|
||||||
|
| **0.6.5** | 2026-02-17 | **Dark-Mode-Karte + Charts:** CartoDB Dark Matter, 3 Charts (Kanal, Hops, Hardware) |
|
||||||
|
| **0.6.7** | 2026-02-17 | **Tabler 1.4.0:** Professionelleres CSS-Framework, überarbeitetes style.css |
|
||||||
|
| **0.6.10** | 2026-02-18 | **Paket-Log:** Neue `/packets`-Seite, `packets`-Tabelle in DB, Typ-Filter, Echtzeit via WebSocket |
|
||||||
|
| **0.6.13** | 2026-02-18 | **Karten-Alter-Transparenz:** Nodes >72h werden ausgeblendet; Legende mit Alter-Sektion |
|
||||||
|
| **0.6.14** | 2026-02-18 | **Pakettypen-Chart:** Viertes Doughnut-Chart mit Pakettyp-Verteilung 24h |
|
||||||
|
| **0.6.15** | 2026-02-18 | **Scheduler Template-Variablen:** `{time}`, `{date}`, `{weekday}`, `{nodes}` etc.; Footer auf allen Seiten |
|
||||||
|
| **0.7.0** | 2026-02-18 | **Docker-Verbesserungen:** HEALTHCHECK, Logging-Config, korrigierter Port |
|
||||||
|
| **0.8.0** | 2026-02-19 | **NINA-Integration:** BBK Warn-App angebunden; duales Polling (Dashboard + mapData); Konfigurationsseite; Monitor-Modus; Live-Tabelle via WebSocket |
|
||||||
|
| **0.8.1** | 2026-02-19 | **NINA Resend-Loop:** Aktive Warnungen werden zyklisch wiederholt; AGS-Code-Tabelle statt Badges |
|
||||||
|
| **0.8.2** | 2026-02-19 | **NINA geografische Filterung:** mapData nur noch ohne AGS-Codes aktiv (verhindert bundesweite Meldungen) |
|
||||||
|
| **0.8.3** | 2026-02-19 | **NINA Gebietsanzeige:** Regionsname aus AGS-Labels in Meldung und Mesh-Text; Sachsen-Combobox |
|
||||||
|
| **0.8.4** | 2026-02-19 | **NINA Sofortabfrage:** Nach Speichern der Config sofort pollen; `last_poll`-Zeitstempel anzeigen |
|
||||||
|
| **0.8.5** | 2026-02-19 | **Kartenlegende Position:** von bottomright nach topleft verschoben |
|
||||||
|
| **0.8.6** | 2026-02-19 | **Paket-Log informativer:** Erweiterte Payload-Zusammenfassung; eigene Telemetrie unterdrückt |
|
||||||
|
| **0.8.7** | 2026-02-19 | **Race-Condition-Fix:** `threading.Event` verhindert falsche Startup-Warning „connection.established missed" |
|
||||||
|
| **0.8.8** | 2026-02-19 | **Kartenlegende neu gestaltet:** Theme-aware CSS-Variablen, kompaktes Design |
|
||||||
|
| **0.8.9** | 2026-02-19 | **NINA aktive Warnungen:** `GET /api/nina/alerts` gibt beim Seitenaufruf alle aktiven Warnungen zurück |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*MeshDD-Bot — entwickelt für das Dresdner Meshtastic-Netz · © MeshDD / PPfeiffer*
|
||||||
205
docs/whats-new-0.8.md
Normal file
205
docs/whats-new-0.8.md
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
# Was ist neu in MeshDD-Bot 0.8.x
|
||||||
|
|
||||||
|
> Aktueller Stand: **v0.8.9** · Release-Datum: 2026-02-19
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
Release 0.8 bringt die vollständige Integration des **NINA BBK Warnsystems** in den
|
||||||
|
MeshDD-Bot, ergänzt um eine Reihe von Verbesserungen am Paket-Log, der Karte und der
|
||||||
|
Verbindungsinitialisierung.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Neue Funktionen
|
||||||
|
|
||||||
|
### NINA Warnmeldungs-Integration (`/nina`)
|
||||||
|
|
||||||
|
Der Bot ist jetzt an die **NINA Warn-App des BBK** (Bundesamt für Bevölkerungsschutz
|
||||||
|
und Katastrophenhilfe) angebunden. Warnmeldungen werden automatisch per HTTP-Polling
|
||||||
|
von `warnung.bund.de/api31` abgerufen und ins Meshtastic-Netz gesendet.
|
||||||
|
|
||||||
|
#### Konfigurationsseite
|
||||||
|
|
||||||
|
Unter `/nina` (Admin-only) steht eine vollständige Verwaltungsseite bereit:
|
||||||
|
|
||||||
|
| Einstellung | Beschreibung |
|
||||||
|
|---|---|
|
||||||
|
| **Aktiviert** | NINA-Abfragen ein-/ausschalten |
|
||||||
|
| **Ins Mesh senden** | Aus = Monitor-Modus (nur Weboberfläche, kein Mesh-Versand) |
|
||||||
|
| **Abfrageintervall** | Wie oft neue Warnmeldungen abgerufen werden (Sek., min. 60) |
|
||||||
|
| **Wiederholungsintervall** | Aktive Warnungen werden in diesem Abstand erneut ins Mesh gesendet |
|
||||||
|
| **Kanal** | Meshtastic-Kanal (0–7) für den Versand |
|
||||||
|
| **Mindest-Schweregrad** | Gering / Mäßig / Schwerwiegend / Extrem |
|
||||||
|
| **AGS-Codes** | Amtliche Gemeindeschlüssel der zu überwachenden Regionen |
|
||||||
|
| **Quellen** | Katwarn, BIWAPP, MoWaS, DWD, LHP, Polizei |
|
||||||
|
|
||||||
|
#### AGS-Code-Verwaltung
|
||||||
|
|
||||||
|
- AGS-Codes werden in einer **Tabelle** mit Ortsname und Lösch-Button angezeigt
|
||||||
|
- Bei der Eingabe schlägt eine **Combobox** alle sächsischen Landkreise und kreisfreien
|
||||||
|
Städte vor (Name + 12-stelliger Code)
|
||||||
|
- Voreingestellt: 5 Codes für den **Raum Dresden** (Stadt Dresden, LK Meißen,
|
||||||
|
LK Sächsische Schweiz-Osterzgebirge, LK Bautzen, LK Görlitz)
|
||||||
|
|
||||||
|
#### Polling-Strategie
|
||||||
|
|
||||||
|
Zwei parallele Abfragestrategien pro Zyklus:
|
||||||
|
|
||||||
|
1. **Dashboard-Endpunkt** (`/dashboard/{AGS12}.json`) — regionale Filterung durch den
|
||||||
|
BBK-Server; deckt alle Quellen für konfigurierte AGS-Codes ab.
|
||||||
|
2. **mapData-Endpunkt** (`/{quelle}/mapData.json`) — wird **nur verwendet, wenn keine
|
||||||
|
AGS-Codes konfiguriert sind** (bundesweite Abfrage ohne Geo-Filterung).
|
||||||
|
|
||||||
|
Quellenübergreifende **De-Duplikation** via ID-Normalisierung verhindert doppelte
|
||||||
|
Meldungen (z. B. `dwdmap.` ↔ `dwd.`, `mow.` ↔ `mowas.`).
|
||||||
|
|
||||||
|
#### Warnmeldungen im Mesh
|
||||||
|
|
||||||
|
Nachrichten-Format im Meshtastic-Netz:
|
||||||
|
|
||||||
|
```
|
||||||
|
[NINA] Schwerwiegend: Sturmböen (Dresden, Stadt)
|
||||||
|
Beschreibung des Ereignisses (max. 120 Zeichen)...
|
||||||
|
|
||||||
|
[NINA] Aufgehoben: Sturmböen (Dresden, Stadt)
|
||||||
|
```
|
||||||
|
|
||||||
|
Das **Herkunftsgebiet** (AGS-Regionsname) wird automatisch an Meldung und Aufhebung
|
||||||
|
angehängt.
|
||||||
|
|
||||||
|
#### Live-Anzeige in der Weboberfläche
|
||||||
|
|
||||||
|
Die Tabelle „Letzte Warnmeldungen" zeigt:
|
||||||
|
|
||||||
|
| Spalte | Inhalt |
|
||||||
|
|---|---|
|
||||||
|
| **Schweregrad** | Farbiger Badge (Extrem / Schwerwiegend / Mäßig / Gering / Aufgehoben) |
|
||||||
|
| **Meldung** | Headline der Warnung |
|
||||||
|
| **Gebiet** | AGS-Regionsname (z. B. „Dresden, Stadt") |
|
||||||
|
| **Typ** | Quell-Präfix (z. B. `dwd`, `katwarn`) |
|
||||||
|
| **Mesh** | Broadcast-Icon (gesendet) oder Auge-Icon (Monitor-Only) |
|
||||||
|
| **Zeitstempel** | Sendezeitpunkt der Warnung |
|
||||||
|
|
||||||
|
Beim Seitenaufruf werden alle **aktuell aktiven Warnungen** sofort geladen
|
||||||
|
(`GET /api/nina/alerts`). Neue Warnungen erscheinen live via WebSocket.
|
||||||
|
|
||||||
|
#### Sofortabfrage nach dem Speichern
|
||||||
|
|
||||||
|
Nach dem Klick auf „Speichern" wird unmittelbar eine NINA-Abfrage gestartet — kein
|
||||||
|
Warten auf den nächsten Intervall-Zyklus. Unterhalb des Abfrageintervall-Felds wird
|
||||||
|
Datum und Uhrzeit der **letzten erfolgreichen Abfrage** angezeigt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verbesserungen am Paket-Log (`/packets`)
|
||||||
|
|
||||||
|
### Informativerer Payload
|
||||||
|
|
||||||
|
Die Info-Spalte zeigt jetzt deutlich mehr Daten je Pakettyp:
|
||||||
|
|
||||||
|
| Typ | Angezeigte Felder |
|
||||||
|
|---|---|
|
||||||
|
| `POSITION_APP` | Koordinaten + Höhe (m), Geschwindigkeit (km/h), Satelliten |
|
||||||
|
| `TELEMETRY_APP` | Akku (%), Spannung (V), Kanalauslastung (%), TX-Auslastung (%), Temperatur (°C), Luftfeuchtigkeit (%), Luftdruck (hPa) |
|
||||||
|
| `NODEINFO_APP` | long_name, short_name, Hardware-Modell |
|
||||||
|
| `ROUTING_APP` | Fehlercode (wenn vorhanden) |
|
||||||
|
| `TRACEROUTE_APP` | Anzahl Hops |
|
||||||
|
| `NEIGHBORINFO_APP` | Anzahl Nachbarn |
|
||||||
|
|
||||||
|
### Unterdrückung eigener Telemetrie
|
||||||
|
|
||||||
|
Telemetriepakete vom **eigenen Node** werden im Paket-Log weder angezeigt noch gezählt.
|
||||||
|
Die Erkennung erfolgt automatisch per `my_node_id` (WebSocket-Initial-Payload) sowie als
|
||||||
|
Fallback über den Short-Name `FTLW`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verbesserungen an der Karte (`/map`)
|
||||||
|
|
||||||
|
### Neue Legendenposition
|
||||||
|
|
||||||
|
Die Kartenlegende wurde von `bottomright` nach **`topleft`** verschoben — direkt
|
||||||
|
unterhalb der Zoom-Schaltfläche, wo sie auf allen Bildschirmgrößen sicher sichtbar ist.
|
||||||
|
|
||||||
|
### Neues Legengendesign
|
||||||
|
|
||||||
|
Die Legende wurde komplett neu gestaltet:
|
||||||
|
|
||||||
|
- **Theme-aware**: passt sich automatisch Light- und Dark-Mode an (CSS-Variablen)
|
||||||
|
- **Kompaktes Layout**: kleine Uppercase-Abschnittsköpfe (`HOPS` / `ALTER`)
|
||||||
|
- **Weicherer Schatten** und dezentes Border
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
### Startup-Warning „connection.established missed" (fixes #2)
|
||||||
|
|
||||||
|
Beim Start erschien regelmäßig eine Warnung im Log:
|
||||||
|
|
||||||
|
```
|
||||||
|
[WARNING] meshbot.bot: connection.established missed – applying fallback
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ursache:** `bot.connect()` läuft in einem separaten Thread. Der `TCPInterface`-Konstruktor
|
||||||
|
kehrte zurück, bevor das `connection.established`-Event aus dem Meshtastic-Bibliotheks-Thread
|
||||||
|
gefeuert wurde. Der sofortige Check sah `_connected = False` und löste den Fallback aus.
|
||||||
|
|
||||||
|
**Fix:** Ein `threading.Event` (`_conn_event`) wird in `_on_connection` gesetzt.
|
||||||
|
Nach dem Konstruktor wartet der Code bis zu 10 Sekunden auf dieses Event. Der
|
||||||
|
Fallback greift nur noch bei echtem Ausbleiben.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfigurationsdateien
|
||||||
|
|
||||||
|
### `nina.yaml`
|
||||||
|
|
||||||
|
Separate Hot-reload-fähige Konfigurationsdatei für NINA (analog zu `scheduler.yaml`).
|
||||||
|
Wird automatisch angelegt wenn nicht vorhanden.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
enabled: false
|
||||||
|
send_to_mesh: true
|
||||||
|
poll_interval: 300 # Sekunden, min. 60
|
||||||
|
resend_interval: 3600 # Sekunden, Wiederholung aktiver Warnungen
|
||||||
|
channel: 0 # Meshtastic-Kanal 0–7
|
||||||
|
min_severity: Severe # Minor | Moderate | Severe | Extreme
|
||||||
|
ags_codes: []
|
||||||
|
sources:
|
||||||
|
katwarn: true
|
||||||
|
biwapp: true
|
||||||
|
mowas: true
|
||||||
|
dwd: true
|
||||||
|
lhp: true
|
||||||
|
police: false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Neue API-Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung | Auth |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `GET` | `/api/nina/config` | NINA-Konfiguration lesen | Admin |
|
||||||
|
| `PUT` | `/api/nina/config` | NINA-Konfiguration speichern + Poll auslösen | Admin |
|
||||||
|
| `GET` | `/api/nina/alerts` | Aktuell aktive Warnmeldungen | Admin |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Versionshistorie 0.8.x
|
||||||
|
|
||||||
|
| Version | Datum | Schwerpunkt |
|
||||||
|
|---|---|---|
|
||||||
|
| 0.8.0 | 2026-02-19 | NINA-Integration (Grundfunktion) |
|
||||||
|
| 0.8.1 | 2026-02-19 | Wiederholungsintervall, AGS-Tabelle, Badge-Fixes |
|
||||||
|
| 0.8.2 | 2026-02-19 | mapData nur ohne AGS-Codes (geografische Filterung) |
|
||||||
|
| 0.8.3 | 2026-02-19 | Gebietsanzeige, AGS-Ortsname, Sachsen-Combobox |
|
||||||
|
| 0.8.4 | 2026-02-19 | Sofortabfrage nach Speichern, Zeitstempel letzte Abfrage |
|
||||||
|
| 0.8.5 | 2026-02-19 | Kartenlegende nach topleft verschoben (fixes #5) |
|
||||||
|
| 0.8.6 | 2026-02-19 | Informativer Paket-Payload, FTLW-Telemetrie unterdrückt (fixes #3) |
|
||||||
|
| 0.8.7 | 2026-02-19 | threading.Event-Fix für Startup-Warning (fixes #2) |
|
||||||
|
| 0.8.8 | 2026-02-19 | Kartenlegende neu gestaltet (theme-aware) |
|
||||||
|
| 0.8.9 | 2026-02-19 | Aktive NINA-Warnungen beim Seitenaufruf laden |
|
||||||
Loading…
Reference in a new issue