Homematic Script für „Dummies“ Teil 1 – Rechnen mit Variablen und Aktoren
Von der Homematic Programmiersprache „TCL“ habe ich keine Ahnung. Daher dachte ich mir, dass man fast alles lernen kann, und wir die Grundzüge der Homematic Scriptsprache zusammen lernen können. In den folgenden Abschnitten möchte ich euch erklären, wir es möglich ist, mit einzelne Aktoren zu rechnen.
In meinem Beispiel war es so, dass ich einige Stromverbraucher addieren wollte. Wie immer, hat mir auch hier wieder Jerome Pech geholfen.
Um ein Script zu erstellen empfehle ich, den Button „Script testen“ zu nehmen. Der befindet sich im Reiter „Programme und Zentralenverknüpfungen“.
Ganz unten der vierte Button.
Das nun offene Fenster wird unsere „Spielwiese“. Es kann gerne mal sofort auf „Ausführen“ geklickt werden. Es werden immer die Werte ausgegeben, die in den Klammern von „WriteLine“ stehen.
Los geht´s…
Wir fangen mit einer simplen Addition an. Hierfür müssen wir Variablen nutzen. (Diese müssen NICHT in der CCU angelegt werden). Jetzt gibst du einfach die unteren Zeilen in das Fenster ein. (Ich empfehle das wirklich abzuschreiben und nicht zu kopieren, da man es sich so leichter merken kann).
1 Zeile:
Wir erstellen (virtuell) eine Variable „a“ und sagen, dass die Variable „a“ den Wert von „1“ hat.
2 Zeile:
Hier das selbe, nur dass die Variable „b“ einen Wert von „5“ hat.
3 Zeile:
Hier erstellen wir die Berechnung, mit Hilfe der Variablen „c“ und sagen. Variable „c“ ist gleich Variable „a“ + „b“.
var a = 1 var b = 5 var c = a+b
Wer jetzt schon auf „Ausführen“ gedrückt hat, wird feststellen, dass das noch nicht funktioniert. Wir müssen nämlich noch die „Regeln der Scriptsprache“ beachten. Daher muss nämlich nach jeder Zeile ein „;“ gemacht werden. Fertig sieht das dann so aus:
var a = 1; var b = 5; var c = a+b;
Das Script würde jetzt schon funktionieren. Aber um eine visuelle Ausgabe des Codes zu erhalten, muss noch eine Zeile dazu, die das Ergebnis ausgibt. (Diese Zeile sollte wieder gelöscht werden, wenn das Script in ein Programm eingebunden wird) Das ist erstmal wirklich nur zum „spielen“.
WriteLine();
Das Wort „WriteLine“ (Groß- und Kleinschreibung beachten), gibt den Wert innerhalb der Klammer optisch aus. Wir wollen die Variable „c“ ausgegeben haben, also schreiben wir „c“ in die Klammern.
WriteLine(c);
Fertig sieht das Ganze dann so aus:
var a = 1; var b = 5; var c = a+b; WriteLine(c);
Jetzt kann das Script getestet werden. Mit dem Button „Ausführen“ erhalten wir das Ergebnis unten angezeigt, nämlich „6“. Die Zahlen in den Variablen „a“ und „b“ können beliebig geändert werden.
Da wir aber damit nicht wirklich viel anfangen können, kommen wir jetzt zu den Kanälen.
Rechnen mit Kanälen
Möchten wir beispielsweise zwei Kanäle miteinander addieren, funktioniert das genauso. Wir geben den Variablenwert mit „1“ oder „5“ jedoch nicht vor, sondern wollen, dass der Wert vom Gerät genommen wird. Wir ersetzen also die „1“ durch die Adresse des Gerätes.
Das „Segement“ eines Gerätes besteht aus mehreren Teilen, die ich im folgenden erkläre.
dom.GetObject("
Der obige Teil ist immer FIX. Jetzt kommt das Interface (6 Spalte [„HmIP-RF“oder „BidCos-RF“]) und die Seriennummer des Gerätes. Diese ist unter „Einstellungen“ –> „Geräte“, in der 5 Spalte zu finden. Die beiden Teile werden durch einen „.“ getrennt.
Nehmen wir beispielsweise mal die Helligkeit des Bewegungsmelders in der Einfahrt.
dom.GetObject("BidCos-RF.NEQ1297666
Soweit so gut. Als nächstes müssen wir dem Script sagen, welchen Kanal er nehmen soll. Bei Schalt- und Messsteckdosen sind das 5 bzw. 6 Kanäle. Den Kanal geben wir mit einem Doppelpunkt hinter der Seriennummer an. In diesem Fall hat der Bewegungsmelder Kanal 0 und Kanal 1. Die Kanäle und die Bezeichnung dazu findet man entweder in ioBroker, oder über das Addon XML-API. (hier zum Download) Nach der Installation findet man unter „http://IPderCCU/addons/xmlapi/statelist.cgi“ alle Geräte und die dazugehörigen Kanäle. Wir suchen das Gerät „Bewegungsmelder Einfahrt“ und den Kanal „BRIGHTNESS“. Dieser hat die Kanalnummer „1“, die wir im Script ergänzen.
dom.GetObject("BidCos-RF.NEQ1297666:1.BRIGHTNESS
Nach dem Kanal muss dieser noch definiert werden, da es pro Kanal mehrere Kanalnamen gibt (Bei diesem Beispiel „BRIGHTNESS“ und „MOTION“). Wir nehmen mal „BRIGHTNESS“. Der Kanal ist ausgesucht und wir schließen die Geräteauswahl mit einem Anführungszeichen und einer geschlossenen Klammer.
dom.GetObject("BidCos-RF.NEQ1297666:1.BRIGHTNESS")
Das Einzige was jetzt noch fehlt, ist die Entscheidung, ob der Wert AKTIV eingeholt „State()“ oder zuletzt bekannte Wert „Value()“ genommen werden soll. Hierbei ist zu beachten, dass sich der Duty Cyle massiv erhöhen könnte, wenn mehrfach „State()“ verwendet wird. (Das war bei mir beim Stromscript der Fall.
Mir genügen die letzten bekannte Werte, die bei jeder Aktualisierung an die CCU gesendet werden und nehme daher „Value()“. Das Ganze wird ebenfalls durch einen „.“ getrennt, dann sieht das Ergebnis, inkl. dem abschließenden Strichpunkt so aus.
dom.GetObject("BidCos-RF.NEQ1297666:1.BRIGHTNESS").Value();
Und fertig ist unser Wert. Wir prüfen direkt mal ob hier ein Wert ausgegeben wird.
Ok, die aktuelle Helligkeit beträgt also 227. Super, dann wollen wir einen zweiten Kanal hinzufügen und diesen damit addieren. Das Verfahren ist das selbe, wie bei der Erstellung des ersten Kanals. Bei mir ist Variable „b“ ein anderer Helligkeitssensor. Das Ergebnis beider Werte ergibt also 312.
Einbindung in die CCU
Bisher können wir mit den errechneten Werten jedoch nichts in der CCU anfangen. Dieser Schritt kommt jetzt. Nun MUSS eine Systemvariable erstellt werden. Der Typ (Logik, Zahl, Werteliste etc.) richtet sich nach dem Ergebnis dieser Berechnung. Bei den normalen Grundrechenarten gehen wir mal davon aus, dass auch Zahlen als Ergebnis herauskommen. Daher legen wir eine Systemvariable vom Typ „Zahl“ an. Der Name ist egal, sollte nur keine Sonderzeichen enthalten, z.B. „Helligkeitsmessung“.
Mit der folgenden Teil des Scriptes wird in das Objekt (in diesem Fall die Systemvariable „Helligkeitsmessung“) ein Wert eingetragen; Und zwar der Wert aus der Varablen „c“.
dom.GetObject("Helligkeitsmessung").State(c);
Wenn alles richtig eingetragen wurde, wird mit dem Button „Ausführen“ immer noch der richtige Wert ausgegeben und die Systemvariable das erste Mal befüllt.
Das kann unter „Status und Bedienung“ –> „Systemvariable“ nachgesehen werden.
Ergebnis erreicht. Wir haben zwei Kanäle miteinander addiert.
EDIT 04.02.2018
Falls die Variable nicht befüllt wird, kann das an dem Namen der Variablen liegen. Bitte diese testweise in der CCU und im Script umbenennen und dann nochmal versuchen.
Das Ganze geht natürlich auch mit anderen Rechenoperationen. Diese sind in der Scriptanleitung von Homematic „Sprachbeschreibung“ auf Seite 7 beschrieben.
Viel Spaß beim Probieren!
Hallo,Auch nach ausführlichem Studien dieses Blog bekomme ich dieses Script nicht ans laufenÖ
varTempFloorStudio = dom.GetObject(„BidCos-RF.JEQ0195503:1“).State();
WriteLine(varTempFloorStudio);
Kein error, aber auch kein Temperaturwert
Habe es mit und ohne das :1 versucht, auch mit :2
Auch Value() verwendet.
Nichts scheint zu gehen
Hilfe !
Vielen Dank,
Dies ist ein sehr hilfreicher Blog
Hallo Ingo,
Ich habe zwei Verbesserungsvorschläge.
1. mit State schreibt man einen Wert in das Gerät. Ich nehme aber an, du möchtest einen Wert auslesen. Das geht mit Value.
2. in der Ausgabe (Write line) muss der Name der variablen rein. Ohne „var“
Versuchs mal so
var TempFloorStudio = dom.GetObject(“BidCos-RF.JEQ0195503:1”).Value();
WriteLine(TempFloorStudio);
Hallo Michael
Erst einmal vielen Dank fuer die schnelle Antwort
Leider noch nicht erfolgreich
Um Parameter zu reduzieren, habe ich die variable erst einmal gegen a ersetzt.
Der Sensor ist Typ HM-WDS30-T-O – Ein-Kanal Temperatursensor, CCU3.
Die Temp.-Werte werden im Webinterface der ccu3 korrect angezeigt
Meine Eingaben:
var a = dom.GetObject(„CBidCos-RF.JEQ0195503:1“).Value();
WriteLine(a);
Habe auch versucht:
var a = dom.GetObject(„CBidCos-RF.JEQ0195503:2“).Value();
var a = dom.GetObject(„CBidCos-RF.JEQ0195503“).Value();
Ebenfalls ohne Erfolg
Ich habe es auch mit einem anderen Sensor versucht (Typ HM-WDS40-TH-I):
var a = dom.GetObject(„CBidCos-RF.FEQ0008836:1“).State();
WriteLine(a);
Das gleiche Ergebnis: Der Temperaturwert wird nicht ausgelesen
Ich gehe davon aus, dass die Temperatur ausgelesen wird,
wenn im Script der Button ‚error check‘ gedrückt wird. Korrekt?
Habe ich da noch irgendetwas übersehen?
Vielen Dank
Ingo
Hallo Ingo,
So, jetzt nach Feierabend und nicht vom Handy…
Beim Scripten kommt es auf Genauigkeit an. Jedes einzelne Zeichen ist wichtig, da das Script sonst nicht funktionert. In dem Artikel habe ich beschrieben, wie man Werte auslesen kann. Da du den Artikel aufmerksam studiert hast, hast du sicher gesehen, dass der Datenpunkt nach dem Kanal, um ein Wort ergänzt ist, damit man weiß, was der Kanal macht. In diesem Beispiel: „dom.GetObject(„BidCos-RF.NEQ1297666:1.BRIGHTNESS“) ist es BRIGHTNESS. Das fehlt in deiner Zeile. Zudem hast du den Teil in den Klammern um ein paar Buchstaben erleichert. 🙂 Bei dir steht: („CBidCos-RF…..) im Beitrag allerdings („BidCos-RF….)
Geh bitte nochmal in das XML-API Addon und kopiere dir exakt nach meiner Anleitung oben den Datenpunkt VOLLSTÄNDIG raus und setze ihn in die Klammern. Dann funktioniert das Ganze auch. 👍
Hallo Michael
Jetzt laeuft es, vielen Dank fuer deinen Einsatz
Damit andere nicht ins gleiche Fettnäpfchen treten:
War ein typisches ‚Nobody is perfect item‘:
Ich habe das Script mit ‚error check‘ IM script selbst ‚getestet‘. NICHT mit dem Button ‚Testscript‘
(hmmm wohl doch etwas oberflächlich gelesen …)
Dabei waren meine anfänglichen Einstellungen richtig
var c = dom.GetObject(„BidCos-RF.FEQ0008836:1.TEMPERATURE“)
habe es nur nicht bemerkt
Die Zeile
dom.GetObject(„TempAirLivFP“).State(c);
WriteLine(TempAirLivFP);
habe ich jetzt noch ergaenzt.
Da der Temp.fuehler auf ‚Trigger when updated‘ steht,
wird die (script) variable c automatisch in die (ccu) variable TempAirLivFP übertragen.
Ingo
Hallo Michael,
ich habe die neu erworbenen Programmierkentnisse angewendet und ein Script geschrieben, dass die Heizung in Abhängigkeit der Temperatur einschaltet
var Rr = dom.GetObject(„TempAirLivWI“).State(); // ausgelesene Temperatur (Script der vergangenen Tage
var Cr = dom.GetObject(„TempAirLiv_set“).State(); // Wunschtemp, ausgelesene Systemvar.
var R = (Rr * 10); // musste die Werte mit 10 multiplizieren, da keine Kommas akzeptiert wurden
var C = (Cr * 10);
var Cp = (C + 1); // Schalthysterese +/- 0.2 Grad
var Cm = (C – 1);
var E1 = (Cp > R);
var E2 = (Cm > R);
var Ef = ( E1 || E2);
dom.GetObject(„TempAirLiv_status“).State(Ef); // schreibe Ergebnis in sysvar
WriteLine(Ef); // true = Heizung an // false = aus
Funktioniert super im Script tester
MEIN PROBLEM:
Es leasst sich nicht von der graphischen Oberfläche aus aktivieren (Programs & CCU connections)
Habe dazu den gleichen Trick wie gestern angewendet: Update on change einer der beiden sysvar’s
var Rr = dom.GetObject(„TempAirLivWI“).State();
var Cr = dom.GetObject(„TempAirLiv_set“).State();
Fällt dir eine Lösung ein?
Irgendetwas dass ich übersehen habe?
Vielen Dank!
Ingo
Hallo,
Frage: Kann man Messwerte, zb Temperatur eines Thermostaten, automatisiert zb alle paar Minuten auslesen und diese Werte in irgendeiner Form zb auf einen PC oder den Raspi übertragen , sofern man diese RaspberryMatik im Einsatz hat ?
Danke im Vorraus
PK
Ja man kann die Daten verarbeiten und/oder senden.
Servus, kann man statt einem Object eine Systemvariable nehmen? Ich will nicht rechnen sondern Auswerten
Hallo Michael!
Kann ich über ein Script die Heizung z.b. 10 minuten heizen lassen und dann aber für 15 minuten nicht mehr heizen
dieses sooft wiederholen bis die Solltemperatur erreicht wurde.
Hintergrund ist ich steuere einen Stromheizkörper und dieser hat einen relativ guten speicher.
Vielen Dank für eine Antwort von Dir.
Hallo Harald,
wenn ich dich richtig verstehe, reden wir von der Hysterese. Also die Zeit, die zwischen Ein- und Ausschalten liegt. Mit der Einstellung wird verhindert, dass das Relais jede Minute oder im schlimmsten Fall, alle 10 sec. ein/aus schaltet. Jetzt kommt es darauf an, was du an hardware hast. Hast du ein Thermostat, dann rate ich davon ab und wüsste aktuell auch nicht wie das gehen würde. (wahrscheinlich in den Expertenparametern).
Sollte ich dich richtig verstanden haben, nutzt du aber eine Stromheizung mit einem Zwischenstecker. Dann geht das und ist ein kein Problem umzusetzen.
1. Erstelle ein Variable und nenne Sie z.b. „Wartezeit 15min“ vom Typ Logik. (Freigabe / keine Freigabe)
2. Erstelle ein Programm: Wenn Schaltzustand der Heizung aus, dann verzögert um 15min die o.a. Variable auf Freigabe, sonst auf keine Freigabe.
3. Im eigentlich Programm gibst du die Solltemperatur ein und prüft zusätzlich (und – „nur prüfen“) ob die o.a. Variable auf Freigabe.
PS: Ich habe das ganze aber über Direktverknüpfungen gelöscht. Wandthermostat an Schaltaktor. Da wird alles selbstständig geregelt. Die Hysterese kann in °C eingestellt werden.
Aber da du leider sehr wenig geschrieben hast, sind das alles Mutmaßungen.
Hallo Michael,
ich möchte die Luftfeuchte meiner Hmipw-WTH auslesen, hier das script:
var WT5humidity = dom.GetObject(„“HmIP-RF.001CDA49910104:1.HUMIDITY““).Value();
WriteLine(WT5humidity)
Ergebnis: 0
auch wenn ich es mit Temperatur versuche
Danke und Gruß, Philipp
Du hast 2 „ in den Klammern statt 1.
PS: dein Kommentar wurde als Spam eingestuft, da die ip gefälscht zu sein scheint. Prüf das mal bitte.
10 mal angeschaut…und die “ nicht gesehen…
Danke mal 🙂
IP keine Ahnung…
Hallo,
ich verzweilfel gerade an der einfachsten Sache der Welt. Ich möchte von einem Homematic IP Präsenzmelder die aktuelle Helligkeit auslesen.
Weder das Auslesen per Seriennummer, noch per Gerätename (habe ich in der CCU geändert) funktioniert.
Anbei meine beiden Beispiele/Versuche:
var a = dom.GetObject(„HmIP-RF.OG_FL_O_PräM:1.ILLUMINATION“).VALUE();
WriteLine(a);
var a = dom.GetObject(„HmIP-RF.000C170999F4F1:1.ILLUMINATION“).VALUE();
WriteLine(a);
Folgende Fehlermeldung erhalte ich :
Error 1 at row 1 col 108 near ^();
WriteLine(a);
Parse following code failed:
var b = dom.GetObject(„HmIP-RF.000C170999F4F1:1.ILLUMINATION“).VALUE();
WriteLine(a);
Du musst State() nehmen!
Du kannst Werte mit State() oder Value() abfragen.
State() fragt das Gerät aktiv nach dem aktuellen Wert.
Value() fragt nach dem letzten bekannten gespeicherten Wert.
Hier funktioniert Value() nicht.
Hallo Michael,
danke für deinen Tipp. Leider funktioniert auch die State() Abfrage nicht.
Error 1 at row 1 col 26 near ^u201CHmIP-RF.000C170999F4F1:1.ILLUMINATION%u201D).State();
WriteLine(a);
Parse following code failed:
var a = dom.GetObject(%u201CHmIP-RF.000C170999F4F1:1.ILLUMINATION%u201D).State();
WriteLine(a);
Und zweitens versuche ich etwas Ordnung in meinem internen Funkverkehr zu bekommen und besonders den Duty Cycle runter zu bekommen. Es wäre daher erstmal vollkommen ausreichen, wenn ich den letzten Wert der Helligkeit nutzen könnte.
VG
Dominik
Ich habe ebenfalls den Präsenzmelder und habe deinen Code getestet. Bei mir hat er mit State() funktioniert.
Hallo Michael,
kurze Info an dich. Es lang an den „-Zeichen, die bei mir irgendwie falsch waren und deshalb funktionierte das auslesen der Helligkeitswerte nicht. Jetzt funktioniert das aber und ich kann den gesuchten Mittelwert aus drei Präsenzmelder berechnen und in eine Variable schreiben.
Deshalb bin ich gleich zum nächsten Projekt übergegangen und möchte den Temperaturwert eines HM-WDS30-OT2-SM zu einem bestimmten Zeitpunkt auslesen und in eine Variable schreiben.
Mit dem Befehl „WriteLine()“ zeigt mir das Script beim Ausführen auch immer den aktuellen Temperaturwert an, aber die zuvor festgelegte Systemvariable verbleibt auf seinem Minimalwert z.B. -30°C order was auch immer ich definiere.
Hier mein Script:
var TEMP = dom.GetObject(„BidCos-RF.OEQ0672414:2.TEMPERATURE“).State();
dom.GetObject(„Garten_Temp_Nacht“).State(TEMP);
WriteLine(TEMP);
Die Systemvariable „Garten_Temp_Nacht“ stimmt überein.
VG
Dominik
Hallo Dominik,
Die variable ist aber vom Typ „Zahl“ oder?
Nimm mal oben das erste „state“ raus und erste es mit“value()“
Hi Michael,
Ja die Systemvariable ist vom Type Zahl. Wenn ich das Script wie beschrieben ändere bekomme ich eine Fehlermeldung.
var TEMP = dom.GetObject(„BidCos-RF.OEQ0672414:2.TEMPERATURE“).Valve();
dom.GetObject(„Garten_Temp_Nacht“).State(TEMP);
WriteLine(TEMP);
Fehlermeldung:
Error 1 at row 1 col 105 near ^();
dom.GetObject(„Garten_Temp_Nacht“).State(TEMP);
WriteLine(TEMP);
Parse following code failed:
var TEMP = dom.GetObject(„BidCos-RF.OEQ0672414:2.TEMPERATURE“).Valve();
dom.GetObject(„Garten_Temp_Nacht“).State(TEMP);
WriteLine(TEMP);
Ich glaube die Temperatur läuft auf Kanal 1, nicht auf Kanal 2.
Hallo Michael,
zunächst vielen Dank für deine Unterstützung.
Sowohl Kanal 1 als auch Kanal 2 messen die Lufttemperatur. An der Auswahl des Kanals lag es nicht.
Das zeigte mir bereits die Ausgabe der richtigen Temperatur mit dem Befehl WriteLine.
Ich habe jetzt die Variable von „Garten_Temp_Nacht“ in „GartenTempNacht“ geändert und jetzt wird auch der richtige Temperaturwert in die Variable geschrieben.
Schönen Abend.
Dominik
Das kann aber nur daran liegen, dass entweder ein Schreibfehler vorlag, oder die Anführungsstriche nicht die richtigen waren (das ist etwas doof, je nach Tastatur oder Gerät, z.B. iPad, da sind die anders). An den Unterstrichen lag es sicher nicht.
Ich habe übrigens nie so einen Zusatz wie TEMPERATURE oder ILLUMINATION hinter dem Kanal stehen. Dann geht alles. Wenn das dabei ist, geht nichts. Nur eine Feststellung, keine Frage 😉
Warum muss man hier State nehmen?
Ich hatte auch schon bei einem Aktor den Fall, dass Value nicht funbktioniert hat aber warum?
Hallo Kevin,
wo genau meinst du? State ändert den Status und Value holt den Wert ab.
Hallo funktionier einfach nicht was mache ich falsch hier das Script.
var a = dom.GetObject(„HmIP-RF.0001D709903CC8:6.POWER“).Value();
var b = dom.GetObject(„HmIP-RF.0001D8A99112AE:6.POWER“).Value();
var c = dom.GetObject(„HmIP-RF.0001D3C99CB30A:6.POWER“).Value();
var d = dom.GetObject(„HmIP-RF.000895699E68C3:5.POWER“).Value();
var e = dom.GetObject(„HmIP-RF.000855699C3B46:7.POWER“).Value();
var f = dom.GetObject(„HmIP-RF.00085709A3ED2E:7.POWER“).Value();
var g = dom.GetObject(„HmIP-RF.000855699C3CFF:7.POWER“).Value();
var i = dom.GetObject(„HmIP-RF.000895699E6A75:5.POWER“).Value();
var z = a+b+c+d+e+f+g+i;
dom.GetObject(„Strom_summiert“).State(z);
Versuchs zuerst mal mit einem Gerät. Danach das nächste. Nicht zuviel auf einmal wollen. ????
Mit was muss man die Systemvariable verknüpfen bzw. wo wird das Hinterlegt komme bei diesen Schritt nicht weiter.?
Hallo Christian, kannst du deine Frage bitte eindeutiger formulieren?
Hallo danke für die Antwort habe die Schritte wie oben beschrieben durchgeführt hat alles funktioniert bis zum Schritt Einbindung in die CCU, hab die Systemvariable angelegt aber wie geht es dann weiter. Muss ich das Scrip was getestet wurde Irgendwo einfügen bzw. muss ich ein Programm für Erstellen.?
Hi, ja klar. Das Programm kannst du in einem Programm z. B. Alle 5 min ausführen lassen.