Ein flexibler Benachrichtigungsbereich in Node-RED Dashboard

Vorgeschichte

Als das SmartHome immer weiter wuchs, kam ich irgendwann an den Punkt, dass ich mir eine einheitliche Vorgehensweise für Benachrichtigungen überlegen musste. Viele Informationen braucht man nur, wenn sie akut sind. Diese über das ganze Dashboard zu verteilen und abzuklappern, wäre unpraktisch, denn Benachrichtigungen entstanden an immer mehr Stellen (der Versuch einer Sammlung):

  • Unwetterwarnungen
  • Meldung von technischen Problemen bei Schnittstellen
  • Meldung von technischen Problemen bei Sensoren
  • Update-Benachrichtigungen für Geräte-Firmware
  • Batterie-Meldungen von Sensoren
  • Indoor und Outdoor Temperaturwarnungen
  • Türklingel
  • Warnung bei hoher CPU Auslastung
  • Verkehrsmeldungen aus dem ÖPNV
  • Warnmeldungen zum Warmwasservorrat
  • Müll-Entsorgungsankündigungen
  • Geöffnete Türen oder Fenster (mit KWL kommt das nicht so häufig vor)
  • tägliche Niederschlagsmenge (ab einem bestimmten Grenzwert)

Inhaltsverzeichnis

  1. Der Benachrichtigungsbereich
    1. Benachrichtigungen aggregieren
    2. So sammle ich die Benachrichtigungen ein
    3. Meldungen entfernen – „Entwarnung“
    4. Den Benachrichtigungsbereich ein- und ausblenden
    5. Den Benachrichtigungsbereich stylen
    6. Ein Problem bleibt – die Höhe
  2. Aus UI-Benachrichtigungen werden Push-Meldungen
    1. Nur einmal pro Zeitraum
    2. Erst wenn ein Warnlevel überschritten wird
    3. Dopplungen filtern
  3. Flow als Download

Der Benachrichtigungsbereich

Herausgekommen ist sowohl im Frontend als auch im Backend ein zentraler Benachrichtigungsbereich, in dem auch die Push-Meldungen ans Smartphone verarbeitet werden.

Ansicht im Frontend

Ansicht im Backend

Benachrichtigungen aggregieren

Um die Benachrichtigungen zu zusammenzufassen, nutze ich das list-Node von node-red-contrib-combine. Es kann eingehende Messages sammeln, auf verschiedene Weise aggregieren und auch selbsttätig nach einer einstellbaren Zeitspanne wieder entfernen.

Einstellungen des list-Nodes

Compose a table of consecutive incoming topics and payloads. Output as array, csv, html table or html list. Columns and sort order can be configured. Message distinction can be configured to msg.topic or msg._id. A timeout can be configured that removes messages from the internal cache. The tables are re-composed when a message times out.

node-red-contrib-combine / list

„list“ nimmt mir viel Arbeit ab, denn es generiert automatisch eine Tabelle aller Benachrichtigungen, die ich dann über ein Template-Node ausgebe.

So sammle ich die Benachrichtigungen ein

Benachrichtigungen entstehen in verschiedenen Flows. Diese leite ich über die Link-In-Out-Nodes zum Benachrichtigungsbereich-Flow. Vorher wird jede Benachrichtigung in einheitlicher Form aufbereitet. Bei mir sieht das so aus:

msg.topicjede Benachrichtigungskategorie erhält ein eindeutiges Topic
msg.payloadenthält die Meldung
msg.timeenthält entweder die aktuelle Zeit oder die Zeit, auf die sich die Meldung bezieht, z.B. das Datum beim Entsorgungstermin oder der Zeitraum bei einer Unwetterwarnung

Der entsprechende „Code“ dazu:

a = new Date();
b = a.getHours();
c = ("00" + a.getMinutes()).slice(-2);

msg.topic="batterie";
msg.time=b+':'+c;
msg.payload="Bei einem Sensor ist die Batterie bald leer.";
return msg;

Da ich msg.time nicht immer für die aktuelle Zeit nutze, sondern teils auch für andere Informationen, wird diese bei jedem Ereignis entsprechend generiert. Bei den Mülltonnen-Leerungen wird zum Beispiel das Datum dort eingesetzt, bei Unwetterwarnungen der Gültigkeitszeitraum der Warnung.

Meldungen entfernen – „Entwarnung“

Um Meldungen zu entfernen oder zu widerrufen, sendet man „false“ als Payload mit gleichem msg.topic, schon wird die Meldung aussortiert. (zumindest wenn man es im list-Node so eingestellt hat)

msg.topic="batterie";
msg.time=false;
msg.payload=false;
return msg;

Den Benachrichtigungsbereich ein- und ausblenden

Damit das Dashboard schön ist, wollte ich einen leeren Benachrichtigungsbereich vermeiden. Dank des ui-control Widgets kann man diesen problemlos ausblenden, sobald keine Nachrichten mehr vorliegen.

Immer wenn eine Meldung ankommt oder entfernt wird, wird die Gesamt-Zeichenanzahl der Benachrichtigungen in den Kontextdaten gespeichert, sodass sowohl bei Änderungen der Benachrichtigungen als auch beim Aufruf des Tabs schnell geprüft werden kann, ob die UI-Gruppe angezeigt werden soll.

if(msg.payload===true) {
msg.payload={"group": {"show": ["Anfang_Meldungen"], "focus": false}};
}
else {
msg.payload={"group": {"hide": ["Anfang_Meldungen"], "focus": false}};
}
return msg;

(mein Tab heißt „Anfang“, die UI-Gruppe „Meldungen“, die Adressierung der Gruppe funktioniert mit einem Unterstrich dazwischen: „Tab_Gruppe“)

Den Benachrichtigungsbereich stylen

Damit der Benachrichtigungsbereich optisch heraussticht, habe ich ihn auffällig gestaltet. Über ein Template-Node in der Head-Sektion habe ich folgende Styles hinterlegt. (Wie die nötige ID der UI-Gruppe zustande kommt, steht ein Absatz weiter oben oder im Quelltext deines Dashboards.)

#Anfang_Meldungen div.nr-dashboard-cardpanel {
    background-color: rgba(255,227,116,0.4);
}
#Anfang_Meldungen div.nr-dashboard-cardpanel p {
    color:red;
}
#Anfang_Meldungen_cards md-card {
    background-color: rgba(255,227,116,0.3);
}

Ein Problem bleibt – die Höhe

Für ein „Problem“ habe ich noch keine Lösung gefunden. Die Gruppe, bzw. das template-Node hat bei mir eine fixe Höhe von aktuelle zwei Raster-Höheneinheiten. Sind viele Meldungen da, muss man also scrollen. Hinweise und Lösungen dazu gerne in die Kommentare.

Aus UI-Benachrichtigungen werden Push-Meldungen

Der Vorteil, wenn man alle Benachrichtigungen zentral sammelt, ist: man kann aus den UI-Benachrichtigungen auch ganz schnell Push-Meldungen – bei mir per XMPP – aufs Smartphone generieren. Um die Nerven zu schonen, habe ich dabei inzwischen umfangreiche Filter eingebaut, um Push-Terror zu vermeiden. Ich habe sehr individuell abgestimmt, welche Benachrichtigungen ich akut aufs Smartphone bekommen will. Dafür nutze ich mehrere Level:

  • alle und immer
  • alle, aber nur einmal pro Zeitraum
  • alle, aber Dopplungen werden für einen gewissen Zeitraum gefiltert
  • erst wenn ein „Warnlevel“ überschritten wird

Anhand des Topics der Benachrichtigung wird bei mir zwischen den unterschiedlichen Leveln variiert. Das sieht aktuell dann so aus:

Nur einmal pro Zeitraum

Nur einmal pro Zeitraum funktioniert ganz einfach über das Delay-Node über „Nachrichtenrate begrenzen“. Wichtig ist hier nur die Aktivierung des Feldes „Zwischennachrichten löschen“.

Erst wenn ein Warnlevel überschritten wird

Beim Warnlevel muss in einem bestimmten Zeitraum eine gewisse Anzahl von Benachrichtigungen eingegangen sein. Nach Ablauf des Zeitraums wird die Zählung genullt. Ich nutze sie vor allem für Sensor- oder Aktor-Erreichbarkeitsprobleme im WLAN oder für Schnittstellen zu externen Datenquellen. Wenn einmal ein Ping z.B. zu einem Shelly nicht zustande kommt, sagt das nicht viel aus. Passiert das innerhalb von drei Stunde mehrfach, liegt vielleicht ein Problem vor.

Mein Code ist nichts besonderes, der Vollständigkeit halber aber trotzdem hier:

msg.warnlevel = flow.get("warnlevel_wlan")+1;
flow.set("warnlevel_wlan",msg.warnlevel);

if(msg.warnlevel > 10) {
     return msg;
}

Dazu noch das entsprechende „Nullen“ nach Ablauf einer Frist. Hierbei nutze ich einen festen Rhythmus, sodass das Alter der Warnungen nicht berücksichtigt wird. In meinen Augen ist das aber nicht weiter schlimm, da ich die Methode „Warnlevel“ eh nur bei nicht-sicherheitsrelevanten Benachrichtigungen nutze. Außerdem werden alle Benachrichtigungen ja auch im UI angezeigt, sodass man dort auch „drüberstolpern“ kann.

Dopplungen filtern

Bei den Unwetterwarnungen filtere ich Dopplungen heraus. Die Informationen werden regelmäßig abgerufen, daraus ergibt sich, dass ein und die selbe Meldung vielfach abgerufen wird. Um nicht jedes Mal wieder Alarm zu geben, werden identische Meldungen 24 Stunden lang geblockt. Dazu speichere ich bereits gepushte Meldungen in den Kontextdaten und gleiche das entsprechend ab.

Flow als Download

Benötigt werden die Nodes von node-red-contrib-combine.

5 Gedanken zu „Ein flexibler Benachrichtigungsbereich in Node-RED Dashboard“

    1. Hallo Konrad,
      ich habe mal ein paar Nodes zusammengestellt und als Download in den Artikel eingefügt. Bei Fragen oder Problemen, melde dich einfach.
      Lukas

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert