Meine Systemvariablen haben Duty Cycle als Präfix, gefolgt von den Seriennummern der Geräte. Entsprechend steht dies hier an erster Stelle. Achten Sie auf Groß– und Kleinschreibung und auf das Leerzeichen am Ende des Strings.
Um den Duty Cycle zu überwachen, kann man ihn in einer Systemvariablen speichern
Auf dieser Seite
Um gesetzlichen Vorgaben zu genügen, darf die CCU höchstens 1 % pro Stunde senden – also 36 Sekunden. Wird dieser Wert überschritten, gibt es üble Kommunikationsstörungen.
Den aktuellen Wert kann man nicht direkt über die WebUI abfragen, aber mit Hilfe eines Scripts kann man für den Duty Cycle einen Wert von 0-100 % in Erfahrung bringen.
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.
Das Programm startet einen Systembefehl, mit dem der aktuelle Duty Cycle angezeigt wird – tatsächlich ein minimales Tcl-Script, das ich hier von alchy aus dem HomeMatic-Forum kopiert habe. Bei der weiteren Bearbeitung des Ergebnisses gehe ich dann einen etwas anderen Weg, aber am Ende wird auch bei mir eine Zahl in einer Systemvariablen landen.
Ich verwende hier den CUx-Daemon, um Systembefehle auszuführen, da das Script regelmäßig ausgeführt wird und system.Exec() bei so etwas gerne zu Instabilität führt.
Ich beschreibe zwei Varianten, um den Duty Cycle regelmäßig zu aktualisieren. Beide verwenden den CUx-Daemon, um Befehle auf Betriebssystemebene auszuführen.
Die Einrichtung eines Exec-Gerätes im CUx-Daemon habe ich schon anderenorts beschrieben.
Hier reserviere ich also nur noch einen Kanal für den Duty Cycle. Wichtig ist die Seriennummer des Kanals – hier der erste Kanal des virtuellen Gerätes.
Wenn man Werte in Systemvariablen speichern möchte, dann muss man diese natürlich vorher anlegen.
Die einfallslose Variable des Tages heißt bei mir heute Duty Cycle und kann einen Wert von 0 bis 100 einnehmen.
Das WebUI-Programm sieht dann so aus:
Das Programm triggert sich selbst: Wenn es ausgelöst wird, wird nach 270 Sekunden ein Script ausgeführt, das Duty Cycle aktualisiert. Durch die Aktualisierung wird wieder das Programm ausgelöst – ad inifinitum. Wichtig ist daher entsprechend der Logik von WebUI-Programmen die Auswahl bei Aktualisierung auslösen.
Das hinterlegte Script ist dieses:
gesamtes Script markieren / kopieren
! HomeMatic-Script ! DUTY CYCLE ABFRAGEN ! http://www.christian-luetgens.de/homematic/cuxd/dutycycle/Duty_Cycle.htm dom.GetObject ("CUxD.CUX2801001:1.CMD_SETS").State("echo 'load tclrpc.so; puts [xmlrpc http://127.0.0.1:2001/ listBidcosInterfaces ]'|tclsh | awk '// { printf $10 }'"); dom.GetObject ("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1); string s_reply = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State(); dom.GetObject ("Duty Cycle").State (s_reply.ToFloat()); ! Ende des Scripts
Als erstes lege ich den auszuführenden Befehl für mein CUxD-Gerät fest. Dann bestimme ich, dass ich das Ergebnis auslesen möchte und starte den Befehl. Nachdem er ausgeführt wurde, wird das Ergebnis in Duty Cycle geschrieben.
Einen ganz großen Haken gibt es jedoch: Abhängig von der Konfiguration muss der auszuführende Befehl angepasst werden. Dazu gehe ich per ssh auf meine CCU und setze den Befehl, der mir die Rohdaten für den Duty Cycle liefert, per Hand ab.
# echo 'load tclrpc.so; puts [xmlrpc http://127.0.0.1:2001/ listBidcosInterfaces ]'|tclsh {ADDRESS JEQ0000000 CONNECTED 1 DEFAULT 0 DESCRIPTION {} DUTY_CYCLE 0 FIRMWARE_VERSION 961 TYPE {Lan Interface}} {ADDRESS KEQ0000000 CONNECTED 1 DEFAULT 1 DESCRIPTION CCU2-Coprocessor DUTY_CYCLE 18 FIRMWARE_VERSION 2.4.3 TYPE CCU2} #
Die Antwort besteht aus zwei Sätzen von Daten: Meinem LAN-Adapter, den ich als Gateway einsetze, und der CCU selbst. Hier etwas übersichtlicher:
{ADDRESS JEQ0000000 CONNECTED 1 DEFAULT 0 DESCRIPTION {} DUTY_CYCLE 0 FIRMWARE_VERSION 961 TYPE {Lan Interface}} {ADDRESS KEQ0000000 CONNECTED 1 DEFAULT 1 DESCRIPTION CCU2-Coprocessor DUTY_CYCLE 18 FIRMWARE_VERSION 2.4.3 TYPE CCU2}
Der LAN-Adapter liefert immer nur 0 % – also brauche ich nur die CCU, die an zweiter Stelle steht. Mit awk nehme ich daher einfach den 25. Eintrag der Zeile heraus. Das ist der Duty Cycle, im Beispiel mit aktuellem Wert von 18.
# echo 'load tclrpc.so; puts [xmlrpc http://127.0.0.1:2001/ listBidcosInterfaces ]'|tclsh | awk '// { printf $25 }' 18#
Würde ich printf $10 schreiben, bekäme ich den zehnten Wert der Zeile – das wäre dann der Duty Cycle meines Konfigurationsadapters.
# echo 'load tclrpc.so; puts [xmlrpc http://127.0.0.1:2001/ listBidcosInterfaces ]'|tclsh | awk '// { printf $10 }' 0#
Wer nur die CCU betreibt, sollte also mit meinem obigen Script ohne Anpassungen klarkommen. Wer dagegen mehrere Sender hat, der muss per SSH oder Telnet auf die Shell der CCU, sich die Rohdaten anschauen und dann den passenden Wert auswählen – oder die etwas kompliziertere Variante verwenden, die ich weiter unten beschreibe.
Bei der einfachen Lösung lasse ich das Programm sich immer wieder selbst auslösen. Ich erhalte so eine weitere Systemvariable, die ich als Systemtakt verwenden kann. So kann ich zyklische Funktionen der CCU regelmäßig ausführen lassen – aber nur, wenn der Duty Cycle noch nicht zu hoch ist.
Ein Beispiel ist das Ladegerät meines Rasenmäh-Roboters. Wegen schlechter Funkverbindung zum Aktor im Garten habe ich hier alles aufgeboten, was zur Vermeidung von Funkstörungen nur möglich ist: Der Aktor wird über eine direkte Verknüpfung als Treppenhauslicht eingeschaltet, so dass er – bei Funkstörungen – nach einiger Zeit in seinen sicheren, ausgeschalteten Zustand zurückfällt.
Mit Duty Cycle als Systemtakt habe ich nun eine weitere Einschränkung: Wenn der Duty Cycle größer ist als 50 %, dann wird das Ladegerät gar nicht erst eingeschaltet. Dadurch reduziere ich auf elegante Art den regelmäßigen Funkverkehr, wenn ich mich der gesetzlichen Grenze nähere und der Totalausfall droht.
Um alle Duty-Cycle-Werte aller Adapter abzufragen, baue ich mir ein etwas komplexeres Programm. Ich erstelle als erstes zwei Systemvariablen vom Typ Zahl, jeweils einen für meine CCU und für meinen LAN-Konfigurationsadapter, den ich als Gateway einsetze. Wichtig ist hier, dass beide Systemvariable mit der Seriennummer des Gerätes enden.
Auch der Präfix Duty Cycle muss identisch sein. Man kann ihn ruhig anders nennen, aber er muss bei allen Geräten übereinstimmen.
Das WebUI-Programm ist sehr übersichtlich. Ich lasse es zunächst durch meinen Systemtakt auslösen, aber man kann es auch durch das Zeitmodul triggern lassen. Als Zyklus reichen meines Erachtens fünf Minuten. Je häufiger eine Systemfunktion ausgeführt wird, desto größer ist die Wahrscheinlichkeit, dass die CCU irgendwann zickt.
Das Script, das im Programm ausgeführt wird, ist dieses:
gesamtes Script markieren / kopieren
! HomeMatic-Script ! DUTY CYCLE ABFRAGEN ! http://www.christian-luetgens.de/homematic/cuxd/dutycycle/Duty_Cycle.htm string s_prefix = "Duty Cycle "; string s_cuxd = "CUxD.CUX2801001:1"; string s_cmd = "echo 'load tclrpc.so; puts [xmlrpc http://127.0.0.1:2001/ listBidcosInterfaces ]'|tclsh"; dom.GetObject (s_cuxd # ".CMD_SETS").State(s_cmd); dom.GetObject (s_cuxd # ".CMD_QUERY_RET").State(1); string s_reply = dom.GetObject(s_cuxd # ".CMD_RETS").State(); string s_atom; string s_address; integer i_run = 0; object o_sysvar; foreach (s_atom, s_reply.Split (" ")) { if (i_run == 0) { if (s_atom.Find ("ADDRESS") >= 0) { i_run = 1; } if (s_atom.Find ("DUTY_CYCLE") >= 0) { i_run = 2; } } else { if (i_run == 1) { s_address = s_atom; } if (i_run == 2) { o_sysvar = dom.GetObject (s_prefix # s_address); if (o_sysvar) { o_sysvar.State (s_atom.ToFloat()); } } i_run = 0; } } ! Ende des Scripts
Präfix definieren
Meine Systemvariablen haben Duty Cycle als Präfix, gefolgt von den Seriennummern der Geräte. Entsprechend steht dies hier an erster Stelle. Achten Sie auf Groß– und Kleinschreibung und auf das Leerzeichen am Ende des Strings.
CUxD-Gerät definieren
Wie geschrieben läuft das Programm bei mir als erster Kanal auf dem virtuellen CUxD-Gerät. Daher steht hier die (virtuelle) Seriennummer und :1 für den ersten Kanal.
Externes Script ausführen
Der Systembefehl wird definiert und dem CUxD zur Ausführung übergeben. Das Script wartet, bis eine Antwort da ist, und speichert sie in s_reply.
Antwort auswerten
Die erhaltene Antwort wird in einzelne Wörter (getrennt durch Leerzeichen) aufgeteilt und die Daten extrahiert:
Ist der Datensatz komplett, sucht das Script die Systemvariable anhand von Präfix und Seriennummer. Wird sie gefunden, wird der Wert gespeichert. Wird sie nicht gefunden, macht das auch nichts – man kann also allein durch Nichtanlegen von Systemvariablen bestimmen, für welche Geräte man Rückmeldungen wünscht
Das passiert für alle Werte, die der Systembefehl zurückliefert.
Das Ergebnis habe ich hier auf die Startseite meiner CCU gelegt.
Mein LAN-Konfigurationsadapter (Seriennummer JEQ…) liefert immer nur 0 – vermutlich ist seine Firmware zu alt für sinnvolle Werte. Ich kann die Systemvariable also beruhigt entfernen.
Die CCU (Seriennummer KEQ…) liegt bei 4 % ihres Duty Cycle. Das ist ein durchaus entspannter Wert, bei dem alles läuft.