Programmierung bei Homematic: Unterschied zwischen den Versionen

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche
(Batterien abfragen)
Zeile 245: Zeile 245:
  
 
Version von Meine-Homematic:
 
Version von Meine-Homematic:
  string MailEmpfaenger = "ich@meine-maildomain";
+
  string MailEmpfaenger = "ich@meine-maildomain.de";
 
  string MailBetreff = "Fenster im Arbeitszimmer geöffnet";
 
  string MailBetreff = "Fenster im Arbeitszimmer geöffnet";
 
  string MailText;
 
  string MailText;
Zeile 270: Zeile 270:
  
 
Mit etwas Selbstdisziplin (alle Leerzeichne durch + ersetzen und am Ende eine Parameters ein echtes Leerzeichen setzen) kann man das Script entsprechend vereinfachen, hier mit Nutzung der CUX-Funktion:
 
Mit etwas Selbstdisziplin (alle Leerzeichne durch + ersetzen und am Ende eine Parameters ein echtes Leerzeichen setzen) kann man das Script entsprechend vereinfachen, hier mit Nutzung der CUX-Funktion:
  dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/mh/email.sh " # "Fenster+geöffnet " # "Fenster+im+Arbeitszimmer+geöffnet " # "ich@meine-maildomain");
+
  dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/mh/email.sh " # "Fenster+geöffnet " # "Fenster+im+Arbeitszimmer+geöffnet " # "ich@meine-maildomain.de");
  
 
=Batterien abfragen=
 
=Batterien abfragen=

Version vom 13. Januar 2019, 19:50 Uhr

Ein wichtige Möglichkeit der CCU ist die der individuellen Programmierung. Der konkrete Aufbau eines Programmes hängt auch von den zur Verfügung stehenden Erweiterungen ab.

  • CUXD
  • Mail-Addon
  • Meine Homematic

Grundlagen

Die Programmierumgebung von Homematic ist sehr stark Objektorientiert. Einen Einblick in die Struktur ergibt das folgende Klassendiagramm, welches der Abbildung in der Dokumentation nachempfunden ist:

HM-Objektmodell.png

Die unterstrichenen Methoden sind in der offiziellen Dokumentation nicht zu finden, wohl aber in manchen Beispielen und unter https://homematic.shoutwiki.com/wiki/Kategorie:Methoden.

Liste der Systemvariablen

Programme kann man in der Entwicklungsphase unter Startseite > Programme und Verknüpfungen > Programme > Script testen in ein Editor-Fenster eingeben und ausführen. Leider gibt das Tool bei Fehlern keine Rückmeldung, das Programm wird dann einfach nicht ausgeführt.

Das folgende Programm nach https://www.blogging-it.com/code-snippet-alle-systemvariablen-und-werte-auslesen-und-auflisten/programmierung/homematic-script.html liefert eine Liste aller Systemvariablen und ihrer Werte:

var objIDs = dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs();
string id; 

! Alle Datenpunkte durchlaufen
foreach(id, objIDs){
  ! Einzelnen Datenpunkt holen
  var sysVar = dom.GetObject(id);
  ! Namen und Wert des Elements ausgeben
  WriteLine("Name: " # sysVar.Name() # " Value: " +  sysVar.Value());
}

! Ausgabe als Rückmeldung beim Test, im Echtbetrieb entfernen
WriteLine("Fertig");

Das Objekt, welches in der ersten Zeile geholt wird ist vom Typ Aufzählung (OT_ENUM). Die Funktion EnumUsedIDs() Liefert die IDs der Objekte in dieser Aufzählung (siehe HM_Script_Teil_2_Objektmodell_V1.2.pdf Seite 26). Das als Ausgangspunkt benutzte Beispiel benutzt die Funktion EnumIDs(), die ich in der Dokumentation nicht gefunden habe. EnumIDs() liefert einige Element mehr, die dann wohl aber nicht genutzt werden?

Es gibt weitere nützliche Elemente zum Abfragen (siehe https://github.com/hobbyquaker/hq-webui/wiki/inoffizielle-Homematic-Script-Dokumentation):

  • ID_SYSTEM_VARIABLES
  • ID_PROGRAMS
  • ID_DEVICES
  • ID_CHANNELS
  • ID_ROOMS
  • ID_FUNCTIONS (liefert die Gewerke)
  • ID_DATAPOINTS
  • ID_STRUCTURE
  • ID_FAVORITES

Bei Rooms und Functions ist die Liste recht nützlich, da die Bezeichnungen sprachabhängig sein können: https://homematic-forum.de/forum/viewtopic.php?f=26&t=14579

Hinweis: Beim Programmtest schreibe ich gern noch die Zeile: WriteLine("Fertig"); ans Ende des Programmes. Ansonsten weiss man immer nicht, ob das Programm wegen eines Fehlers beendet wurde, oder einfach nur keine Daten gefunden hat. Wenn die Meldung "fertig" ausgegeben wird, dann ist das Programm erfolgreich bis zum Ende durchgelaufen. Das spieltaber nur für den Programmtest eine Rolle, bei den normalen Programmen bekommt man die Meldung ja nicht zu Gesicht.

Geräteliste holen

Das Listing für die Systemvariablen lässt sich natürlich für Geräte leicht angepasst anwenden:

var objIDs = dom.GetObject(ID_DEVICES).EnumUsedIDs();
string id; 

! Alle Datenpunkte durchlaufen
foreach(id, objIDs){
 ! Einzelnen Datenpunkt holen
 var object = dom.GetObject(id);
 ! Namen und Wert des Elements ausgeben
 WriteLine("Name: " # object.Name() # ": " #  object.ID());
}

! Ausgabe als Rückmeldung beim Test, im Echtbetrieb entfernen
WriteLine("Fertig");

Kanäle eines Gerätes holen

Das folgende Script holt alle Kanäle und deren IDs für ein beliebiges Gerät.

! Namen des Gerätes definieren, hier den eigenen eintragen
string GeraetName = "Heizung.Arbeitszimmer.01";

! Kanal holen
var Geraet = dom.GetObject(GeraetName);

string id; 

! Alle Datenpunkte durchlaufen
foreach(id, Geraet.Channels()) {
  ! Einzelnen Kanal holen
  var ch = dom.GetObject(id);
  ! Namen und Wert des Kanals ausgeben
  WriteLine(ch.Name() # ": " # ch.ID());
}

! Ausgabe als Rückmeldung bei Test, im Echtbetrieb entfernen
WriteLine("Fertig");

Auch hier wird mit einer Aufzählung gearbeitet, welche die Funktion Channels() liefert, die Liste der Kanäle in dem Gerät (HM_Script_Teil_2_Objektmodell_V1.2.pdf Seite 14).

Der Aufruf des Scriptes ergibt:

Heizung.Arbeitszimmer.01:0: 1302
Heizung.Arbeitszimmer.01:1: 1331
Heizung.Arbeitszimmer.01:2: 1332
Heizung.Arbeitszimmer.01:3: 1333
Heizung.Arbeitszimmer.01:4: 1334
Heizung.Arbeitszimmer.01:5: 1378
Heizung.Arbeitszimmer.01:6: 1379

Liste der Datenpunkte eines Kanals

Mit dem folgenden Script (angeregt von http://www.schneller-und-besser.de/faq/index.php?action=artikel&cat=58&id=126&artlang=de) kann ich mir die Datenpunkte eines Kanals und die zugehörigen Werte ausgeben lassen.

! Namen des Kanals definieren, hier den eigenen eintragen
string KanalName = "Heizung.Arbeitszimmer.01:0";

! Kanal holen
var AktorKanal = dom.GetObject(KanalName);

string id; 

! Alle Datenpunkte durchlaufen
foreach(id, AktorKanal.DPs()) {
   ! Einzelnen Datenpunkt holen
   var dp = dom.GetObject(id);
   ! Namen und Wert des DPs ausgeben
   WriteLine(dp.Name() # ": " # dp.Value());
}

! Ausgabe als Rückmeldung beim Test, im Echtbetrieb entfernen
WriteLine("Fertig");

Hier liefert DPs() eine Liste der Datenpunkte des Kanals (HM_Script_Teil_2_Objektmodell_V1.2.pdf Seite 17).

Die Bezeichnung des Kanals habe ich mit dem vorherigen Programm und dem Parameter ID_CHANNELS ermittelt. Zu dem Heizkörper-Thermostat gehören sieben Kanäle, von denen aber nur die mit den Nummern 0 und 4 Datenpunkte liefern:

"Heizung.Arbeitszimmer.01:0" liefert: (für den Kanal 0 finde ich in der Doku übrigens keine Beschreibung)

BidCos-RF.MEQ1885552:0.UNREACH: false
BidCos-RF.MEQ1885552:0.STICKY_UNREACH: false
BidCos-RF.MEQ1885552:0.CONFIG_PENDING: false
BidCos-RF.MEQ1885552:0.LOWBAT: false
BidCos-RF.MEQ1885552:0.RSSI_DEVICE: 1
BidCos-RF.MEQ1885552:0.RSSI_PEER: 194
BidCos-RF.MEQ1885552:0.INHIBIT: false
BidCos-RF.MEQ1885552:0.DEVICE_IN_BOOTLOADER: false
BidCos-RF.MEQ1885552:0.UPDATE_PENDING: false
BidCos-RF.MEQ1885552:0.AES_KEY: 0

"Heizung.Arbeitszimmer.01:4" liefert:

BidCos-RF.MEQ1885552:4.CONTROL_MODE: 0
BidCos-RF.MEQ1885552:4.FAULT_REPORTING: 0
BidCos-RF.MEQ1885552:4.BATTERY_STATE: 3.000000
BidCos-RF.MEQ1885552:4.VALVE_STATE: 12
BidCos-RF.MEQ1885552:4.BOOST_STATE: 0
BidCos-RF.MEQ1885552:4.ACTUAL_TEMPERATURE: 23.400000
BidCos-RF.MEQ1885552:4.SET_TEMPERATURE: 21.000000
BidCos-RF.MEQ1885552:4.AUTO_MODE: 
BidCos-RF.MEQ1885552:4.MANU_MODE: 
BidCos-RF.MEQ1885552:4.BOOST_MODE: 
BidCos-RF.MEQ1885552:4.COMFORT_MODE: 
BidCos-RF.MEQ1885552:4.LOWERING_MODE: 
BidCos-RF.MEQ1885552:4.PARTY_MODE_SUBMIT: 
BidCos-RF.MEQ1885552:4.PARTY_TEMPERATURE: 5.000000
BidCos-RF.MEQ1885552:4.PARTY_START_TIME: 0
BidCos-RF.MEQ1885552:4.PARTY_START_DAY: 1
BidCos-RF.MEQ1885552:4.PARTY_START_MONTH: 1
BidCos-RF.MEQ1885552:4.PARTY_START_YEAR: 0
BidCos-RF.MEQ1885552:4.PARTY_STOP_TIME: 0
BidCos-RF.MEQ1885552:4.PARTY_STOP_DAY: 1
BidCos-RF.MEQ1885552:4.PARTY_STOP_MONTH: 1
BidCos-RF.MEQ1885552:4.PARTY_STOP_YEAR: 0
Ventilstellung.Arbeitszimmer: 12.000000
Batterie.Arbeitszimmer: 3.000000

Die letzten beiden Datenpunkte scheinen von meinen Erweiterungen zu stammen?

Eine Übersicht über alle Datenpunkte aller Kanäle aller Geräte bekommt man übrigens über http://<<IP-Adresse>>/config/xmlapi/statelist.cgi .

Offene Fenster

Ich wollte eine Systemvariable (Offene Fenster) haben, die mir anzeigt ob und wenn ja welche Fenster offen stehen. Diese Systemvariable wird durch ein kleines Programm aktualisiert, welches über die Zeitsteuerung den Zustand der Fenster abfragt, genaugenommen den Zustand aller Mitglieder des Gewerkes Verschluss.

Homematic-28.png

Das Script hat dann folgenden Inhalt

! Script zum Ermitteln offener Fenster 
! von Uwe Debacher Version vom 30.04.2017
! 1. Ein Gewerk "Verschluss" anlegen
! 2. Alle zu überwachenden Sensoren dem Gewerk zuordnen
! 3. Das Skript per Zeitmodul regelmäßig (z.B. alle 30 min) ausführen

var gewerk = dom.GetObject("Verschluss");
string itemID;
string text = "";
integer counter = 0;
foreach(itemID, gewerk.EnumUsedIDs())  {
 ! Gerät zum Kanal holen
 var device = dom.GetObject(dom.GetObject(itemID).Device());
 
 ! Kanal 1 vom Gerät holen
 var ch = device.Channels().GetAt(1);

 ! Datenpunkt mit gesuchter Information vom Kanal
 var dp  = ch.DPByHssDP("STATE");

 ! Ist das Fenster offen
 if  (dp.State() && dp.Value())   {
   text = text # " " # ch.Name().StrValueByIndex(".", 1) # "\r";
   counter = counter +1;
 }
}
! Wenn kein Fenster offen ist
if (counter == 0) {
 text = "-";
}

! Systemvariable holen
var systemv = dom.GetObject("Offene Fenster");

! Wert setzen
systemv.State(text);

Zur Erklärung des Programmes. Die Zeile

var gewerk = dom.GetObject("Verschluss");

liefert eine Aufzählung (OT_ENUM) der Kanäle des Gewerkes Verschluss.

gewerk.EnumUsedIDs()

liefert eine Liste von IDs der Kanäle, über die iteriert wird. Da nicht klar ist, dass der geliefert Kanal auch der mit dem Datenpunkt STATE ist erfolgt mittels

 var device = dom.GetObject(dom.GetObject(itemID).Device());

die Abfrage des Gerätes (OT_DEVICE). Dazu wird erst der Kanal (OT_CHANNEL) über seine ID geholt und dann das Feld Device() ausgewertet, welches die ID des zugehörigen Gerätes enthält.

Mit

 var ch = device.Channels().GetAt(1);

wird dann der Kanal mit der Nummer 1 geholt (also der zweite).

Über

 var dp  = ch.DPByHssDP("STATE");

wird der Datenpunkt (OT_DP) des Kanals anhand seines Namens gesucht. Anschließend kann dann der Wert des Datenpunktes abgefragt und die Systemvariable entsprechend gesetzt werden.

E-Mail, durch den Fenstersensor

Das folgende Programm soll immer dann eine Mail auslösen, wenn ein Fenster geöffnet bzw. geschlossen wurde.

Dazu legt man unter Programme und Verknüpfungen -> Programme und Zentralen-Verknüpfungen oder unter Einstellungen -> Geräte -> <betroffener Sensor> -> Programme einen neuen Eintrag an.

Homematic-25.png

Klickt man hier auf Bearbeiten, so öffnet sich ein Fenster mit einer Reihe von Funktionen.

Homematic-26.png

Hier wird gesagt, dass wenn der Fenstersensor eine Änderung feststellt und das Fenster offen ist, dann ein Programm sofort ausgeführt werden soll. Sonst, wenn er eine Änderung feststellt und das Fenster geschlossen ist, dann wird ein zweites Programm ausgeführt. Die beiden Programme unterscheiden sich nur hinsichtlich der Texte, die übermittelt werden.

Für das Programm habe ich hier mehrere Versionen:

Version mit CUxD und E-Mail Addon. Der eigentlich Mailtext und die Konfiguration des Mailsystems steckt in der Konfiguration des Addons.

dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/email/email 10 "+"geöffnet");

Version von Meine-Homematic:

string MailEmpfaenger = "ich@meine-maildomain.de";
string MailBetreff = "Fenster im Arbeitszimmer geöffnet";
string MailText;
MailText = "Das Fenster im Arbeitszimmer\r\n";
MailText = MailText # "wurde geöffnet\r\n";
string stdout;
string stderr;
string teilstr;
string sendmail = "";
string sendbetreff = "";
string mailto = "";
foreach(teilstr, MailBetreff.Split(" ")) {
 sendbetreff = sendbetreff # "+" # teilstr;
}
foreach(teilstr, MailText.Split(" ")) {
 sendmail = sendmail # "+" # teilstr;
}
foreach(teilstr, MailEmpfaenger.Split(" ")) {
 mailto = mailto # "+" # teilstr;
}
system.Exec ("/bin/sh /etc/config/addons/mh/email.sh "# sendbetreff # " " # sendmail # " " # mailto, &stdout, &stderr);

Das Script wirkt relativ aufwändig. In einem großen Teil des Scriptes geht es aber nur darum Leerzeichen durch "+" zu ersetzen, da für das email.sh das Leerzeichen die Parameter abtrennt. Das "#" Zeichen wird in dem Script wohl zur Stringverknüpfung benutzt, da das "+" Zeichen mit die Lesbarkeit erschweren würde.

Mit etwas Selbstdisziplin (alle Leerzeichne durch + ersetzen und am Ende eine Parameters ein echtes Leerzeichen setzen) kann man das Script entsprechend vereinfachen, hier mit Nutzung der CUX-Funktion:

dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/mh/email.sh " # "Fenster+geöffnet " # "Fenster+im+Arbeitszimmer+geöffnet " # "ich@meine-maildomain.de");

Batterien abfragen

Unter https://www.meine-homematic.de/index.php/hm-support/anleitungen/mail-beispiel-pruefung-batterie-ladezustand findet sich ein kleines Programm, mit dessen Hilfe man den Ladezustand der Batterien der Sensoren abfragen kann. Dieses Script ähnelt dem aus dem Buch "Hausautomation mit HomeMatic" auf Seite 75.

Homematic-27.png

Der Test wird dann einmal täglich über die Zeitsteuerung (cron-Job) ausgelöst.

Das Script von der Meine-Homematic-Seite lief problemlos, zumindest mit System.Exec. Ich wollte aber auch hier die CUx-Funktion nutzen und das Mailscript von Meine-Homematic, doch damit hatte ich leider anfangs keinen Erfolg.

Mit ist dann im Protokoll des CUx Daemon aufgefallen:

Apr 17 16:41:48 homematic-ccu2 daemon.info cuxd[4552]: system(/etc/config/addons/mh/email.sh +Batterie+-+Warnung +Prüfung+des+Ladestandes+der+Batterien+vom+17.04.2017.^M Der+Ladezustand+folgender+Batterien+ist+niedrig:+^M ^M -+Fenster.Arbeitszimmer.01:1^M -+Fenste

Irgendetwas erzeugt hier wieder Leerzeichen und zwar das "\n" (newline) hat sich als Ursache gezeigt. Nachdem ich alle \n entfernt hatte lief das Script auch mit dem CUxD.

Das ist eigentlich ganz interessant, das CMD_EXEC des CUxD scheint sich gegenüber \n ganz anders zu verhalten als die Shell, die mit System.Exec gerufen wird:

system.Exec ("/bin/sh /etc/config/addons/mh/email.sh "# sendbetreff # " " # sendmail # " " # mailto, &stdout, &stderr);

Die korrektere Form der CUXd-Zeile ist wohl:

dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/mh/email.sh '" # sendbetreff # "' '" # sendmail # "' '" # mailto #"'");

Hier sind die Parameter jeweils in einfache Anführungsstriche gesetzt, dann klappt auch "\r\n" wieder. Außerdem stören auch die Leerzeichen im Betreff und im Mailtext nicht mehr, ich muss sie also auch nicht ersetzen.

Damit ergibt sich bei mir das folgenden, viel einfachere Script:

! Script für Warnung bei niedrigen Batterie - Ladestand
! von Uwe Debacher, Version vom 3.05.2017
! 1. Ein Gewerk "Batteriebetrieb" anlegen
! 2. Alle zu überwachenden Objekte dem Gewerk zuordnen
! 3. Das Skript per Zeitmodul 1x täglich ausführen

var gewerk = dom.GetObject("Batteriebetrieb");
string itemID;
string text = "";
integer counter = 0;

foreach(itemID, gewerk.EnumUsedIDs())  {
 var device = dom.GetObject(dom.GetObject(itemID).Device());

 var ch = device.Channels().GetAt(0);

 var dp = ch.DPByHssDP("LOWBAT");
 if (!dp) {
   var dp = ch.DPByHssDP("LOW_BAT");
 }
 if ( dp.State() && dp.Value() ) {
   text = text # "- " # ch.Name().StrValueByIndex(":", 0) # "\r\n";
   counter = counter + 1;
 }
}

string mailto = "ich@meine-maildomain.de";
string sDate = system.Date("%d.%m.%Y %H:%M:%S");
string sendmail = "Prüfung des Ladestandes der Batterien vom " # sDate # ".\r\n";

! Systemvariable holen
var sv = dom.GetObject("Batteriezustand");

if ( counter > 0 ) {
 sendmail = sendmail # "Der Ladezustand folgender Batterien ist niedrig: \r\n\r\n" # text;
 sendmail = sendmail # "\r\nBitte tauschen Sie die Batterien zeitnah aus.";
 string sendbetreff = "Batterie - Warnung";
 ! Systemvariable  Wert setzen
 sv.State(false);
}
else {
 sendmail = sendmail # "Der Ladezustand aller Batterien ist in Ordnung.\r\n\r\n";
 string sendbetreff = "Batterie - OK";
 ! Systemvariable  Wert setzen
 sv.State(true);
}

dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("/etc/config/addons/mh/email.sh '" # sendbetreff # "' '" # sendmail # "' '" # mailto #"'");

Momentan lasse ich mir auch zusätzlich eine Mail erzeugen, die mir mitteilt, dass alle Batterien in Ordnung sind.

Zusätzlich habe ich mir inzwischen eine Systemvariable "Batteriezustand" (Type Logischer Wert) erstellt, deren Wert entsprechend im Programm gesetzt wird.

Im Kopfteil des Programmes hole ich mir den Zugriff auf die Variable:

! Systemvariable holen
var systemv = dom.GetObject("Batteriezustand");

In den Programm-Zweigen werden dann die Wert entsprechend gesetzt

! Systemvariable  Wert setzen
systemv.State(false);

bzw.

! Systemvariable  Wert setzen
systemv.State(true);


Erklärung

Der Teil des Scripts, der die Batteriezustände abfragt hat mir bei anderen Lösungen nicht gefallen. Ich habe für mich folgende Lösung erarbeitet:

var gewerk = dom.GetObject("Batteriebetrieb");
string itemID;
string text = "";
integer counter = 0;

foreach(itemID, gewerk.EnumUsedIDs())  {
  var device = dom.GetObject(dom.GetObject(itemID).Device());

  var ch = device.Channels().GetAt(0);
 
  var dp = ch.DPByHssDP("LOWBAT");
  if (!dp) {
    var dp = ch.DPByHssDP("LOW_BAT");
  }
  if ( dp.State() && dp.Value() ) {
    text = text # "- " # ch.Name().StrValueByIndex(":", 0) # "\r\n";
    counter = counter + 1;
  }
}

Die erste Zeile liefert eine Liste von Kanälen für die "Batteriebetrieb" aktiviert ist (also nur für jeweils einen Kanal aktivieren, sonst kommen die Geräte mehrfach). Leider ist das nicht unbedingt der richtige Kanal für die Batterieinfomationen. Daher holen wir uns das Gerät (device) und zu dem Gerät den ersten Kanal (ch). Auf diesem Gerät suchen wir dann den Datenpunkt mit der Bezeichnung "LOWBAT". Bei meinem HomaticIP Rauchmelder heißt der Datenpunkt "LOW_BAT", daher die zusätzliche Abfrage.

Statusanzeige HM-OU-LED16 ansteuern

Ziel des Programmes ist es, für jeden Fenstersensor die zugehörige Leuchtdiode auf Rot zu stellen, wenn das Fenster offen ist. Bei geschlossenem Fenster soll die Leuchtdiode ausgeschaltet sein. Da im Schlafzimmer zwei Fenster vorhanden sind und damit auch zwei Sensoren, soll die entsprechende Leuchtdiode auf Orange stehen, wenn nur ein Fenster offen ist und wenn beide Fenster offen sind auf Rot.


string raeume="Dachboden,Schlafzimmer,Badezimmer,Kind1,Kind2,Wohnzimmer,Esszimmer,frei,Gästeklo,Arbeitszimmer";
string raum;
string anzeige;
integer i = 0;
integer status = 0;

foreach(raum, raeume.Split(",")) {
 raum = "Fenster."+raum+".01:1";
 i=i+1;
 anzeige="Statusanzeige:"+i.ToString();

 if (dom.GetObject(raum).DPByHssDP("STATE").Value()==0) {
   status = 0;
 }
 else {
   status = 1;
 }
 if (raum=="Fenster.frei.01:1") {
  status=0;
 }  
 if (raum=="Fenster.Schlafzimmer.01:1") {
   if (dom.GetObject("Fenster.Schlafzimmer.02:1").DPByHssDP("STATE").Value()!=dom.GetObject("Fenster.Schlafzimmer.01:1").DPByHssDP("STATE").Value()) {
     status = 3;
   }
 }
 if (dom.GetObject(anzeige).DPByHssDP("LED_STATUS").State() != status)   {
   dom.GetObject(anzeige).DPByHssDP("LED_STATUS").State(status);
 }
}


Starten muss man dieses Script über eine Reihe von verknüpften Bedingungen:

Homematic-display-1.png

Hier sind für jeden Sensor zwei Bedingungen aufgeführt, einmal dafür dass das Fenster geöffnet wird und einmal dafür, dass es geschlossen wird.