MeshDD-Bot/CHANGELOG.md
ppfeiffer fa03bcaac2 release: v0.09.00 – Mitarbeiter-Rolle, /config-Seite, Paket-Log-Filter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 23:01:46 +01:00

811 lines
36 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Changelog
## [0.09.00] - 2026-02-20
### Summary
Release 0.9 konsolidiert alle seit v0.08.15 eingeführten Erweiterungen und bündelt
sie als neues Minor-Release. Schwerpunkte: neues Rollensystem (Mitarbeiter),
Konfigurationsseite im Dashboard, erweitertes Paket-Log, strukturelle Bereinigungen.
### Added
- **Rollensystem Mitarbeiter** (closes #7): Neue Rolle `mitarbeiter` ersetzt `user`
vollständig. Einladungs-Workflow per E-Mail mit auto-generiertem Passwort und
Pflicht-Passwortwechsel beim ersten Login. Neue Seite `/auth/change-password`.
- **Konfigurationsseite `/config`** (closes #4): Bearbeitbare Bot-, Meshtastic-,
Web- und Links-Einstellungen direkt im Dashboard (Admin). `config.py`: `save()`.
- **Paket-Log: Erweiterte Filterzeile** (closes #6): Von, An, Kanal-Dropdown,
Hops-Maximum und Freitext alle Filter kombiniert (AND-Logik).
- **Initialer Admin-User**: Erster Start ohne Datenbank legt automatisch
`admin@localhost` / `changeme` an (verifiziert, Passwort-Änderung empfohlen).
- **Sidebar: Konfigurationen-Gruppe**: Gruppenüberschrift mit eingerückten
Untereinträgen (Scheduler, NINA, Einstellungen) für Staff-Mitglieder.
### Changed
- **Umbenennung MeshDD-Bot → MeshDD-Dashboard** (closes #4): Alle Seiten-Titel
und Navbar-Texte aktualisiert.
- **NINA-Verbesserungen** (closes #2): Quellenkennung (`[DWD@NINA]` etc.),
Schalter nebeneinander, Intervalle in Minuten, `last_sent`-Anzeige.
- **Konfiguration konsolidiert**: Alle Config-Dateien in `config/`, `.env` in
`config.yaml` integriert keine separate Secrets-Datei mehr nötig.
- **Datenbank in `data/`**: SQLite-Datei nach `data/meshdd.db` verschoben;
WAL-Checkpoint beim Schließen; isolierter Shutdown (jeder Schritt try/except).
- **API-Auth**: `/api/send`, `/api/node/config`, `/api/nina/*`, `GET /api/scheduler/jobs`
nutzen `require_staff_api` (Mitarbeiter + Admin).
- **Scheduler/NINA read-only für Mitarbeiter**: Schaltflächen und Eingaben gesperrt,
Badge „Nur Lesezugriff".
- **Docker entfernt**: `Dockerfile`, `docker-compose.yml`, `.dockerignore` gelöscht;
Deployment ausschließlich per systemd-Service.
### Fixed
- **Karte: Legende theme-aware** (closes #5): CSS-Variablen + JS-Inline-Styles
für zuverlässige Light/Dark-Umschaltung im Leaflet-Control-Kontext.
- **Dashboard**: `channelBreakdown`-Card entfernt; Nachrichten-Trenner stärker
(closes #1).
- **`upsert_node` Race-Condition**: `INSERT OR IGNORE` + `UPDATE` statt
SELECT → INSERT kein `UNIQUE constraint failed` mehr bei gleichzeitigen Updates.
## [0.08.26] - 2026-02-20
### Added
- **Rolle Mitarbeiter + Einladungs-Workflow** (closes #7):
- Neues Rollensystem: Public → Mitarbeiter → Admin (Rolle `user` entfällt).
- DB-Migration: `must_change_password`-Spalte, bestehende `user`→`mitarbeiter`.
- `require_staff_api()`: erlaubt `mitarbeiter` + `admin`.
- `POST /api/admin/invite`: Admin lädt Mitarbeiter ein; Passwort auto-generiert
(12 Zeichen), E-Mail mit Login-URL und Passwort-Änderungspflicht.
- `POST /auth/change-password`: Pflicht-Passwortwechsel für eingeladene Accounts.
- Neue Seite `/auth/change-password` (`change-password.html`).
- Login-Redirect: `force_password_change=true``/auth/change-password`.
- Admin-Seite: Button „Mitarbeiter einladen" ersetzt „Neuer Benutzer".
### Changed
- **Sidebar**: `sidebar-staff`-Klasse statt `sidebar-user/admin` für Scheduler,
NINA, Einstellungen (sichtbar für Mitarbeiter + Admin). Benutzer-Link nur Admin.
- **API-Auth**: `/api/send`, `/api/node/config`, `/api/nina/config`,
`/api/nina/alerts`, `GET /api/scheduler/jobs` jetzt `require_staff_api`.
- **Scheduler**: Neue-Job/Bearbeiten/Löschen-Buttons deaktiviert für Mitarbeiter
(Nur Lesezugriff-Badge).
- **NINA**: Alle Eingabefelder und Speichern-Button deaktiviert für Mitarbeiter.
## [0.08.25] - 2026-02-20
### Added
- **Paket-Log: Erweiterte Filterzeile** (closes #6): Unterhalb des Typ-Filters
neue Zeile mit Von, An, Kanal-Dropdown, Hops-Maximalwert und Freitextsuche.
Alle Filter wirken kombiniert (AND-Logik). Reset-Button (✕) setzt alle
Zusatzfilter zurück. `buildRow()` befüllt `data-from/to/channel/hops/search`
für performante DOM-Filterung ohne Re-Render.
## [0.08.24] - 2026-02-20
### Added
- **Sidebar: Konfigurationen-Gruppe** (closes #4 Aufgabe 12): Neue Gruppenüberschrift
mit eingerückten Untereinträgen für Scheduler, NINA und Konfiguration.
CSS-Klassen `.sidebar-group-label` und `.sidebar-link-sub` ergänzt.
- **Neue Seite `/config`** (closes #4 Aufgabe 34): Bearbeitbare Bot-Konfiguration
(Bot, Meshtastic, Web, Links). `GET/PUT /api/config` (Admin).
`config.py`: `save()`-Funktion für persistentes Schreiben in `config.yaml`.
### Changed
- **Umbenennung MeshDD-Bot → MeshDD-Dashboard** (closes #4 Aufgabe 5):
Alle HTML-Seiten (`<title>` + Navbar-Text) umbenannt.
## [0.08.23] - 2026-02-20
### Fixed
- **Karte: Legende theme-aware** (closes #5): `.legend` nutzt jetzt
`var(--tblr-bg-surface/border-color/body-color)` statt hardcodierter Farben.
`map.js` speichert die Legende als `legendDiv` und aktualisiert per
`updateLegendTheme()` Inline-Styles beim Init und bei jedem `themechange`-Event
zuverlässig auch im Leaflet-Control-Kontext.
## [0.08.22] - 2026-02-20
### Changed
- **NINA Quellenkennung** (closes #2 Aufgabe 1): Präfix `[NINA]``[DWD@NINA]`,
`[KATWARN@NINA]` usw. je nach Warnquelle.
- **NINA Schalter nebeneinander** (closes #2 Aufgabe 2): "Aktiviert" und
"Ins Mesh senden" liegen jetzt in einer Zeile nebeneinander.
- **NINA Intervalle in Minuten** (closes #2 Aufgabe 3): UI zeigt und speichert
Abfrage- und Wiederholungsintervall in Minuten (intern weiterhin Sekunden).
### Added
- **NINA Zuletzt gesendet** (closes #2 Aufgabe 4): Neues Feld unter dem
Abfrageintervall zeigt, wann zuletzt eine Meldung ins Mesh gesendet wurde.
## [0.08.21] - 2026-02-20
### Changed
- **Dashboard**: `channelBreakdown`-Card entfernt (closes #1 Aufgabe 1).
- **Nachrichten-Seite**: Trenner zwischen Nachrichten stärker
Padding `.6rem``.75rem`, Border `1px``2px` (closes #1 Aufgabe 2).
## [0.08.20] - 2026-02-20
### Fixed
- **`upsert_node` Race-Condition** (`UNIQUE constraint failed: nodes.node_id`):
Statt SELECT → INSERT nutzt die Methode jetzt `INSERT OR IGNORE` + `UPDATE`,
wodurch konkurrierende Aufrufe keinen Constraint-Fehler mehr auslösen.
## [0.08.19] - 2026-02-20
### Added
- **Initialer Admin-User**: Existiert beim Start keine Datenbank, wird automatisch ein
verifizierter Admin-Account angelegt (`admin@localhost` / `changeme`).
Passwort-Änderung nach dem ersten Login empfohlen.
## [0.08.18] - 2026-02-20
### Changed
- **Datenbankdatei nach `data/` verschoben**: `database.path` in `config.yaml` ist jetzt
`data/meshdd.db`; WAL/SHM-Dateien in `data/` sind gitignored.
- **Sauberes DB-Close**: `database.py` führt vor dem Schließen `PRAGMA wal_checkpoint(FULL)`
durch, damit keine Daten im WAL-Journal verbleiben.
- **Robusterer Shutdown** in `main.py`: Jeder Shutdown-Schritt (NINA, Bot, WebSocket, Web)
ist einzeln mit try/except gekapselt `db.close()` wird jetzt immer ausgeführt.
## [0.08.17] - 2026-02-20
### Changed
- **`.env`-Datei abgeschafft**: Alle Konfigurationswerte (`auth.secret_key`, `smtp.*`)
sind jetzt direkt in `config/config.yaml` enthalten keine separate `.env`-Datei mehr nötig.
- **`meshbot/auth.py`**: `config.env()` durch `config.get()` ersetzt (liest jetzt aus YAML).
- **`meshbot/config.py`**: `ENV_PATH`, `_load_env()` und `env()` entfernt.
- **`config/env.example`** entfernt.
## [0.08.16] - 2026-02-20
### Changed
- **Konfigurationsdateien in `config/` verschoben** (closes #3):
`config.yaml`, `nina.yaml`, `scheduler.yaml` und `env.example` liegen jetzt im
Unterverzeichnis `config/` statt im Root-Verzeichnis bzw. `conf/`.
- **`conf/` entfernt**: Das alte Verzeichnis `conf/` wurde vollständig gelöscht.
- **Python-Pfade aktualisiert**: `meshbot/config.py`, `meshbot/nina.py` und
`meshbot/scheduler.py` referenzieren jetzt das neue `config/`-Verzeichnis.
## [0.08.15] - 2026-02-20
### Added
- **`web.online_threshold`** in `config.yaml` (Default: 900 s): Online-Schwellwert zentral
konfigurierbar; Änderung in der Config wirkt sofort auf alle Stellen (closes #12).
- **`/api/stats`** liefert `online_threshold` Frontend liest Wert vom Backend.
### Changed
- `meshbot/bot.py`: `?mesh`-Kommando nutzt `config.get("web.online_threshold", 900)`.
- `meshbot/database.py`: `nodes_online`-Abfrage nutzt konfigurierten Schwellwert.
- `static/js/dashboard.js`: `isOnline()` nutzt `onlineThreshold` aus Stats-API statt hardcodierter 900.
## [0.08.14] - 2026-02-20
### Added
- **Dashboard Links-Card**: Neue Card mit frei konfigurierbaren Links aus `config.yaml`
(`links:` Liste mit `url` + `label`). Ersetzt die Nachrichten-Card im Dashboard (closes #11).
- **`GET /api/links`**: Neuer Endpunkt gibt konfigurierte Links zurück.
### Changed
- **Nachrichten-Seite öffentlich** (closes #11): Kein Login mehr erforderlich für `/messages`.
`initial_messages` und `new_message` werden an alle WebSocket-Clients gesendet.
- **Dashboard**: Nachrichten-Card entfernt; Nodes-Card auf `col-lg-8` verbreitert.
- **Nachrichtenliste Trenner**: `border-bottom` von `translucent` auf `var(--bs-border-color)`
deutlich sichtbarer Trenner zwischen Nachrichten.
- **`msgCount`-Badge theme-aware**: `bg-secondary``bg-secondary-subtle text-secondary-emphasis`
Text in Hell- und Dunkel-Theme lesbar.
## [0.08.13] - 2026-02-20
### Added
- **Scheduler: neue Template-Variablen** (closes #15):
- `{nodes_online}` Nodes mit `last_seen < 15 Min` (Live-Status, analog Dashboard-Schwellwert)
- `{version}` aktuelle Bot-Version aus `config.yaml`
- **Scheduler Variablen-Badges theme-aware**: Badge-Klasse von `bg-secondary` auf
`bg-secondary-subtle text-secondary-emphasis border-secondary-subtle` umgestellt
korrekte Lesbarkeit in Hell- und Dunkel-Theme.
## [0.08.12] - 2026-02-20
### Changed
- **Bot-Nachrichtenversand ohne ACK**: `sendText()` verwendet jetzt `wantAck=False`
Nachrichten werden einmal gesendet ohne auf Bestätigung zu warten und ohne Retry-Logik.
Sinnvoll für Broadcasts und periodische Status-Meldungen; reduziert ACK-Pakete im Netz (closes #14).
## [0.08.11] - 2026-02-20
### Fixed
- **Pakettypen-Diagramm: eigene Telemetrie ausgeschlossen**: `get_stats()` akzeptiert
jetzt optionalen Parameter `my_node_id`. Ist er gesetzt, werden `TELEMETRY_APP`-Pakete
des eigenen Nodes aus `packet_type_breakdown` herausgefiltert (konsistent mit der
`isSuppressed()`-Logik im Paket-Log-Frontend). Alle Aufrufer (`bot.py`, `webserver.py`)
übergeben `get_my_node_id()`.
## [0.08.10] - 2026-02-19
### Added
- **Neue Nachrichten-Seite** (`/messages`, User-only): Komplett eigenständige Seite für
den Nachrichtenverlauf mit Kanal-Farbcodierung und Richtungs-Kennzeichnung:
- Empfangene Nachrichten: links, Absenderbild (Initialen-Avatar) mit Kanalfarbe,
Bubble mit farbigem linkem Rand
- Gesendete Nachrichten (Bot): rechts, grüne Bubble mit rechtem Rand
- Kanalfilter-Buttons oben (farblich je Kanal), Löschen-Button
- Node-ID des Absenders als zweite Zeile unterhalb des Namens
- Sidebar-Eintrag „Nachrichten" nur für eingeloggte Benutzer sichtbar (`sidebar-user`)
- **Dashboard Nodes-Tabelle erweitert**: Neue Spalten RSSI (dBm) und GPS-Positions-Indikator
(grünes Stecknadel-Icon wenn Position bekannt, graues sonst)
- **`packet_type_breakdown` in Stats-API**: `GET /api/stats` und `stats_update`-WebSocket
liefern jetzt Pakettypen-Verteilung der letzten 24h aus der `packets`-Tabelle
### Fixed
- **Dashboard Charts initial leer** (fixes #10): `updateChannelChart` wurde aufgerufen
bevor der `channels`-WS-Event ankam → Chart blieb leer. Fix: `lastStats` speichern,
Chart neu zeichnen wenn Channels eintreffen.
- **Dashboard Pakettypen-Chart immer leer** (fixes #10): `packet_type_breakdown` fehlte
komplett in `get_stats()` jetzt per SQL-Abfrage über `packets`-Tabelle befüllt.
- **Kartenlegende transparent** (fixes #10): CSS-Variablen in Leaflet-Control-Container
wurden nicht zuverlässig aufgelöst. Fix: explizite Hintergrundfarben für Light- und
Dark-Mode per `[data-bs-theme]`-Selektor statt CSS-Variablen.
## [0.08.09] - 2026-02-19
### Added
- **NINA aktive Warnmeldungen beim Seitenaufruf laden**: Neuer Endpunkt
`GET /api/nina/alerts` gibt alle aktuell aktiven Warnungen aus `_active` zurück.
Die NINA-Seite lädt diese beim Init und zeigt sie in der Tabelle an — auch
Warnungen die bereits vor dem Seitenaufruf ins Mesh gesendet wurden.
Neu eintreffende WS-Events (`nina_alert`) werden per ID dedupliziert.
## [0.08.08] - 2026-02-19
### Changed
- **Kartenlegende neu gestaltet**: Theme-aware (CSS-Variablen für Light/Dark-Mode),
kompaktes Design mit kleinen Uppercase-Abschnittsköpfen statt `<strong>` + `<hr>`,
weicherer Schatten, angepasste Altersdots für beide Themes.
## [0.08.07] - 2026-02-19
### Fixed
- **Startup-Warning "connection.established missed"** (fixes #2): Der Fallback-Check
nach `TCPInterface()`-Konstruktor prüfte `_connected` sofort, obwohl das Event
`connection.established` erst kurz danach aus dem Bibliotheks-Thread feuert.
Fix: `threading.Event` wartet jetzt bis zu 10 Sekunden auf das Event; der Fallback
greift nur noch bei echtem Ausbleiben des Events.
## [0.08.06] - 2026-02-19
### Added
- **Paket-Log informativer Payload** (fixes #3): `bot.py` speichert nun vollständige
Paketdaten je Typ:
- `POSITION_APP`: lat/lon + Höhe, Geschwindigkeit, Satelliten
- `TELEMETRY_APP`: Akku, Spannung, Kanalauslastung, TX-Auslastung, Temperatur,
Luftfeuchtigkeit, Luftdruck (Environment Metrics)
- `NODEINFO_APP`: long_name, short_name + Hardware-Modell
- `ROUTING_APP`: Fehlercode (errorReason)
- `TRACEROUTE_APP`: Hop-Anzahl
- `NEIGHBORINFO_APP`: Anzahl Nachbarn
- **Telemetrie-Unterdrückung eigener Node** (fixes #3): Telemetriepakete vom eigenen
Node (per `my_node_id` oder short_name `FTLW`) werden im Paket-Log nicht angezeigt
und gehen nicht in die Zählung ein.
## [0.08.05] - 2026-02-19
### Fixed
- **Kartenlegende Position**: Legende von `bottomright` nach `topleft` verschoben,
neben die Zoom-Steuerung (fixes Issue #5).
## [0.08.04] - 2026-02-19
### Added
- **NINA Sofortabfrage nach Speichern**: Nach dem Speichern der Konfiguration wird
unmittelbar eine Warnmeldungsabfrage gestartet (kein Warten auf den nächsten
Intervall-Zyklus). Das Frontend lädt die Konfiguration 5 Sekunden nach dem Speichern
automatisch neu, um den Zeitstempel der letzten Abfrage zu aktualisieren.
- **Letzte Abfrage anzeigen**: Unterhalb des Abfrageintervall-Felds wird Datum und Uhrzeit
der letzten erfolgreichen NINA-Abfrage angezeigt (`last_poll`-Feld im Config-Response).
## [0.08.03] - 2026-02-19
### Added
- **NINA Gebietsanzeige**: Warnmeldungen zeigen jetzt das Herkunftsgebiet (AGS-Regionsname)
sowohl in der Weboberfläche (neue Spalte "Gebiet" in der Alerts-Tabelle) als auch im
Mesh-Nachrichtentext (z.B. `[NINA] Schwerwiegend: Sturmböen (Dresden, Stadt)`).
- **AGS-Ortsname in der Konfigurationstabelle**: Die AGS-Code-Tabelle zeigt jetzt den
lesbaren Ortsnamen je Code als zweite Spalte an.
- **Sächsische AGS-Combobox**: Bei der Eingabe neuer AGS-Codes schlägt eine Datalist
alle sächsischen Landkreise und kreisfreien Städte vor (Name + Code).
### Fixed
- **colspan**: Leere Zeile in der Alerts-Tabelle auf 6 Spalten aktualisiert.
## [0.08.02] - 2026-02-19
### Fixed
- **NINA mapData geografische Filterung**: mapData-Endpunkte werden nur noch abgefragt,
wenn **keine** AGS-Codes konfiguriert sind. Sind AGS-Codes gesetzt, filtert der
Dashboard-Endpunkt bereits serverseitig regional (deckt alle Quellen inkl. DWD ab).
Vorher wurden bundesweite Meldungen außerhalb der konfigurierten Regionen angezeigt.
## [0.08.01] - 2026-02-19
### Added
- **NINA Wiederholungsintervall** (`resend_interval`): Zweiter konfigurierbarer Intervall,
der aktive Warnmeldungen in regelmäßigen Abständen erneut ins Mesh sendet
(nur wenn `send_to_mesh=true`). Standard: 3600 Sekunden (1 Stunde).
- **NINA AGS-Code-Tabelle**: AGS-Codes werden jetzt in einer Tabelle mit Lösch-Button
je Zeile angezeigt übersichtlicher als die bisherigen Badge-Einträge.
### Fixed
- **Badge-Lesbarkeit**: Severity-Badges in der Alerts-Tabelle haben jetzt explizite
Textfarben (`text-white` / `text-dark`) ohne `bg-opacity`, damit der Text auf allen
Hintergründen und in beiden Themes lesbar bleibt.
- **colspan**: Leere Zeile in der Alerts-Tabelle korrekt auf 5 Spalten gesetzt.
## [0.08.00] - 2026-02-19
### Added
- **NINA-Integration**: Anbindung an die NINA Warn-App des BBK (Bundesamt für Bevölkerungsschutz
und Katastrophenhilfe). Warnmeldungen werden per HTTP-Polling von `warnung.bund.de/api31`
abgerufen und bei neuen Meldungen automatisch ins Meshtastic-Netz gesendet.
- **Duales Polling**: Zwei parallele Abfragestrategien pro Zyklus:
- **Dashboard** (`/dashboard/{AGS}.json`): Regionale Filterung durch den BBK-Server,
deckt alle Quellen für konfigurierte AGS-Codes ab.
- **mapData** (`/{quelle}/mapData.json`): Nationale Abfrage je aktivierter Quelle
(Katwarn, BIWAPP, MoWaS, DWD, LHP, Polizei) mit Schweregrad-Filterung.
Schließt Lücken, die der Dashboard-Endpunkt nicht abdeckt.
- Intelligente quellenübergreifende De-Duplikation via ID-Normalisierung
(z.B. `dwdmap.``dwd.`, `mow.``mowas.`).
- **NINA-Konfigurationsseite** (`/nina`, Admin-only): Separate Webseite zur Verwaltung der
NINA-Einstellungen analog zur Scheduler-Seite. Konfigurierbar:
- Aktivierung / Deaktivierung
- Abfrageintervall (Sekunden, min. 60)
- Meshtastic-Kanal für Warnmeldungen
- Mindest-Schweregrad (Gering / Mäßig / Schwerwiegend / Extrem)
- AGS-Codes (Amtliche Gemeindeschlüssel) der zu überwachenden Landkreise/Städte
- Quellen-Auswahl (Katwarn, BIWAPP, MoWaS, DWD, LHP, Polizei)
- **„Ins Mesh senden"**-Schalter: aus = Monitor-Modus (nur Weboberfläche, kein Mesh-Versand)
- **Voreinstellung Raum Dresden**: `nina.yaml` enthält 5 AGS-Codes als Standard:
Stadt Dresden, LK Meißen, LK Sächsische Schweiz-Osterzgebirge, LK Bautzen, LK Görlitz
- **Live-Anzeige** empfangener NINA-Warnmeldungen in der Weboberfläche via WebSocket
(`nina_alert`-Event).
- **NINA-Sidebar-Eintrag** in allen Seiten (Admin-only, Icon: `bi-shield-exclamation`).
- **`nina.yaml`** als Hot-reload-fähige Konfigurationsdatei (analog zu `scheduler.yaml`).
## [0.07.01] - 2026-02-18
### Changed
- **Standard-Theme**: Hell-Theme (Light) ist jetzt der Default für neue Besucher
(bisher: Dark). Gespeicherte Benutzereinstellung bleibt erhalten.
## [0.06.15] - 2026-02-18
### Added
- **Scheduler Template-Variablen**: Nachrichten-Jobs können Platzhalter nutzen:
`{time}`, `{date}`, `{datetime}`, `{weekday}`, `{nodes}`, `{nodes_24h}`.
Werden beim Ausführen serverseitig aufgelöst.
- **Scheduler UI**: Bei Typ „Nachricht" werden klickbare Variablen-Badges
unter dem Eingabefeld angezeigt Klick fügt Variable an Cursorposition ein.
- **Footer**: Auf allen Seiten fixer Footer mit Copyright „MeshDD / PPfeiffer",
Versionsnummer und Monat/Jahr (MM/YYYY).
### Fixed
- **Sauberer Shutdown**: WebSocket-Verbindungen werden vor `runner.cleanup()`
explizit geschlossen (`ws_manager.close_all()`), so dass der Prozess nicht
mehr auf hängende WS-Loops wartet.
## [0.06.14] - 2026-02-18
### Added
- **Dashboard**: Viertes Diagramm "Pakettypen (24h)" Doughnut-Chart mit Pakettyp-Verteilung
der letzten 24h aus der `packets`-Tabelle, farblich nach Typ kodiert.
## [0.06.13] - 2026-02-18
### Added
- **Version in Navbar** aller Seiten sichtbar (via `app.js initPage()` + `/api/stats`).
- **Karte Alter-Transparenz**: Nodes < 24h voll sichtbar (0.9), 2448h halb transparent (0.45),
4872h stark transparent (0.2), älter als 72h werden nicht mehr angezeigt.
Legende um Alter-Sektion erweitert.
### Changed
- **Statistiken Rolling Window**: Anfragen-Zähler und Kanal-Breakdown nutzen jetzt
rollendes 24h-Fenster (jetzt minus 24h) statt Mitternacht-Reset.
## [0.06.12] - 2026-02-18
### Fixed
- **Paket-Log**: Typ-Badges nutzen jetzt solide `bg-{color}`-Hintergründe mit `text-white`
(bei Warning: `text-dark`) statt `bg-opacity-20 text-{color}` garantiert lesbaren
Typ-Label-Text in jedem Theme.
## [0.06.11] - 2026-02-18
### Changed
- **Paket-Log**: Badges gleich breit (CSS `min-width:5.5rem`, zentriert), Typ-Filter-Pills in
Typ-Farbe eingefärbt (aktiv: gefüllt, inaktiv: Outline), unbekannte/undekodierbare Pakete
(leerer Portnum) als Typ „?" im Filter sichtbar, Kanal-Spalte zeigt Kanalname wenn verfügbar.
## [0.06.10] - 2026-02-18
### Added
- **Paket-Log** (`/packets`): neue öffentliche Seite zeigt alle empfangenen Meshtastic-Pakete
in Echtzeit via WebSocket mit Tabelle (Zeit, Von, An, Typ, Kanal, SNR, RSSI, Hops, Info),
Typ-Filterleiste, Pause- und Löschen-Funktion, max. 300 Einträge im Browser.
- **DB**: `packets`-Tabelle + `insert_packet()` / `get_recent_packets()` in `database.py`.
- **bot.py**: `_handle_packet()` loggt alle empfangenen Pakete mit Payload-Zusammenfassung
(Text, Position, Telemetrie, NodeInfo) und broadcasted sie über WebSocket an alle Clients.
- **webserver.py**: Route `/packets` + API `/api/packets` + `initial_packets` im WS-Initial-Payload.
- **Sidebar**: Eintrag Pakete" (öffentlich) zwischen Karte und Einstellungen.
### Changed
- **Node-Modal**: von `modal-lg` auf `modal-xl` + `modal-dialog-scrollable` vergrößert,
Karten-Höhe von 250 px auf 300 px erhöht.
## [0.06.09] - 2026-02-18
### Fixed
- **bot.py**: `_on_node_updated` Signatur um `interface=None` ergänzt
`meshtastic.node.updated` sendet `(node, interface)`, fehlender Parameter
führte zu `SenderUnknownMsgDataError` und Absturz des Node-Handlers.
## [0.06.08] - 2026-02-18
### Fixed
- **bot.py**: `pub.subscribe()` wurde nach `TCPInterface()` aufgerufen `connection.established`
und `node.updated`-Events beim Start wurden verpasst; Nodes nicht geladen, Status blieb
"Getrennt". Subscriptions werden jetzt VOR dem Konstruktor registriert + Fallback danach.
- **HTML**: `tabler.min.js` exportiert `bootstrap` nicht global `new bootstrap.Modal()` schlug
fehl, Seiten brachen ab. Zurück zu `bootstrap.bundle.min.js` (Tabler CSS bleibt).
- **dashboard.js**: Bootstrap-4-Klasse `badge-pill` durch `rounded-pill` (Bootstrap 5) ersetzt.
- **style.css**: CSS-Variablen-Typo `--tblr-bg-body` `--tblr-body-bg`.
## [0.06.07] - 2026-02-17
### Changed
- **Tabler 1.4.0** als Admin-Theme eingebunden: ersetzt Bootstrap CSS/JS in allen 6 HTML-Seiten
- `style.css` komplett überarbeitet mit Tabler-Variablen: Inter-Font, subtile Karten-Schatten, verfeinerte Sidebar (Rounded Active-Links), Hover-Animation auf Info-Boxen, pulsierender Status-Dot
- Navbar-Höhe 46px 48px, Sidebar-Breite auf 210px, Karten-Header-Schrift verfeinert
## [0.06.06] - 2026-02-17
### Added
- Nachrichten-Kanalfilter: Filter-Buttons im Nachrichten-Card-Header ("Alle" + ein Button pro Kanal)
- Neue Nachrichten werden sofort gefiltert; `data-channel`-Attribut auf jedem `.msg-item`
- `renderMsgFilterBar()` und `applyMsgFilter()` in `dashboard.js`
## [0.06.05] - 2026-02-17
### Added
- Dark Mode Kartentiles: CartoDB Dark Matter bei dunklem Theme, OpenStreetMap bei hellem (Karte + Node-Modal)
- `themechange` Custom-Event in `app.js` alle Karten reagieren live auf Theme-Wechsel
- 3 Charts im Dashboard: Kanal-Anfragen (Doughnut), Hop-Verteilung (Bar), Hardware Top 5 (Bar)
- Charts passen sich automatisch dem Dark/Light Mode an
- Nodes-Tabelle: Suchfeld + Online-Filter + Sortierung per Klick auf Spaltenköpfe
## [0.06.04] - 2026-02-17
### Added
- Bot-Uptime als 4. Info-Box im Dashboard (live via WebSocket)
- Meshtastic-Verbindungsstatus als zweiter Status-Dot in der Navbar
- `bot_status` WebSocket-Event bei Connect/Disconnect des Meshtastic-Nodes
- `uptime` und `bot_connected` in `stats_update` und `/api/stats`
## [0.06.03] - 2026-02-17
### Fixed
- WebSocket sendet `initial_messages` und `new_message` nur noch an authentifizierte Clients
- `WebSocketManager` unterscheidet jetzt `clients` (alle) und `auth_clients` (eingeloggt)
## [0.06.02] - 2026-02-17
### Changed
- Refactor: Gemeinsames `static/js/app.js` Modul extrahiert
- Eliminiert ~360 Zeilen doppelten Code aus allen 5 Seiten (Navbar, Sidebar, Theme, escapeHtml)
- Sidebar-HTML wird jetzt dynamisch per `initPage()` injiziert mit automatischer Active-Link-Erkennung
## [0.06.00] - 2026-02-17
### Summary
- Node-Detail-Modal mit Minikarte im Dashboard
- Anfragen-Tracking pro Kanal mit taeglichem Reset
- Kanal-Badges fuer alle Kanaele im Dashboard
### Added
- Node-Detail-Modal: Klick auf Node-Zeile oeffnet Modal mit allen Node-Daten und Leaflet-Minikarte
- Anfragen-Aufschluesselung pro Kanal mit Kanalnamen im Dashboard
- Channel-Spalte in der commands-Tabelle (mit automatischer DB-Migration)
### Changed
- Anfragen-Zaehler zeigt nur Anfragen von heute (Reset um Mitternacht)
- Kanal-Badges zeigen immer alle Kanaele aufsteigend sortiert (auch bei 0 Anfragen)
- Kanal-Badge in Nachrichten im Light-Mode besser lesbar
## [0.05.10] - 2026-02-17
### Fixed
- Kanal-Badge in Nachrichten im hellen Modus besser lesbar (bg-secondary statt bg-body-secondary)
## [0.05.09] - 2026-02-17
### Changed
- Kanal-Badges zeigen immer alle Kanaele aufsteigend sortiert mit Kanalnamen (auch bei 0 Anfragen)
- Label-Zeile "Anfragen/Kanal" entfernt
## [0.05.08] - 2026-02-17
### Changed
- Anfragen-Zaehler zeigt nur noch Anfragen von heute (Reset um Mitternacht)
- Kommando-Badges entfernt, nur noch Kanal-Aufschluesselung angezeigt
## [0.05.07] - 2026-02-17
### Added
- Anfragen-Aufschluesselung pro Kanal mit Kanalnamen im Dashboard
- Channel-Spalte in der commands-Tabelle (mit DB-Migration fuer bestehende DBs)
## [0.05.06] - 2026-02-17
### Added
- Node-Detail-Modal im Dashboard: Klick auf Node-Zeile oeffnet Modal mit allen Node-Daten
- Leaflet-Minikarte im Modal zeigt Node-Position (oder "Keine Position" Hinweis)
- Zwei-Spalten-Layout: Datentabelle links, Karte rechts (responsive)
## [0.05.05] - 2026-02-17
### Changed
- SMTP-Versand auf EmailMessage + aiosmtplib.SMTP (async context manager) umgestellt
- Plaintext-Fallback fuer nicht-HTML-faehige E-Mail-Clients
- SMTP-Host zurueck auf ssl0.ovh.net
## [0.05.04] - 2026-02-16
### Added
- Admin: Benutzer direkt anlegen mit Passwort und Rollenwahl
- Admin: Benutzer bearbeiten (Name, E-Mail, Rolle) per Modal
- Admin: Passwort zuruecksetzen mit optionalem E-Mail-Versand
- Admin: Info-Mail mit Zugangsdaten an Benutzer senden
- Passwort-Generator (crypto.getRandomValues) in Admin-UI
- Verifikationslink wird immer im Log ausgegeben (nicht nur ohne SMTP)
### Changed
- Admin-Seite komplett ueberarbeitet mit Modals fuer alle Aktionen
- E-Mail-Funktionen um `send_user_info_email` erweitert
## [0.05.03] - 2026-02-16
### Changed
- Zugangsdaten (AUTH_SECRET_KEY, SMTP-*) aus config.yaml in .env-Datei ausgelagert
- Neuer `config.env()` Helper fuer Umgebungsvariablen
- `.env.example` als Vorlage hinzugefuegt
- E-Mail-Versand in gemeinsame `_send_email()` Hilfsfunktion refaktoriert
## [0.05.02] - 2026-02-16
### Fixed
- SMTP-Versand: TLS (Port 465) und STARTTLS (Port 587) automatisch anhand des Ports
## [0.05.01] - 2026-02-16
### Fixed
- Fernet key setup fuer EncryptedCookieStorage korrigiert (doppelte Base64-Kodierung)
## [0.05.00] - 2026-02-16
### Added
- Benutzerverwaltung mit Session-basierter Authentifizierung
- Registrierung mit E-Mail-Verifikation (OTP-Token via aiosmtplib)
- Passwort-Hashing mit bcrypt (12 Rounds, min. 8 Zeichen)
- Benutzerrollen: public (nicht eingeloggt), user, admin
- Login/Register/Passwort-vergessen Seite (`/login`, `/register`)
- Admin-Benutzerverwaltung (`/admin`) mit Rolle aendern, verifizieren, loeschen
- Session-Management via aiohttp-session mit EncryptedCookieStorage
- Auth-Middleware setzt `request['user']` auf allen Routen
- API-Endpoint `GET /api/auth/me` fuer Frontend-Rollenabfrage
- Auth-Routen: login, register, logout, verify, set-password, forgot-password, reset-password
- Admin-API: users CRUD, Rolle aendern, manuell verifizieren
- Navbar zeigt User-Name + Logout oder Login-Button auf allen Seiten
- Sidebar zeigt Scheduler/Settings/Admin nur fuer Admins (JS-gesteuert)
### Changed
- Dashboard: Nachrichten-Card und Sende-Card nur fuer eingeloggte User sichtbar
- API `/api/send` erfordert User-Login
- API `/api/node/config`, `/api/scheduler/*` erfordern Admin-Rolle
- Neue DB-Tabellen: users, tokens, email_logs
- config.yaml: auth + smtp Sektionen hinzugefuegt
- requirements.txt: bcrypt, aiohttp-session, cryptography, aiosmtplib
## [0.04.00] - 2026-02-16
### Summary
- Node-Einstellungen Seite, Karte im Sidebar-Layout
- Wetter mit Ortsnamen, PLZ-Support, Luftdruck und Taupunkt
- /me Befehl, Ping mit Hop-Anzahl
- Gesendete Nachrichten im Dashboard mit gruener Bubble
- Sende-Card als eigene Komponente, Command-Prefix "?"
## [0.03.15] - 2026-02-16
### Changed
- Debug-Logging aus _send_text entfernt
## [0.03.14] - 2026-02-16
### Changed
- Command-Prefix von "/" auf "?" geaendert
- Channel-Combobox in Sende-Card breiter (180px) fuer vollstaendige Channelnamen
- Debug-Logging in _send_text fuer Diagnose der Nachrichtenspeicherung
## [0.03.13] - 2026-02-16
### Fixed
- Gesendete Nachrichten werden jetzt vor dem Radio-Send gespeichert und broadcastet
- Getrenntes Exception-Handling fuer DB-Store und Radio-Send
## [0.03.12] - 2026-02-16
### Fixed
- Eigene Nachrichten-Echos werden in _handle_packet gefiltert (keine Doppelspeicherung)
- Bot-Nachrichten erscheinen korrekt im Dashboard-Nachrichtenfenster
## [0.03.11] - 2026-02-16
### Changed
- Sende-Zeile als eigene Card mit gruener Oberkante oberhalb der Nodes/Nachrichten-Cards
- Nachrichten-Card ohne Footer (schlanker)
## [0.03.10] - 2026-02-16
### Added
- Gesendete Bot-Nachrichten werden im Nachrichtenfenster angezeigt
- Eigene Nachrichten mit gruener Bubble und rechtsbuendiger Ausrichtung
- Bot-Nachrichten werden in DB gespeichert und via WebSocket broadcastet
## [0.03.09] - 2026-02-16
### Added
- Neuer Befehl `/me` zeigt eigene Node-Infos (Name, HW, Hops, SNR, RSSI, Batterie, Position)
- Wetter zeigt Luftdruck NN (hPa) und Taupunkt C)
## [0.03.08] - 2026-02-16
### Changed
- Ping-Antwort zeigt Hop-Anzahl des anfragenden Nodes (z.B. "Pong ueber 2 Hops!")
## [0.03.07] - 2026-02-16
### Added
- Weather-Befehl zeigt Ortsnamen via Reverse-Geocoding (Nominatim)
- Optionales Argument `plz:XXXXX` fuer Wetter nach deutscher Postleitzahl
- Geocoding-Methoden `_geocode_plz()` und `_reverse_geocode()` im Bot
### Changed
- Help-Text zeigt `plz:XXXXX` Option beim Weather-Befehl
## [0.03.06] - 2026-02-15
### Added
- Node-Einstellungen Seite (`/settings`) zeigt Geraet, LoRa, Channels, Position, Power, Bluetooth/Netzwerk
- Neuer API-Endpoint `GET /api/node/config` liest Config vom lokalen Meshtastic-Node
- `get_node_config()` Methode im Bot (liest localConfig, myInfo, metadata via Protobuf)
- Sidebar-Eintrag "Einstellungen" mit Gear-Icon auf allen Seiten
### Changed
- Karte (`/map`) im Sidebar-Layout statt Vollbild (Top-Navbar, Sidebar, Content-Wrapper)
- Karte oeffnet im selben Tab statt `target="_blank"`
- Status-Info und Node-Count in Karten-Navbar integriert
- Map-Styles (Tooltip, Legende) in zentrale `style.css` verschoben
- Sidebar-Navigation auf allen 4 Seiten konsistent (Dashboard, Scheduler, Karte, Einstellungen)
## [0.03.05] - 2026-02-15
### Changed
- Dashboard und Scheduler auf AdminLTE-Style umgestellt
- Feste Sidebar-Navigation (Dashboard, Scheduler, Karte) mit Active-State
- Fixed Top-Navbar mit Branding, Status-Dot und Theme-Toggle
- Content-Wrapper mit leicht abgesetztem Hintergrund
- Info-Boxes im AdminLTE-Stil (Icon-Spalte + Inhalt) statt Cards
- Card-Outline mit farbiger Oberkante (info/warning) statt Borders
- Table-Striped fuer bessere Lesbarkeit
- Sidebar responsive: auf Mobile als Overlay mit Backdrop
- Einheitliches Layout auf Dashboard und Scheduler
## [0.03.04] - 2026-02-15
### Fixed
- Kanalnamen in Nachrichten fehlten beim Laden (Channels werden jetzt vor Messages gesendet)
### Changed
- Dashboard deutlich kompakter: weniger Padding, kleinere Schriftgroessen
- Stat-Cards, Navbar, Panels und Nachrichten platzsparender
- Hover-Animationen und Pulse-Effekt entfernt (schlichter)
## [0.03.03] - 2026-02-15
### Changed
- Dashboard-Layout modernisiert: Glassmorphism-Navbar (sticky, blur-Effekt)
- Stat-Cards mit Gradient-Akzentlinie, dezenten Hintergrund-Icons und Hover-Lift
- Nachrichten als Chat-Bubbles statt flache Listeneintraege
- Buttons und Badges als Rounded-Pills fuer moderneren Look
- Sende-Leiste mit eigenem abgesetztem Styling
- Panel-Cards borderless mit Soft-Shadow
- Node-Count-Badge als Pill mit halbtransparentem Hintergrund
- Status-Dot mit sanfter Pulse-Animation bei Verbindung
- Breakdowns-Leiste mit subtilerem Hintergrund
## [0.03.02] - 2026-02-15
### Added
- Nachrichten senden direkt aus dem Dashboard (Channel-Dropdown + Textfeld)
- Neuer API-Endpoint `POST /api/send` zum Senden von Textnachrichten
- `send_message()` Methode im Bot fuer freie Textnachrichten
- Scheduler unterstuetzt neuen Typ "Nachricht" neben "Kommando"
- Typ-Auswahl (Kommando/Nachricht) im Scheduler-Modal mit dynamischem Label
- Typ-Spalte in der Scheduler-Tabelle
## [0.03.01] - 2026-02-15
### Added
- Scheduler-Feature: zeitgesteuerte Bot-Kommandos via Cron-Ausdruecke
- Neue Datei `scheduler.yaml` fuer Job-Konfiguration mit File-Watcher (Live-Reload)
- Eigener minimaler Cron-Parser (Minute, Stunde, Tag, Monat, Wochentag)
- Scheduler-Webseite unter `/scheduler` zum Verwalten der Jobs (CRUD)
- REST API: GET/POST/PUT/DELETE `/api/scheduler/jobs`
- Live-Updates der Scheduler-Seite via WebSocket
- `execute_command()` Methode im Bot fuer programmatische Kommando-Ausfuehrung
- Scheduler-Link in der Dashboard-Navbar
## [0.03.00] - 2026-02-15
### Added
- Produktiver Betrieb als Systemd-Service
## [0.02.06] - 2026-02-15
### Added
- WordPress-Beitrag unter docs/wordpress-beitrag.html
- Systemd Service-File meshdd-bot.service
- Nachrichten-Splitting mit [x/y] Nummerierung
### Changed
- Pause zwischen gesplitteten Nachrichten auf 3 Sekunden erhöht
## [0.02.05] - 2026-02-15
### Added
- Automatisches Aufteilen langer Nachrichten (max 170 Zeichen) mit 1,5s Pause
### Changed
- /mesh Befehl: bessere Lesbarkeit mit Absätzen und Einrückungen
- Hop-Verteilung: "Direkt", "1 Hop", "2 Hops" statt "0h", "1h", "2h"
## [0.02.04] - 2026-02-15
### Added
- Neuer Befehl /mesh - zeigt Mesh-Netzwerk-Infos (Nodes online/gesamt, aktiv 24h, Positionen, Hop-Verteilung, Top-Hardware)
## [0.02.03] - 2026-02-15
### Added
- Kommando-Tracking in der Datenbank (neue Tabelle `commands`)
- Stats Card "Aktiv (24h)" zeigt Nodes der letzten 24 Stunden
- Stats Card "Anfragen" zeigt beantwortete Bot-Kommandos
- Kommando-Aufschlüsselung als Badges in voller Breite (z.B. /help 5, /ping 3)
### Changed
- Stats Cards von 4er auf 3er Grid umgestellt plus Breakdown-Zeile
- Bot /stats Kommando zeigt aktualisierte Statistiken
## [0.02.02] - 2026-02-15
### Changed
- SNR-Spalte rechtsbündig, Batterie-Spalte linksbündig
- Spaltenabstände in der Nodesliste reduziert (kompakteres Layout)
- Spaltenüberschrift "Zuletzt gesehen" zu "Zuletzt" gekürzt
## [0.02.01] - 2026-02-15
### Changed
- Stats Cards kompakter (kleinerer Padding und Schrift)
- Batteriestatus mit Bootstrap Icons und Farbcodierung (grün/gelb/rot)
- Version wird in der Navbar angezeigt
- Karte fittet beim Öffnen auf alle Nodes
## [0.02.00] - 2026-02-15
### Added
- Zentrale config.yaml mit Live-Reload (File-Watcher)
- Konfigurierbarer Command-Prefix (Standard: /)
- Kanalnamen in der Nachrichtenliste
- Hops-Spalte in der Nodes-Tabelle
- Karte: Farbcodierung der Nodes nach Hop-Anzahl mit Legende
- Karte: Tooltip mit Node-Infos beim Hover
- Hell/Dunkel Theme-Umschalter im Dashboard
- Node-Namen (LongName/ShortName) werden korrekt angezeigt
- Nachrichten werden beim Connect aus der DB geladen
- Wetter-Fallback auf Dresden Zentrum bei fehlender Position
### Changed
- Konfiguration von Environment-Variablen auf config.yaml umgestellt
- Version wird in config.yaml statt version.py verwaltet
### Removed
- Git pre-commit Hook (manuelle Versionierung)
- version.py (ersetzt durch config.yaml)
## [0.01.02] - 2026-02-15
### Changed
- Auto-commit update
## [0.01.01] - 2026-02-15
### Changed
- Dashboard auf Bootstrap 5.3 Dark Theme umgestellt
- Bootstrap Icons hinzugefügt
- Responsive Stat-Cards, verbessertes Node-Table-Layout
- Online-Nodes werden grün hervorgehoben
## [0.01.00] - 2026-02-15
### Added
- Initial release
- Meshtastic Bot mit TCP-Verbindung
- Bot-Kommandos: !ping, !nodes, !info, !help, !weather, !stats, !uptime
- SQLite-Datenbank für Nodes und Nachrichten
- Web-Dashboard mit Live-Updates via WebSocket
- Leaflet-Karte mit Node-Positionen
- Automatische Versionierung via Git pre-commit Hook