Homematic
Homematic Script für „Dummies“ Teil 1 – Rechnen mit Variablen und Aktoren

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!

32

32 thoughts on “Homematic Script für „Dummies“ Teil 1 – Rechnen mit Variablen und Aktoren

    • 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

    • 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

    • 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 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);

    • Mit was muss man die Systemvariable verknüpfen bzw. wo wird das Hinterlegt komme bei diesen Schritt nicht weiter.?

Schreibe einen Kommentar

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

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.