Einfaches generisches Skript

Hallo,

was wäre der saubere weg für ein generisches Skript zum einfachen schalten von Relaisausgängen?
Situation ist folgende: In meinem LCN System gibt es einige Relais (Lampen, ein Brunnen im Garten) dessen Statusvariable ich bisher im WF darstelle und dort per Standardaktion Ein- und Ausschalte. Nun würde ich aber dafür gerne eine Art „Vergessensschaltung“ einrichten, die bei dem eingeschalteten Brunnen z.B. nach 2h automatisch ausschaltet. Timer per Skript starten und auf Events reagieren ist soweit kein Problem, mache ich für andere Funktionen bisher auch.
Im Rahmen dieser eigentlich „einfachen“ Schaltaufgabe würde ich aber gerne etwas mehr auf generische Programmierung umschalten, sodass ich dieses eine Skript evtl. für weitere Aktionen nur einbinden muss. Bisher kopiere ich die Skripte lediglich immer BMW Flur EG ist z.B. einfach für das OG kopiert und darin die IDs ersetzt. Das sollte ja sicherlich auch generischer gehen.

Mein 1. Ansatz war eigentlich folgender:

  • Unter der jetzt vorhandenen Statusvariable, lege ich zunächst ein Aktionsskript an
  • Darin schaue ich auf den Wert der Statusvariable (den ich im WF ja ändern kann) und Werte aus. Einschalten vom Relais und starten vom Timer…
  • Nach x Sekunden wird das Skript wieder aufgerufen, Timer deaktiviert, Relais auf „AUS“ gesetzt
  • ABER die Statusvariable bleibt auf dem im WF gesetzten Wert, vmtl. weil diese ja read-only ist?:confused:

Wenn Du das Relais mit der zugehörigen IPS-Funktion (LCN_SwitchRelay oder ähnlich) ausschaltest, dann geht die Statusvariable im WebFront auch auf Aus.

Die Steuerung von Geräten funktioniert nicht mit SetValue.
Dazu benutzt du am besten RequestAction, das ist unabhängig von den Instanzen.
Michael

Moin,
das LCN Kommando musst du an die Instanz-ID (also den ‚Parent‘) schicken, angezeigt im WebFront wird die Status-Variable.
Ob das Schaltkommando wirklich kommt sieht man dann aber auch wunderbar im Busmonitor der Pro.
Und: du darfst der Statusvariablen kein anderes Aktionsskript ‚verpassen‘, dann geht die ‚Standardaktion‘ nicht mehr. Mit einem Ereignis auf dem Skript geht das aber - auf Änderung prüfen, nicht auf Aktualisierung, da LCN ja immer mal wieder den Status in den Bus ‚plappert‘.

Grüße, Uwe

Wenn ich dieses Skript nun als Aktionsskript für die Statusvariable festlege funktionieren ja die Systemvariablen und liefern die IDs.
Wenn ich das aber mit einem Ereignis aufrufe, was durch die Variablenänderung derselben Statusvariable ausgelöst wird aber (natürlich) nicht mehr.
Wie kann ich den dem Skript mitteilen, dass der Parent vom aufrufenden Ereignis gesetzt werden soll? Ich weiß ich könnte die ID hier fest eintragen, aber mein Ziel wäre es eben das Skript nachher kopieren zu können und es 1zu1 für andere Variablen zu nutzen oder meinetwegen nur noch das auslösende Ereignis ändern zu müssen.

<?
//aufrufende Variable
$variable =  $_IPS['VARIABLE'];
//Übergeordnete Instanz der Statusvariable
$variablepar = IPS_GetParent($variable);
//Wert aus dem WF 
$value = $_IPS['VALUE'];
//Zeit Auto-Aus in sec
$i_time_sec = 5;

if ($value == false or $_IPS['SENDER'] == "TimerEvent" ) {
	SetValue($variable, false);
	LCN_SwitchRelay($variablepar, false);
	IPS_setscripttimer($_IPS['SELF'], 0);
	echo PHP_EOL;
	echo $variablepar;	
}
else  {
	SetValue($variable, true);
	LCN_SwitchRelay($variablepar, true);
	IPS_setscripttimer($_IPS['SELF'], $i_time_sec);
}


?>

Mit dem Parent von $_IPS[‚EVENT‘],

Vielleicht blöde ausgedrückt von mir…

IPS_GetParent($_IPS['EVENT']);

gibt mir von dem Ereignis die ID. Ich brauche aber die ID von der Statusvariablen die das Event auslöst. Um damit dann über GetParent die LCN Instanz auszulesen

Erstelle bitte mal einen Screenshot aus dem Objektbaum.

$_IPS[‚VARIABLE‘] sollte klappen.

Das Ereignis schaut hier auf die STATUS-VARIABLE der Instanz

Wenn es generisch sein soll, kein LCN Kommando benutzen, sondern immer RequestAction auf die Variable.

Selbstverständlich darf man ein eigenes Aktionsskript eintragen.
Vorsicht: Dies ist dann die neue Aktion, somit wird bei RequestAction auf dieses Aktionsskript ausgeführt!
Wenn man somit eine Statusvariable mit einer eigene Aktion versieht, dann muss dieses Aktionsskript tatsächlich wieder die original Instanz-Funktion (LCN_xxx) und nicht RequestAction (=Endlosschleife) benutzen.
Außerdem ist das übliche SetValue in so einem Aktionsskript wegzulassen, da die Variable immer durch die Hardware-Instanz gesetzt wird.
Michael

Das sollte die ID von Skript enthalten.
$_IPS[‚EVENT‘] ist die ID vom Ereignis.
Dazu noch ein GetParent darum und du hast die Instanz.
Auch wenn dir das bei einem Dummy-Modul nicht viel hilft.
Michael

Alternativ kannst du zum zeitlich verzögerten Ausschalten auch super das Treppenhauslicht Modul aus dem Modulstore verwenden.

Viele Grüße Stephan

ABer um jetzt nochmal Struktur reinzubringen… Es sind doch zwei Paar Schuhe, entweder ich führe das Skript direkt unter der Statusvariablen als Aktionsskript ODER ich lasse das Skript irgendwo liegen und Starte es nur bei einer Änderung dieser Statusvariablen…
Der zweite Fall hört sich eigentlich sinnvoller an, weil ich es dann ja an einer Stelle im Strukturbaum liegen lassen kann und eben von 1 2 oder 15 Stellen aus aufrufen kann, eben mit mehreren Events die es auslösen. ABER ich muss dann ja feststellen, von welcher Statusvariable die Änderung kommt und entsprechend den Parent dieser Statusvariable setzen.

Du hast aber nur einen Scripttimer. Wie soll das also funktionieren wenn das eine Script 15 potentielle Quellen von Ereignissen und 15 potentielle Variablen als Ziel für die Ansteuerung hat?

Dann musst du etwas komplexes bauen, welche sich die Auslöser und die Zeiten merken, neue Zielzeit berechnen und Timer setzen…usw…
Michael

Ja das habe ich jetzt seit dem letzten Post auch gerade herausgefunden^^.

Hiermit bekomme ich schonmal von egal woher den parent der Statusvariable:


if ($_IPS['SENDER'] == 'Variable') {
	$value = $_IPS['VALUE'];
	$variablepar = (IPS_GetParent($_IPS['VARIABLE']));
}
elseif ($_IPS['SENDER'] == "TimerEvent") {
	$value = false;
}

Aber es ist eben nicht möglich ohne weiteres festzustellen, wohin das TimerEvent gehört. Nunja ok dann muss eben eine andere Lösung her :slight_smile:

Ist die Frage ob ein, relativ einfaches, generisches Script, welches man zigmal als Kopien im Baum hat, nicht einfacher ist als ein einzelnes spezialisierte Script welches an zentraler Stelle liegt.

Das Problem mit dem Scripttimer kannst du lösen, indem das Script für jede Quellvariable einen eigenes zyklischen Ereignis erzeugt, dies entsprechend mit der Zielzeit versieht und z.b. in das Info Feld oder den Namen die ID der Quellvariable hinterlegt.

Dann kannst du die ID, wenn das Ereignis auslöst, dort wieder extrahieren.
Michael

Ok danke. Hab ich jetzt aber erstmal gelassen, denn soooviele Stellen sind es dann auch nicht im Objektbaum.
Das ist erstmal das fertige.

// ID des Relais, welchesgeschaltet werdenn soll
$var = IPS_GetParent(IPS_GetParent($_IPS['SELF']));
// Zeit für Auto-Aus in min
$i_time_sec = 180;
// DEBUG
//echo $var.PHP_EOL;

// Ausführen, je nachdem ob Ablauftimer zugeschlagen hat oder manuelle Handlung	
if ($_IPS['SENDER'] == "TimerEvent"){
	LCN_SwitchRelay($var, false);
	IPS_setscripttimer($_IPS['SELF'], 0);
}
elseif ($_IPS['VALUE'] == false) {
	LCN_SwitchRelay($var, false);
	IPS_setscripttimer($_IPS['SELF'], 0);}
else  {
	LCN_SwitchRelay($var, true);
	IPS_setscripttimer($_IPS['SELF'], $i_time_sec*60);
}