setState: Synchrone Verarbeitung der ioBroker Homematic RPC Adapter Befehle via BIN-RPC/XML-RPC um Probleme bei der Kommunikation zu vermeiden

Setzt man neben Homematic Komponenten und der Steuerung via CCU (o. ä. piVCCU/RaspberryMatic…) zusätzlich auch das ioBroker Smart-Home-System ein, kommt man eigentlich um die Installation und Nutzung des ioBroker HomeMatic RPC Adapters (ioBroker.hm-rpc) zur Anbindung an die Kommunikationsmodule der Steuerungszentrale nicht herum. Dabei kommuniziert der Adapter mit einer Schnittstelle von der Steuerungszentrale, entweder über das BIN-RPC oder XML-RPC Protokoll. Oft müssen auch mehrere Adapter-Instanzen gleichzeitig laufen, da eine Instanz des Adapters nur für genau EINES der unterstützen Module (rfd (funk), HMIP-rfd, hs485d (wired), cuxd ..) zuständig sein kann.

Leider kam es bei Änderungen von Datenpunkten in ioBroker bei mir regelmäßig zu Übertragungsprobleme, sobald der Adapter versucht die Werte zur Steuerung der Homematic Komponenten an die Zentrale zu übertragen. Teilweise kommt dann eine entsprechende Meldung im ioBroker Log, was aber nicht immer der Fall sein muss.

Logmeldung – Beispiele:
error: hm-rpc.0 (26742) xmlrpc -> setValue ["MEQXXXXXXXX:1","LEVEL",1] FLOAT
error: hm-rpc.0 (26742) Cannot call setValue: XML-RPC fault: Failure

oder
error: hm-rpc.0 (26742) Error: XML-RPC fault: Generic error (TIMEOUT)

In all diesen Fällen, wurde der Wert nicht korrekt übertragen und die gewünschte Aktion nicht ausgeführt. Diese Problematik konnte ich vor allem dann beobachten, wenn viele Werte der Homematic-Datenpunkte in kurzer aktualisiert werden.

Beispiele: wenn Datenpunkt-Werte mittels Iteration in einem Script gesetzt oder mehrere Scripte mit solchen Aktionen zeitgleich oder kurz hintereinander laufen.

Leider konnte ich dieses Problem bisher nicht wirklich lösen, trotz intensiver Recherche und ausprobieren unterschiedlicher Lösungsansätze wie setStateDelayed, setTimeout usw….

Um das Problem trotzdem in den Griff zu bekommen, habe ich deshalb nachfolgendes Script als Workaround entwickelt. Zumindest bisher trat damit, bei konsequenter Verwendung in ioBroker Scripte, das Problem nicht mehr auf.

Script – Funktionsweise

Anstelle der Verwendung des Befehls setState zum Setzen neuer Werte, muss die gleichnamige Funktion „setState“ der „GlobalStateHandler“ Klasse verwendet werden. Diese führt bei Homematic Datenpunkten nicht sofort den „setState“ Befehl aus, sondern fügt zuerst die Aktion zu einer Warteschlange (Queue) hinzu. Die Abarbeitung der Queue wird danach sofort begonnen. Läuft jedoch bereits eine Verarbeitung, muss die Aktion solange mit der Abarbeitung warten, bis alle vorherigen Aktionen in der Queue verarbeitet wurden. Durch die synchrone Verarbeitung „zum Entprellen“ (Debounce) ist sichergestellt, dass nicht mehrere „setState“ Befehle gleichzeitig über Scripte gestartet werden, die sich ggf. gegenseitig beeinträchtigen können. Die Verarbeitung des nächsten Eintrags in der Warteschlange wird dann fortgesetzt, sobald für den betroffenen Datenpunkt, die Anerkennung der Änderung durch das Acknowledge (ack) Flag bestätigt wurde. Da nicht alle Homematic-Komponenten eine Rückmeldung für die Verarbeitung innerhalb des definierten Zeitraums zurückliefern, wird die Verarbeitung der Warteschlange nach erreichen eines Timeouts fortgesetzt.

Script – Installation

Der JavaScript-Code muss in ioBroker als globales Script eingerichtet werden. Somit ist eine zentrale Instanz der „GlobalStateHandler“ Klasse in allen Scripten verfügbar. Hierzu muss zuerst im Scripte Bereich des Javascript Script Engine Adapters, der Expertenmodus aktiviert werden. Danach sollte der neue Ordner/Bereich „global“ sichtbar sein, in dem das Script gespeichert werden muss.

Script – Verwendung

Beispiel 1:
Durch den await Befehl, wartet das Script solange, bis die „setState“ Aktion ausgeführt wurde und setzt dann das Script fort.

 (async () => { 
    const id_test_state = "javascript.0.variables.test";

    setTimeout(async function(){ await GSH.setState(id_test_state, '2'); }, 500);
    setTimeout(async function(){ await GSH.setState(id_test_state, '3'); }, 500);
    setTimeout(async function(){ await GSH.setState(id_test_state, '4'); }, 500);
    await GSH.setState(id_test_state, '1'); 

})();

Beispiel 2:
Die „setState“ Aktionen werden ohne zu warten der Warteschlange hinzugefügt und nacheinander abgearbeitet. Durch die Funktion „waitWhileProcessing“ besteht aber zusätzlich die Möglichkeit zu warten, bis alles aus der Warteschlange abgearbeitet wurde.

 const id_test_state = "javascript.0.variables.test";

 setTimeout(function(){ GSH.setState(id_test_state, '3'); }, 500);

 GSH.setState(id_test_state, '1'); // do not wait until action have been processed
 GSH.setState(id_test_state, '2'); 

 (async () => { 
    await GSH.waitWhileProcessing(); // wait until all actions in queue have been processed
    log('Complete! All queued actions are processed');
 })();

Script – Hinweis

Natürlich ist das Script nicht wirklich „die Lösung“ des eigentlichen Problems. Auch wird bedingt durch die synchrone Verarbeitung, die Ausführung von mehreren Befehlen verzögert. Daher sollte das Script bewusst und mit Be­dacht eingesetzt werden.

Script – Quellcode

https://github.com/mesche/iobroker-scripts/tree/master/iobroker_global_state_handler

SQL-History Adapter – Einstellungen der Datenpunkte sichern/wiederherstellen

Vor kurzem war es notwendig, dass ich aufgrund einer Aktualisierung eines Adapters im ioBroker Smart-Home-System, die bisher angelegten Datenpunkte komplett löschen und neu erzeugen musste.

Wichtig hierbei zu beachten: Es dann auch alle SQL-History Adapter Einstellungen für die betroffenen Datenpunkte gelöscht.

Um nicht alle Einstellungen manuell zu sichern und anlegen zu müssen, habe ich zwei kleine JavaScript Programme (nachfolgend „Script“ genannt) geschrieben, welche die Aufgaben übernehmen.

Es wurde jeweils für die Sicherung der Einstellungen und für die Wiederherstellung ein eigenes Script erzeugt. Diese können unabhängig voneinander ausgeführt werden.

Script – Backup (Sicherung)
Liest die aktuellen Einstellungen für alle vorhandenen Datenpunkte aus, bei denen der SQL-History Adapter aktiviert ist. Dafür wird die Funktion getEnabledDPs verwendet, welche direkt vom Adapter zur Verfügung gestellt wird. Die Einstellungen werden in einem eigenen Datenpunkt gesichert, welcher vom Script automatisiert angelegt wird.

Script: iobroker_sql_history_backup_dp_settings.js

Script – Restore (Wiederherstellung)
Stellt die gesicherten SQL-History Adapter Einstellungen wieder her, welche zuvor über das Backup-Script in einem Datenpunkt gespeichert wurden. Zum Setzen der Einstellungen wird die Nachrichten-Funktion enableHistory verwendet, welche direkt vom Adapter zur Verfügung gestellt wird.

Script: iobroker_sql_history_backup_restore_dp_settings.js

Script – Voraussetzungen
Damit die Scripte funktionieren und ausgeführt werden können, müssen nachfolgende Adapter als Instanz unter ioBroker installiert und eingerichtet sein.

ioBroker.sql (History) Adapter
– ioBroker.javascript Adapter

Script – Installation
Jedes Script muss in ioBroker jeweils als eigenes Script vom Typ „JavaScript“ angelegt werden.
Ggf. müssen am Script selbst die Parameter für die Instanzen oder wenn gewünscht die ID des Datenpunkts entsprechend angepasst werden.

Script – Quellcode
Aktuelle Version der Scripte findet man unter:
https://github.com/mesche/iobroker-scripts/tree/master/iobroker_sql_history_backup_dp_settings

Ungültige / abgelaufene (expired) Schlüssel der Linux-Paketquellen unter Debian aktualisieren

Bei der Wartung des Linux-Betriebssystems Debian trat das Problem auf, dass die GPG-Schlüssel des GNU-Privatsphärenschutzes (GNU Privacy Guard) von einzelnen Paketquellen abgelaufen (engl. expired) waren. Genauer gesagt trat dieses Problem beim Neueinlesen bzw. Aktualisieren der verfügbaren Pakete auf.

 sudo apt-get update 

Analyse

Um sich alle abgelaufenen Schlüssel auflisten zu lassen, kann folgender Befehl verwendet werden.

 sudo LANG=C apt-key list | grep -A 1 expired 

Mit dem Parameter "LANG=C" wird sichergestellt, dass die Ausgabe der Liste immer in englisch erfolgt und zwar unabhängig von der aktuellen Spracheinstellung des Betriebssystems. Somit kann mit grep nach dem Wort "expired" gefiltert werden.

Lösung

Um das Problem zu lösen, muss der abgelaufene Schlüssel aktualisiert werden.

 sudo apt-key adv --keyserver keys.gnupg.net --recv-keys $KEY$ 


Mit dem Programm apt-key  für den Schlüsselverwaltungsdienst
, kann der vom Programm Advanced Package Tool (apt) zur Authentifizierung von Paketen verwendete Schlüsselring verwaltet werden. Der Parameter "$KEY$" muss natürlich durch den entsprechenden Schlüssel ersetzt werden.

 sudo apt-key adv --keyserver keys.gnupg.net --recv-keys B188E2B695BD4743 

Danach sollte „apt-get update“ wieder ohne Fehlermeldung durchgeführt werden können.

Warn-App NINA – Eventhandler-Script um Nachrichten zu verarbeiten & weiterzuleiten

Mit der Notfall-Informations- und Nachrichten-App (NINA) des Bundes, können wichtige amtliche Warnungen und Informationen erhalten werden. Dazu zählen u. a. Informationen des Bevölkerungsschutzes für unterschiedliche Gefahrenlagen wie z. B. Gefahrstoffausbreitung, Wetterwarnungen des Deutschen Wetterdienstes und Hochwasserinformationen der zuständigen Stellen der Bundesländer.

Script – Beschreibung
Damit nicht jede Person in unserer Familie die NINA-App installieren muss, wurde ein kleines Script entwickelt, welches diese Informationen regelmäßig verarbeitet und an unterschiedliche Systeme weiterleiten kann. Implementiert wurde bisher die Anbindungen der Notification-Dienste für Pushover und Telegram.

Script – Voraussetzung
Durch den NINA-Adapter für ioBroker, können diese Nachrichten regelmäßig abgerufen und in das System integriert werden. Diese ist Voraussetzung und muss vorab installiert werden.

Je nachdem welche Anbindung verwendet werden soll, muss hierzu ein entsprechender Adapter für den Dienst installiert und eingerichtet werden.
Pushover Adapter
Telegram Adapter

Script – Quellcode
Aktuelle Version des Scripts findet man unter:
https://github.com/mesche/iobroker-scripts/tree/master/nina_messages_eventhandler


Workaround: Script-Editor – Icons werden nicht angezeigt – Codicon Font defekt

Seit einigen Versionen (aktuell 5.0.15) des Javascript Script Engine – Adapters für ioBroker besteht leider das Problem, dass die Icons/Grafiken im Script-Editor nicht mehr angezeigt werden.

Ursache:
Der Grund für das Problem dürfte eine defekte Codicon TrueType-Schriftartendatei sein. Diese stellt normalerweise die Grafiken für die Icons bereit.

Bug-Tickets:
Ticket #751 – Suchfunktion -> Grafikfehler
Ticket #761 – Icons are not displayed

Workaround:

cd /opt/iobroker/
cd node_modules/iobroker.javascript/admin/vs/base/browser/ui/codicons/codicon/
cp codicon.ttf codicon.ttf-org
curl -L -o codicon.ttf https://github.com/microsoft/vscode-codicons/blob/main/dist/codicon.ttf?raw=true
iobroker upload javascript

Workaround zurücksetzen:

cd /opt/iobroker/
cd node_modules/iobroker.javascript/admin/vs/base/browser/ui/codicons/codicon/
mv codicon.ttf-org codicon.ttf
iobroker upload javascript

Wichtig: Ggf. Pfad zum ioBroker-Verzeichnis anpassen und Befehle mit entsprechenden Benutzer ausführen.

Ergebnis: