Event Deaktivierung funktioniert nicht wie erwartet

Hallo,

ich habe ein Problem mit der dynamischen Aktivierung/Deaktivierung von Events über den Befehl IPS_SetEventActive.
Deaktiviere ich ein Änderungs-Event für eine Variable, ändere die Variable und aktiviere das Event danach wieder, so wird das zugehörige Event nicht immer unterdrückt.

Hintergrund:
Ich nutze einen CUL-Adapter für das Senden und Empfangen von FS20 Befehlen und habe jeweils zwei Variablen für einen FS20 Aktor definiert „UI_Status“ und „UI_Intensity“. Die beiden Variablen sollen nun automatisch in Abhängigkeit geändert werden, d.h. wenn UI_Status auf True gesetzt wird, wird automatisch UI_Intensity auf 16 bzw. 100% gesetzt usw… Für beide Variablen existiert ein Änderungsevent auf das gleiche Sende-Skript.
Wird nun also z.B. UI_Status geändert wird das Sende-Skript aufgerufen und UI_Instensity in Abhängigkeit geändert. Diese Änderung soll natürlich nicht noch eine Event-Verarbeitung auslösen.

Problem:
Zu ca. 50% funktioniert die Funktion wie erwartet und korrekt. In den anderen 50% der Fälle wird trotz der Deaktivierung des Änderungsevents das Sende-Skript nochmals durch die Änderung der abhängigen Variable angestoßen (habe via Logs nachvollzogen, dass das Event tatsächlich deaktiviert wurde während der Änderung).
Wie kann dies passieren?
Ich dachte in IPS werden die Skripte und Events sequentiell und synchron abgearbeitet, somit müßte die Deaktvierung sofort aktiv werden und es dürfte nicht noch ein Event in die Verarbeitungsqueue eingehängt werden!? Oder sehe ich das falsch und die Verarbeitung in IPS läuft doch anders?
Was mache ich hier falsch bzw. wie kann ich das gewünschte Verhalten erziehlen?

Code Send-Skript:


switch ($name)
	{
		case "UI_Status":

		   $intensityID=IPS_GetObjectIDByName("UI_Intensity", $fs20);

			SetEventIsActive($_IPS['SELF'], $intensityID, false); // Event für Änderung deaktivieren, damit diese nicht wieder das Script aufruft!

		   if($IPS_VALUE)
			{
			   $val = "11";
			   SetValueInteger($intensityID, 16); // 16 = 100% for FS20
			}
			else
			{
			   $val = "00";
			   SetValueInteger($intensityID, 0);
			}
			
			SetEventIsActive($_IPS['SELF'], $intensityID, true); // Event für Änderung wieder aktivieren, damit Änderungen durch User wieder erkannt werden

			break;
		case "UI_Intensity":

			$val=dimmer($IPS_VALUE);

			$statusID = IPS_GetObjectIDByName("UI_Status", $fs20);

			SetEventIsActive($_IPS['SELF'], $statusID, false); // Event für Änderung deaktivieren, damit diese nicht wieder das Script aufruft!

		   if($IPS_VALUE > 0)
			{
			   SetValueBoolean($statusID, true);
			}
			else
			{
			   SetValueBoolean($statusID, false);
			}

			SetEventIsActive($_IPS['SELF'], $statusID, true); // Event für Änderung wieder aktivieren, damit Änderungen durch User wieder erkannt werden

			break;
		default:

			print "Unknown Name $name";

			return;

	}

Code Funktion SetEventIsActive:


/**
* Activates/deactivates a event
* @param integer eventTargetID The parent object of the events to set active/deactive
* @param integer eventTriggerID The id of the trigger variable of the event
* @param boolean active Set true if event should be active; otherwise false
*/
function SetEventIsActive($eventTargetID, $eventTriggerID, $active)
{

	$eventIDs = @IPS_GetChildrenIDs($eventTargetID);

	if($eventIDs)
	{

		foreach($eventIDs as $eventID)
		{

		   $eventObj = @IPS_GetEvent($eventID);

		   if($eventObj)
		   {

		      if($eventObj['TriggerVariableID'] == $eventTriggerID)
		      {
		      
					IPS_SetEventActive($eventObj['EventID'], $active);
		      	IPS_LogMessage("CommonHelper.SetEventIsActive", "Event Active changed: EventID: ".$eventObj['EventID']." TriggerID: ".$eventObj['TriggerVariableID']." IsActive: ".$active);

		      }

		   }

		}

	}

}

Wofür brauchst du die Events den überhaupt?
Normalerweise definiert man bei beiden Variablen ein Aktions-Skirpt.
Dort wird dann der Befehl zur Hardware (CUL) gesendet und bei Erfolg werden die Variablen nachgeführt.
Events auf die Variablen braucht es dann gar nicht.
Michael

Hallo Michael,

danke für die schnelle Antwort!

Beim CUL geht leider vieles nicht automatisch und man muss alles über Skripte selbst umsetzten.

Ich habe mich hier an das Beispiel von tdressler http://www.tdressler.net/ipsymcon/cun_ips.html gehalten und diese erweitert.

Das Senden über das Aktion-Skript zu starten, ist eine gute Idee und könnte das Problem lösen.

Ich würde aber trotzdem gerne wissen, warum die Event-Deaktivierung nicht wie erwartet funktioniert.
Ich möchte gerne verstehen, wie IPS hier funktioniert, sonst könnte ich immer wieder in solche Probleme laufen. :rolleyes:

Gruß
André

Deaktiviere ich ein Änderungs-Event für eine Variable, ändere die Variable und aktiviere das Event danach wieder, so wird das zugehörige Event nicht immer unterdrückt.

Korrekt, das kann so passieren. Die Erklärung hast dir schon so gut wie selbst gegeben.

Ich dachte in IPS werden die Skripte und Events sequentiell und synchron abgearbeitet

Wo hast du dies gelesen? Eigentlich ist in IP-Symcon sehr viel asynchron. Ein Skript wird sequenziell abgearbeitet, somit wird das Ereignis entsprechend deaktiviert. Aber das Ereignis selbst, durch die Änderung der Variable, ist komplett asynchron. Somit hast du wahrscheinlich das Ereignis wieder aktiviert, bevor intern die Ereignisse abgearbeitet wurden.

paresy

Ja die Lösung von Thomas ist anders als es üblich ist für IPS, damit es mit den FS20-Instanzen funktioniert.
Hier ist das Ändern einer FS20-Statusvariable der Auslöser für das SendScript. Diese wiederum können nur per WebFront und FS20-Befehle geschaltet werden. Damit ist die CUL/CUN Variante kompatibel zur FHZ.

Du scheinst das aber ohne FS20-Instanzen und mit normalen Variablen zu nutzen ? Weil SetValue funktioniert auf Statusvariablen nicht.

Zur Ursache warum das Script ausgeführt wird, auch wenn das Event fast zeitgleich deaktiviert wird…
Habe ich gerade keine wirkliche Idee.
Eventuell hilft eine kurze Pause vom 5ms zwischen den Deaktivieren des Event und den SetValue ?
Michael

PS: Ich würde auf IP-Symcon 4.0 wechseln und mir mal die PHP Module angucken. Das würde dein Problem vollständig eleganter und wiederverwendbarer lösen :slight_smile:

paresy

Ich muss erstmal das Forum loben :slight_smile:
Man bekommt echt super schnell die Antworten die man sucht!

@Nall chan: Ja, ich habe das Senden auf normale Variablen umgestellt und lasse mir die Sende-Funktionen mit in dem RegVar-Skript generieren. Das spart mir das separate Anlegen von Sende-FS20-Instanzen; wenn ich einmal ein FS20 Paket auf einer neuen Instanz empfange wird „alles“ automatisch angelegt.

Ich habe das Senden jetzt auf Aktion-Skripts umgestellt und alles funktioniert stabil, wie gewünscht :slight_smile:

@paresy: Ich hatte hier im Forum mal in einem Beitrag gelesen, dass man sich normalerweise bei den Skripten nicht um Thread-Synchronisierung kümmern muss und alles sequentiell und eben synchron abgearbeitet wird.
Ich bin dann davon ausgegangen, dass das Deaktivieren der Events sofort aktiv ist, die Variablenänderungen synchron das Eventhandling anstößt und dann eben kein Event auslöst und danach das Event wieder aktiviert wird.
Wenn die Eventverarbeitung der Variablen allerdings asynchron ist, verstehe ich das Verhalten.
Gibt es eine Möglichkeit die Eventverarbeitung zu forcieren, ähnlich wie dies z.B. in VB mit DoEvents möglich ist? (Ich weiß, dass das kein guter Stil ist :wink: )

Ab wann ist denn IPS 4.0 released?
Das mit den PHP Modulen schaue ich mir auf jeden Fall nochmal an.

Komme eigentlich aus der C#-Welt und bin nicht so der PHP-Spezialist :wink:

Der Sinn es mit den FS20 Instanzen zu lösen war / ist ja, dass du eine vorhandene Installation weiter nutzen kannst ohne in IPS alles von FS20 auf Dummy-Instanzen mit Variablen umzustellen.
Und das du auch weiterhin die ganzen FS20_Befehle in den Scripten weiter nutzen kannst. Ohne das du etwas ändern musst beim wechsel von xzy auf CUL/CUN(O).

Auch das Umrechnen mit der Intensität oder Einschaltdauer, machen die FS20 Instanzen ja intern. Da ist das mit der zweiten Variable also gar nicht nötig. Vielleicht wäre es dann etwas einfacher ?! Da ich keine FS20 Aktoren habe, nutze ich das sende Script aber gar nicht und kann da dann auch nicht mehr viel helfen :o
Vielleicht einfach mal ausprobieren ?

Das mit den PHP-Module für IPS4 ist hier wirklich ein gutes Beispiel. So könnte man einen eigenen Splitter für FS20-Instanzen schreiben, welche die Befehle für CUL/CUN(O) umsetzt und dann per SerialPort oder LAN versendet.
Freiwillige vor :smiley:

Michael