Just Can’t Get Enough

Wenn die Telegram-Meldungen hereinprasseln, braucht man eine Warteschlange

Nachdem das Telegram-Framework jetzt seit Jahren problemlos seinen Dienst versieht, gibt es nun noch eine klitzekleine Verbesserung, über die ich seit fast ebensovielen Jahren nachgedacht hatte: Eine Queue für die Nachrichten.

Das Aufsetzen einer neuen HomeMatic erinnert mich dunkel an die vagen Ideen in den vergessensten Ecken meines alternden Hirns und ich schreite beherzt zur Umsetzung.

Neue Script-Funktionen

Mit Firmware 2.29.22 wurden neue Funktionen in der Scriptsprache der CCU eingeführt, die auf dieser Seite genutzt werden. Achten Sie darauf, als Logikschicht-Version in den Systemeinstellungen der CCU nicht „Legacy“ zu wählen.

Wenn Sie eine ältere Firmware verwenden oder als Logikschicht-Version „Legacy“ ausgewählt haben, werden Sie Script-Fehler angezeigt bekommen, wenn Sie diese Anleitung umsetzen. Die Programme werden nicht funktionieren.

Aktualisieren Sie die Firmware Ihrer CCU! Wählen Sie „Standard“ als Logikschicht-Version aus!

Veraltete wget-Version verhindert Verbindungsaufbau

Im Februar 2020 hat Telegram die TLS-Parameter für den Zugang zur Telegram-API geändert. Ältere Versionen von wget können damit nicht umgehen und deshalb auch keine Nachrichten mehr über Telegram absenden.

Aktualisieren Sie die Firmware Ihrer CCU, in der ein neueres wget enthalten ist, um dieses Problem zu beheben!

Variablen in HomeMatic-Scripten

Die CCU hatte früher ein Limit von maximal 200 Variablen, das mit Firmware-Version 2.29.18 aufgehoben wurde. Dieses Limit bezog sich auf alle Variablen, die in allen Scripten verwendet werden. Gemeint sind Variablen, die direkt im Script definiert werden: object x; object y; var z;

Wenn Scripte nicht mehr funktionieren und bei der Prüfung unerklärliche Syntax-Fehler auftreten, sollte versuchsweise dieses Programm wieder gelöscht oder deaktiviert werden – oder, noch besser, auf die aktuelle Firmware-Version aktualisiert werden.

Strings in HomeMatic-Scripten

Durch String-Verwendung in HomeMatic-Scripten kann die CCU fehlerhaft arbeiten, instabil werden oder sogar abstürzen. Grundsätzlich gilt: Je öfter mit Strings hantiert wird, desto eher führt dies zu Problemen.

Ich empfehle daher, nach Umsetzung dieser Anleitung die CCU unter Beobachtung zu halten.

Benennung von Systemvariablen

Prinzipiell kann man Systemvariablen – so wie allen Objekten in der CCU – beliebige Namen geben, also z. B. auch Umlaute und Sonderzeichen verwenden. Ich empfehle jedoch, sich auf reguläre Buchstaben (a-z, A-Z) zu beschränken: Bei Umlauten und Sonderzeichen besteht die Gefahr, dass Systemvariablen in Scripten nicht überall gefunden werden.

Problem: Verzögerungen und Nachrichten

Bei der Nutzung des bisherigen T-Frameworks muss man ein bisschen darauf achten, dass verschiedene WebUI-Programme sich nicht gegenseitig die Nachrichten wegschießen. Wenn man nicht aufpasst, kann es passieren, dass Programm eins eine Nachricht mit Verzögerung absendet und Programm zwei dazwischenfunkt, die laufende Verzögerung abbricht und seine eigene Nachricht sendet.

Beinahe noch größer ist das Problem, wenn man mehrere Nachrichten aus einem oder mehreren WebUI-Programmen nacheinander absenden möchte. Man muss unter Umständen mit einer Reihe von verzögerten Scripten arbeiten und die WebUI-Programme auch untereinander passend verzögert ausführen lassen.

Geht alles, ist aber doof. Die Lösung lautet: Warteschlange

Statt wie bisher bei Änderung der Systemvariable (bei mir Telegram genannt) sofort die Telegram-API aufzurufen und die Nachricht abzusenden, hänge ich den Text zunächst an eine weitere Systemvariable (bei mir Telegram.Queue) an. Der bisherige Wert in Telegram.Queue bleibt bestehen, der neue wird mit einem Tabulator getrennt angehängt.

Ein zweites WebUI-Programm kümmert sich um Telegram.Queue: Wenn diese Zeichenkette aktualisiert wird und nicht leer ist, wird der Text bis zum ersten Tabulator abgesendet und alles weitere wieder gespeichert. Durch das Speichern löst sich das Programm so lange immer wieder selbst aus, bis alle Nachrichten gesendet wurden.

Zusätzliche Systemvariable

Ich setze bei dieser Anleitung mein funktionierendes T-Framework voraus, das heißt, ich habe schon eine Systemvariable Telegram, die von verschiedenen WebUI-Programmen angesprochen wird, und ein Versandprogramm, das auf die Variable reagiert.

Als nächstes – ich bin versucht, zu sagen: wie immer – erstelle ich eine zusätzliche Systemvariable.

Es handelt sich genau wie bei Telegram um eine Zeichenkette und ich nenne sie Telegram.Queue.

WebUI-Warteschlange

Wie oben beschrieben, teilt sich der Versand in zwei WebUI-Programme auf.

Das erste Programm führt ein Script aus, um Telegram.Queue zu füllen.

Wie gehabt reagiert es auf Aktualisierungen der Systemvariablen Telegram, in die meine Programme und Scripte die abzusendenden Texte schreiben.

Ist die Variable leer, passiert nichts, sonst wird das folgende Script augeführt:

! HomeMatic-Script
! JUST CAN'T GET ENOUGH
! http://www.christian-luetgens.de/homematic/telegram/queue/Warteschlange.htm

object o_telegram = dom.GetObject ("Telegram");
object o_queue = dom.GetObject ("Telegram.Queue");

if (o_telegram.Value() != "") {
  o_queue.State ((o_queue.Value() # "\t" # o_telegram.Value()).Trim());
  o_telegram.State ("");

}

!  Ende des Scripts

Das Script sucht zunächst beide Systemvariablen heraus. Wenn Telegram wirklich einen Text enthält (die CCU führt leider manchmal auch dann das Script aus, wenn die Variable in Wirklichkeit leer sein sollte), wird der Inhalt an Telegram.Queue gehängt und Telegram geleert.

Das abschließende .Trim() sorgt relativ elegant dafür, dass keine Leerzeichen oder Tabulatoren am Anfang oder Ende der Queue stehen. Das würde unweigerlich passieren, wenn die Queue leer ist, während das Script ausgeführt wird.

WebUI-Versand

Das zweite WebUI-Programm kümmert sich wie angekündigt um den Versand der Nachrichten, die in Telegram.Queue aneinandergereiht wurden.

Das WebUI-Programm ist wieder langweilig. Wie immer bei Aktualisierung auslösen, wie immer steht der spannende Teil im Sonst…-Zweig.

Wichtig ist noch, dass das Script um eine Sekunde verzögert ausgeführt wird. Da das Programm sich immer wieder selbst auslöst, werden damit die Nachrichten aus der Queue im Sekundentakt an die Telegram-API übergeben und versendet. Das entlastet die CCU und verhindert Überschneidungen oder Verlust von Nachrichten.

Das auszuführende Script ähnelt dem bisherigen Versandscript das T-Frameworks

object o = dom.GetObject ("Telegram.Queue");

if (o.Value() != "") {
  boolean b_first = true;
  string s;
  string t = "";
  foreach (s, o.Value()) {
    if (b_first) {
      string s_cmd = "wget --no-check-certificate --quiet -O /dev/null \"https://api.telegram.org/bot314321353:AAFKjr29dF940b-aTchoFJ_pb6oZKxzx8Zw/sendMessage?chat_id=374629384&parse_mode=Markdown&text=" # s.ToUTF8().UriEncode() # "\"";
      dom.GetObject("CUxD.CUX2801001:5.CMD_EXEC").State (s_cmd);
      b_first = false;
    } else {
      t = t # "\t" # s;
    }
  }

  o.State (t.Trim());
  
}

Das Script sucht sich als erstes die neue Systemvariable Telegram.Queue heraus. Wenn diese nicht leer ist, wird sie in ihre Einzelbestandteile – geteilt durch Tabulatoren – zerlegt. Der erste Teil wird über die Telegram-API gesendet, der Rest wird in einer neuen Systemvariable t zusammengefügt, auch hier durch Tabulatoren getrennt.

Ganz zum Schluss wird Telegram.Queue mit dem Wert von t gefüllt, wobei auch hier mit .Trim() unnötige Leerzeichen oder Tabulatoren entfernt werden.

Test

Zum Testen klatsche ich einen Einzeiler in den Scriptparser:

dom.GetObject ("Telegram").State ("*Achtung! Achtung!*\tDies ist ein Test.\tDas Unglück muss zurückgeschlagen werden.\tVielen Dank für Ihr Verständnis.");

Hier erkennt man, dass ich natürlich auch Texte in die Systemvariable Telegram schreiben kann, die bereits fertig durch Tabulatoren getrennt sind und die dann – so, wie sie sind – an Telegram.Queue gehängt und daraus einzeln versendet werden.

Das Ergebnis: Nach dem üblichen Geplapper meiner HomeMatic aus den vergangenen Tagen kommen in kurzem Abstand die vier Nachrichten, die ich per Scriptparser gesendet habe.

Die fehlerhaften Umlaute liegen übrigens wieder am Scriptparser. Texte in der WebUI oder in Scripten werden genau wie beim T-Framework korrekt wiedergegeben.

Jetzt kann ich loslegen und mir von meiner Hausautomation kleine Romane zusammenstellen lassen.

Völlig gedankenlos kann man leider immer noch nicht programmieren: Wenn mehrere Programme oder Scripte gleichzeitig ausgeführt werden sollen, überschreiben sie trotzdem gegenseitig die Systemvariable, bevor das Queue-Script sie abräumen kann. Man kann das vermeiden, indem man in Scripten die neuen Texte wieder mit \t an den bestehenden Inhalt der Systemvariablen hängt.

Navigation