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:
ppfeiffer 2026-02-19 17:53:39 +01:00
parent f36a126200
commit 79f80563c8
2 changed files with 802 additions and 0 deletions

597
docs/bot-beschreibung.md Normal file
View 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%, 2448h=45%, 4872h=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" # MoFr 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 07
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 0100%
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
View 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 (07) 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 07
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 |