Quicktipp – Homematic Programm im Programm aufrufen
In diesem Quicktipp möchte ich euch eine Möglichkeit zeigen, wie ihr ein Programm aus einem Programm heraus aufrüfen bzw. starten könnt. Es existiert in einer HomeMatic Installation nicht die Möglichkeit über die WebUI Unterprogramme oder sogenannte Subroutinen auszuführen. Über ein kleines Skript können wir diese fehlende Möglichkeit jedoch in jedem Programm einbauen. Somit haben wir die Chance, Teilaufgaben sinnvoll aufzuteilen in einzelne kleine Programme. Dies macht die ganze Sache übersichtlicher und es müssen nicht die gleichen Aktionen in mehreren Programmen eingebaut werden. Ich denke die ein oder andere Idee für eine solche Variante fällt jedem Anwender sofort ein. Da es sich um einen kleinen Zweizeiler handelt, sind auch keine grundlegenden Skriptkenntnisse erforderlich.
Programmaufruf in WebUI Programm einbauen
Wie bereits oben erwähnt, müsst ihr lediglich ein kleines Skript im entsprechenden Programm ausführen und in diesem Skript den Programmnamen des aufzurufenden Programmes eintragen.
Aufgrund des wirklich guten Hinweises von Jérôme Pech ( Jérôme , Danke für den Kommentar), habe ich das Skript ein wenig erweitert. Damit sichergestellt wird, das auch wirklich das Programm mit dem gewünschten Namen und nicht das erste gefundene Objekt mit dem gleichen Namen (was nicht zwangsläufig ein Programm sein muss) aufgerufen wird, habe ich „ID_PROGRAMS“ eingebaut. Zusätzlich frage ich über „if (prgObj.Active()“ ab, ob das aufgerufene Unterprogramm auch auf „aktiv“ steht und nicht mit Absicht „inaktiv“ ist. Ist das Unterprogramm auf „inaktiv“ definiert (Haken bei aktiv raus), wird es nicht aufgerufen. Auf die Abfrage ob da Unterprogramm existiert, habe ich bewusst verzichtet. Ein Test hat gezeigt, dass das Skript ausgeführt wird, aber nichts zum Aufrufen findet, wenn das Unterprogramm nicht existiert. Somit ist aus einen Quicktipp eine richtig runde Sache geworden. Die Writeline commands sind eigentlich nur für den Test drin. Könnt ihr rausnehmen, stören aber auch nicht!
var prgObj = dom.GetObject(ID_PROGRAMS).Get("Test Unterprogramm");
if ( prgObj.Active() ) {
WriteLine("Unterprogramm aktiv");
prgObj.ProgramExecute();
} else {
WriteLine("Unterprogramm inaktiv");
}
Beispiel
In dem folgenden Screenshot seht ihr ein Testprogramm in dem wir über diese Möglichkeit ein weiteres Programm starten:
Das folgende Unterprogramm wurde ausgeführt:
Viel Spass beim Ausprobieren.
Hallo,
dazu sollte aber noch gesagt werden, das bei diesem Aufruf KEINE Bedingungsprüfung stattfindet. Es wird immer das DANN ausgeführt.
Und es kann die Stabilität der CCU beeinträchtigen, je nachdem wie exzessiv man das nutzt und ob es ggf. zu rekursiven Aufrufen kommt.
Unterm Strich ist es sehr schlechter Programmierstil, da man das triggergesteuerte Betriebssystem der Zentrale somit „austrickst“.
Besser wäre es im aufzurufenden Programm auf eine Systemvariable zu triggern und diese im aufrufenden Programm entsprechend zu setzen. Das geht dann auch ganz ohne Skript. Und mit einer Werteliste kann man auf diese Art und Weise sehr fein gesteuert Aktionen auslösen. Und das auch noch zeitverzögert. Also ProgrammExecute ist vollkommen überflüssig.
Hallo Michael,
Du sprichst mir aus der Seele und hast mich vor einem verhängnisvollen Fehler bewahrt. Die Homematic-Programmierung ist schon unübersichtlich genug. Da mit sprechenden Systemvariablen zu arbeiten, die in Programmen einfach gesetzt und im eigentlichen Programmskript zurückgesetzt werden, ist das Gebot der Stunde.
Ich habe gestern Nacht mal die Skripte „CheckLampen“, „CheckZugaenge“, „AlleLampenAusschalten“, „SendTelegramMessage“ und „HausVerlassen“ geschrieben. Alle getriggert bei diversen Aktionen (Taster, Türschloss oder Umweltsensoren). Den Telegram-Text speichere ich natürlich ebenfalls dynamisch in einer Systemvariablen.
Hi,
ist es möglich, Variablen beim Aufruf zu übergeben? So könnte man das gleiche Unterprogramm aufrufen um Rolladen hoch/runter/halbhoch usw. zu fahren.
Gruß
Daniel
Hi Daniel,
bevor du den Aufruf des zweiten Programms startest kannst du ja Systemvariablen beschrieben, die die Ausführung des Programms beeinflussen, wie z.B. die Höhe. Tipp: falls du mehrere Rollläden hast und verschiedene Höhen definieren willst, kannst du statt mit dedizierter Variable/Rollladen auch eine Zeichenkette nehmen und die Höhen mit „;“ trennen (30;50;80;50;..). Einfach mit foreach(rolllade, rollladenHoehen.Split(„;“)) in einer Schleife abarbeiten.
Gruß
Stefan
Ist es möglich, ein so aufgerufenes Programm mehrfach gleichzeitig abzuarbeiten? Z.B. wenn man die Rollläden auf verschiedenen Stockwerken fahren möchte, kann es ja sein dass man das kurz hintereinander startet und dafür eine Routine schreibt, die mehrfach verwendet wird. Aus deiner Beschreibung fürchte ich fast, dass das nicht geht.
Es sollte grundsätzlich berücksichtigt werden, dass Bezeichnungen in der CCU mehrfach vorkommen können.
So kann bspw. eine Systemvariable genau so heißen wie ein Gerät, ein Kanal wie ein Raum usw.
dom.GetObject(„NAME_DES_PROGRAMMS“); liefert dabei das erste gefundene Objekt mit dem Namen zurück.
Das kann u.U. nicht das Programm sein.
Es ist daher best practice, den Objekttyp bei der Abfrage anzugeben und auch vor dem Execute zu prüfen, ob tatsächlich das Programm vorhanden ist:
object pgmObj = dom.GetObject(ID_PROGRAMS).Get(„NAME_DES_PROGRAMMS“);
if (pgmObj) {
pgmObj.ProgramExecute();
}
Man könnte zusätzlich noch prüfen, ob das auszuführende Programm überhaupt aktiviert ist, um „Zwangsausführungen“ trotz bewusstem Deaktivieren (Fehlersuche, Debugging) zu verhindern.
Hallo Jérôme,
vielen Dank für deinen wirklich sinnvollen Hinweis. Ich habe das Skript erweitert, getestet und den Artikel aktualisiert.
Gruss
Werner