Web Push ohne App, E-Mail, das gerechnete Geraet und der zweite Weg ueber MQTT - samt der Stolpersteine (sw.js gehoert ins Wurzelverzeichnis, iPhone erst ab Home-Bildschirm, Endpoint ist das Geheimnis, Schluessel nie neu erzeugen solange Abos daran haengen). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.8 KiB
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.
flowchart LR
A["Automatik<br/><small>Aktion: Benachrichtigungen</small>"] --> R
P["Probe aus den Einstellungen"] -->|"MQTT benachrichtigung/#"| R
R["autoaction_runner.py<br/><small>BenachrichtigungTransport</small>"] --> PUSH["Push-Dienst<br/><small>Google, Mozilla, Apple</small>"] --> H["Handy / Browser<br/><small>sw.js zeigt die Meldung</small>"]
R --> MAIL["SMTP"] --> M["Postfach"]
DB[("homeMesh.push_abos")] --> R
KEY[["push_vapid.json<br/><small>Schlüsselpaar</small>"]] --> 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 |
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
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.jsmuss 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:
[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 |