# Benachrichtigungen Automatiken können melden: als Nachricht auf dem Handy oder als E-Mail. Beides ohne eine eigene App — die Meldung aufs Handy kommt über **Web Push** aus dem Dashboard selbst. ```mermaid flowchart LR A["Automatik
Aktion: Benachrichtigungen"] --> R P["Probe aus den Einstellungen"] -->|"MQTT benachrichtigung/#"| R R["autoaction_runner.py
BenachrichtigungTransport"] --> PUSH["Push-Dienst
Google, Mozilla, Apple"] --> H["Handy / Browser
sw.js zeigt die Meldung"] R --> MAIL["SMTP"] --> M["Postfach"] DB[("homeMesh.push_abos")] --> R KEY[["push_vapid.json
Schlüsselpaar"]] --> R ``` --- ## 1. Das Gerät „Benachrichtigungen“ Ein gerechnetes Gerät wie „Zeitpunkt“: Es hängt an keinem Netzwerkanschluss, sondern bündelt Kommandos, die der Runner selbst ausführt. Angelegt wird es vom Gerätesuchlauf (`benachrichtigung_module.py`), Aktor-URL `Benachrichtigung`. | Kommando | `command_url` | Parameter | |---|---|---| | Nachricht aufs Handy | `push` | Titel, Text | | E-Mail | `mail` | Betreff, Text | **Warum als Gerät und nicht als eigener Aktionstyp?** Weil der Editor, die Übersicht und die Zeitleiste damit nichts Neues lernen müssen: Für sie ist es ein Gerät mit Kommandos wie jedes andere. Eine Meldung ist deshalb eine gewöhnliche Aktion — sie lässt sich mit anderen Aktionen mischen, im Rahmen begrenzen und verketten. **Keine Empfängerliste je Automatik.** Wer eine Meldung bekommt, steht an einer Stelle: die Handys in `homeMesh.push_abos`, die Mailadressen in der `config.ini` des Runners. Ein Empfängerfeld je Aktion wäre eine zweite Liste, die mit der ersten auseinanderläuft. --- ## 2. Web Push — ohne App ```mermaid sequenceDiagram participant B as Browser (Handy) participant W as ajax/push.php participant DB as homeMesh.push_abos participant R as Runner participant D as Push-Dienst B->>B: sw.js registrieren, Erlaubnis holen B->>D: subscribe(VAPID-Public-Key) D-->>B: Abo (endpoint + 2 Schlüssel) B->>W: POST ?action=anmelden W->>DB: INSERT … ON DUPLICATE KEY UPDATE Note over R: Automatik löst aus R->>DB: Abos lesen R->>D: verschlüsseltes Paket, VAPID-signiert D->>B: push-Ereignis → showNotification() ``` Drei Teile, die zusammengehören: | Teil | Wo | Aufgabe | |---|---|---| | Service Worker | `sw.js` (Wurzelverzeichnis!) | nimmt das `push`-Ereignis an und zeigt die Meldung; ein Klick holt die Seite nach vorn | | Abo | `homeMesh.push_abos` | Endpoint plus zwei Schlüssel je Gerät | | Schlüsselpaar | `SolarManager/push_vapid.json` | der private Teil unterschreibt jede Meldung, der öffentliche steckt im Abo | Wissenswertes: * **`sw.js` muss im Wurzelverzeichnis liegen.** Ein Service Worker gilt nur für Adressen unterhalb seines eigenen Ortes. * **Er speichert nichts zwischen.** Das Dashboard lebt von aktuellen Werten; ein Cache wäre hier keine Beschleunigung, sondern eine Fehlerquelle. * **iPhone:** Safari erlaubt Web Push erst, wenn die Seite über „Teilen ▸ Zum Home-Bildschirm“ abgelegt und von dort geöffnet wurde. * **Das Abo gehört dem Browser, nicht dem Konto.** Jedes Gerät meldet sich einzeln an; in den Einstellungen stehen alle nebeneinander. * **Der Endpoint ist das Geheimnis.** Wer ihn hat, kann dem Gerät schreiben — deshalb geht er nie an den Browser zurück, auch nicht in der Liste. * **Tote Abos räumt der Runner selbst weg:** Antwortet der Dienst mit 404 oder 410, gibt es das Gerät nicht mehr. * Der Schlüssel wird **nie neu erzeugt**, solange Abos daran hängen — `vapid_erzeugen.py` überschreibt eine vorhandene Datei nicht. --- ## 3. E-Mail Ein gewöhnlicher SMTP-Versand aus dem Runner, eingetragen in dessen `config.ini`: ```ini [mail] server = smtp.example.net port = 587 ; 587 = STARTTLS, 465 = von Anfang an verschlüsselt benutzer = passwort = von = an = einer@example.net, zweiter@example.net ``` Unverschlüsselten Versand gibt es nicht: Bei 465 wird die Verbindung verschlüsselt aufgebaut, sonst mit STARTTLS gewechselt. Fehlen Server oder Empfänger, meldet die Automatik einen Fehler ins Protokoll (`automation_log`), statt still nichts zu tun. --- ## 4. Der zweite Weg: MQTT Der Runner hört zusätzlich auf `benachrichtigung/#`: | Topic | Nutzlast | Wirkung | |---|---|---| | `benachrichtigung/push` | `{"titel": "...", "text": "..."}` | Meldung an alle Geräte | | `benachrichtigung/mail` | `{"betreff": "...", "text": "..."}` | Mail an die eingetragenen Empfänger | Darüber schickt die **Probe** aus den Einstellungen — die Weboberfläche muss so nichts verschlüsseln und braucht den privaten Schlüssel nie. Denselben Weg kann jedes Skript auf der NAS nehmen. Zugestellt wird im Haupttakt des Runners, nicht im MQTT-Faden: Eine Datenbankverbindung gehört einem Faden, und der Rückruf des Brokers läuft in einem eigenen. --- ## 5. Die Pakete `pywebpush`, `py_vapid` und `http_ece` liegen wie alle übrigen Fremdpakete **im SolarManager-Ordner**, nicht in `site-packages`. Weil der Runner aus `autoActions/` startet, hängt `transports.py` diesen Ordner an den Suchpfad. --- ## 6. Wo fange ich an, wenn ich … | Vorhaben | Ort | |---|---| | … einen weiteren Kanal (Telegram, Signal, WhatsApp) | ein Kommando in `benachrichtigung_module.py`, ein `elif` in `BenachrichtigungTransport.senden()` | | … den Text einer Meldung ändern | in der Automatik selbst — Titel und Text sind Parameter der Aktion | | … ein Handy loswerden | Einstellungen → Meldungen → Papierkorb; oder auf dem Gerät selbst abmelden | | … den Schlüssel erneuern | `push_vapid.json` löschen, `vapid_erzeugen.py` laufen lassen, danach müssen sich **alle** Geräte neu anmelden | | … nachsehen, warum nichts ankam | `autoActions.log` auf der NAS und die Spalten `zuletzt`/`fehler` in `push_abos` |