Alle eigenen Projektversionsnummern wurden auf das neue Format umgeschrieben: 0.X.Y → 0.XX.YY (z.B. 0.8.11 → 0.08.11, 0.6.7 → 0.06.07) Betrifft 130 Zeilen in 9 Dateien; externe Bibliotheksversionen unverändert. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
598 lines
25 KiB
Markdown
598 lines
25 KiB
Markdown
# MeshDD-Bot — Vollständige Beschreibung
|
||
|
||
> Aktueller Stand: **v0.08.09** · 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.08.09"
|
||
|
||
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.01.00** | 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.02.00** | 2026-02-15 | **Konfiguration & Karte:** Zentrale `config.yaml` mit Live-Reload, Hop-Farbcodierung auf der Karte, Theme-Toggle (Hell/Dunkel), Kanalnamen in Nachrichten |
|
||
| **0.02.05** | 2026-02-15 | **Nachrichten-Splitting:** Automatisches Aufteilen langer Nachrichten mit `[x/y]`-Nummerierung und Pause |
|
||
| **0.03.01** | 2026-02-15 | **Scheduler:** Zeitgesteuerte Bot-Kommandos via Cron-Ausdrücke, `scheduler.yaml` mit File-Watcher, REST-CRUD-API, Live-Updates via WebSocket |
|
||
| **0.03.02** | 2026-02-15 | **Nachrichten senden:** Direktes Senden aus dem Dashboard (`POST /api/send`); Scheduler-Typ „Nachricht" |
|
||
| **0.03.05** | 2026-02-15 | **AdminLTE-Layout:** Einheitliches Sidebar-Layout für alle Seiten mit Active-State |
|
||
| **0.03.06** | 2026-02-15 | **Node-Einstellungen:** `/settings`-Seite liest Gerät, LoRa, Kanäle, Position, Power, Bluetooth via Protobuf vom Node |
|
||
| **0.04.00** | 2026-02-16 | **UX-Verbesserungen:** `?me`-Kommando, Ping mit Hop-Anzahl, PLZ-Support fürs Wetter, Luftdruck & Taupunkt, gesendete Nachrichten im Dashboard |
|
||
| **0.05.00** | 2026-02-16 | **Benutzerverwaltung:** Session-Auth mit bcrypt, E-Mail-Verifikation, Rollen (public/user/admin), Admin-Panel, Passwort-Reset |
|
||
| **0.05.03** | 2026-02-16 | **Secrets in .env:** AUTH_SECRET_KEY und SMTP-Einstellungen aus config.yaml in Umgebungsvariablen ausgelagert |
|
||
| **0.05.04** | 2026-02-16 | **Admin erweitert:** Benutzer direkt anlegen mit Passwort, Bearbeiten-Modal, Passwort-Reset, Passwort-Generator |
|
||
| **0.06.00** | 2026-02-17 | **Node-Detail-Modal:** Klick auf Node → Modal mit allen Feldern + Leaflet-Minikarte |
|
||
| **0.06.01** | 2026-02-17 | **Docker-Support:** Dockerfile, docker-compose.yml, .dockerignore |
|
||
| **0.06.02** | 2026-02-17 | **Geteiltes app.js:** ~360 Zeilen duplizierten Frontend-Code in gemeinsames Modul extrahiert |
|
||
| **0.06.03** | 2026-02-17 | **WebSocket-Sicherheit:** `auth_clients` vs. `clients` — Nachrichten nur an authentifizierte WS-Clients |
|
||
| **0.06.05** | 2026-02-17 | **Dark-Mode-Karte + Charts:** CartoDB Dark Matter, 3 Charts (Kanal, Hops, Hardware) |
|
||
| **0.06.07** | 2026-02-17 | **Tabler 1.4.0:** Professionelleres CSS-Framework, überarbeitetes style.css |
|
||
| **0.06.10** | 2026-02-18 | **Paket-Log:** Neue `/packets`-Seite, `packets`-Tabelle in DB, Typ-Filter, Echtzeit via WebSocket |
|
||
| **0.06.13** | 2026-02-18 | **Karten-Alter-Transparenz:** Nodes >72h werden ausgeblendet; Legende mit Alter-Sektion |
|
||
| **0.06.14** | 2026-02-18 | **Pakettypen-Chart:** Viertes Doughnut-Chart mit Pakettyp-Verteilung 24h |
|
||
| **0.06.15** | 2026-02-18 | **Scheduler Template-Variablen:** `{time}`, `{date}`, `{weekday}`, `{nodes}` etc.; Footer auf allen Seiten |
|
||
| **0.07.00** | 2026-02-18 | **Docker-Verbesserungen:** HEALTHCHECK, Logging-Config, korrigierter Port |
|
||
| **0.08.00** | 2026-02-19 | **NINA-Integration:** BBK Warn-App angebunden; duales Polling (Dashboard + mapData); Konfigurationsseite; Monitor-Modus; Live-Tabelle via WebSocket |
|
||
| **0.08.01** | 2026-02-19 | **NINA Resend-Loop:** Aktive Warnungen werden zyklisch wiederholt; AGS-Code-Tabelle statt Badges |
|
||
| **0.08.02** | 2026-02-19 | **NINA geografische Filterung:** mapData nur noch ohne AGS-Codes aktiv (verhindert bundesweite Meldungen) |
|
||
| **0.08.03** | 2026-02-19 | **NINA Gebietsanzeige:** Regionsname aus AGS-Labels in Meldung und Mesh-Text; Sachsen-Combobox |
|
||
| **0.08.04** | 2026-02-19 | **NINA Sofortabfrage:** Nach Speichern der Config sofort pollen; `last_poll`-Zeitstempel anzeigen |
|
||
| **0.08.05** | 2026-02-19 | **Kartenlegende Position:** von bottomright nach topleft verschoben |
|
||
| **0.08.06** | 2026-02-19 | **Paket-Log informativer:** Erweiterte Payload-Zusammenfassung; eigene Telemetrie unterdrückt |
|
||
| **0.08.07** | 2026-02-19 | **Race-Condition-Fix:** `threading.Event` verhindert falsche Startup-Warning „connection.established missed" |
|
||
| **0.08.08** | 2026-02-19 | **Kartenlegende neu gestaltet:** Theme-aware CSS-Variablen, kompaktes Design |
|
||
| **0.08.09** | 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*
|