Files
Smart-Dashboard/doku/benachrichtigungen.md
T
adminandClaude Opus 5 d3ff959574 Doku: Benachrichtigungen beschrieben
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>
2026-09-21 08:38:44 +02:00

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
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

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:

[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