Benachrichtigungen: Geraet, Abos und der Reiter Meldungen

Der Geraetesuchlauf legt "Benachrichtigungen" an (benachrichtigung_module.py),
ein Kommando je Kanal. Damit kann jede Automatik melden, ohne dass Editor,
Zeitleiste oder Datenbank etwas davon wissen muessten.

Fuer die Meldung aufs Handy braucht es keine App: Der Browser meldet sich
unter Einstellungen -> Meldungen selbst an (sw.js, ajax/push.php), das Abo
steht in homeMesh.push_abos, verschickt wird vom Runner. Auf dem iPhone geht
es erst ab der Ablage auf dem Home-Bildschirm - der Reiter sagt das auch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 08:37:31 +02:00
co-authored by Claude Opus 5
parent 061dfa3fc5
commit df48432133
10 changed files with 720 additions and 1 deletions
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""
Benachrichtigungen als Geraet.
Ein gerechnetes Geraet wie "Zeitpunkt" (logic_module.py): Es haengt an keinem
Netzwerkanschluss, sondern buendelt Kommandos, die der Runner selbst
ausfuehrt. Damit kann jede Automatik melden, ohne dass Editor, Datenbank oder
Zeitleiste etwas davon wissen muessten - fuer sie ist es ein Geraet mit
Kommandos wie jedes andere.
Zwei Kanaele, beide ohne fremde App auf dem Handy:
Nachricht Web Push an alle angemeldeten Geraete. Der Browser meldet sich
unter Einstellungen -> Meldungen selbst an; verschickt wird
verschluesselt ueber den Push-Dienst des Browserherstellers.
E-Mail ueber den SMTP-Zugang aus der config.ini des Runners.
Die Kommandos tragen keine Empfaengerliste: Wer eine Meldung bekommt, steht
in der Datenbank (push_abos) bzw. in der Konfiguration. Ein Empfaengerfeld je
Automatik waere eine zweite Stelle, an der dieselbe Liste gepflegt werden
muesste - und sie liefe auseinander.
Der Text darf Platzhalter enthalten, die der Runner ersetzt:
{automatik} Name der Automatik, die gerade ausgeloest hat
{zeit} Uhrzeit der Ausloesung, "HH:MM"
{datum} Datum der Ausloesung, "TT.MM.JJJJ"
"""
import logging
from typing import List, Dict, Tuple
from modules.base_module import BaseModule
logger = logging.getLogger(__name__)
class BenachrichtigungModule(BaseModule):
"""Legt das Geraet "Benachrichtigungen" mit seinen Kanaelen an."""
def is_enabled(self) -> bool:
# Wie beim Logic-Modul: ohne eigenen Abschnitt in der config.ini
# trotzdem an - das Geraet kostet nichts und schadet nicht.
return getattr(self.config, "benachrichtigung_enable", True)
def discover(self) -> Tuple[List[Dict], List[Dict]]:
logger.info("\n" + "=" * 60)
logger.info("BENACHRICHTIGUNGEN WERDEN ERZEUGT")
logger.info("=" * 60)
kommandos = [
{
"command": "Nachricht aufs Handy",
"url": "push",
"parameters": [
{"name": "Titel", "type": "string", "url": "titel"},
{"name": "Text", "type": "string", "url": "text"},
],
},
{
"command": "E-Mail",
"url": "mail",
"parameters": [
{"name": "Betreff", "type": "string", "url": "betreff"},
{"name": "Text", "type": "string", "url": "text"},
],
},
]
aktoren = [{
"type": "Benachrichtigung",
"name": "Benachrichtigungen",
"url": "Benachrichtigung",
"commands": kommandos,
"states": [],
}]
return aktoren, []