<?
/*
*******************************
IP-SYMCON Event Scripting
*******************************
File : Semaphore_Demo.ips.php
Trigger : Test_Trigger > OnUpdate
Interval :
*/
if (!IPS_SemaphoreEnter("Semaphore_Demo", 1)) { // Name von diesem Skript
echo "Das Skript wurde erneut getriggert, bevor es beendet wurde";
// !! Ausgabe erfolgt im Kernel / Debug !!
return;
}
echo "Debug-Blubb";
IPS_Sleep(2000); // wie die Zeit vergeht - nur zum Test
// hier kommt das eigentliche Skript
// nicht vergessen:
IPS_SemaphoreLeave("Semaphore_Demo"); // Name von diesem Skript
?>
Für ein Test: Test_Trigger ändern / updaten und im Kernel / Debug sehen, was passiert.
also wenn ich das jetzt richtig verstanden habe, wäre das ‚reagieren nur auf negative Flanke eines Impulses‘ jedoch mit Blindflug, d.h. wir nehmen an, das Skript war „durchlaufen“ obwohl es das zwar NOCH nicht war, doch wir holen es nach nach 2 Sekunden.
tut mir leid Steiner, aber dieses Semaphore- Dingsda habe ich irgendwie verpasst. Ich habe auch in der WIKI nachgelesen, doch wurde nachher nicht schlauer. Ich sitz sicherlich wieder mal auf dem Schlauch
Macht aber nichts. Ich brauch das eh nicht.
void P (Semaphor s) {
s.zaehler = s.zaehler - 1;
if (s.zaehler < 0)
block (s.queue); /* Blockieren des Prozesses, Einreihung in Warteschlange */
}
void V (Semaphor s) {
s.zaehler = s.zaehler + 1;
if (s.zaehler <= 0)
ready (s.queue); /* Entblockieren eines Prozesses aus der Warteschlange */
}
Das Beispiel von wikipedia macht es etwas verständlicher.
Steiner hätte besser die Kommentare von dort genommen und nicht seine „echo’s“.
Die erste Instanz von „Script“ führt dazu, dass der Semaphor angelegt wird.
Die erste Instanz von „Script“ läuft normal weiter.
Die zweite Instanz von „Script“ wird gestartet. Der Semaphor existiert, also muss die zweite Instanz von „Script“ „millisekunden“ warten.
Wenn die Zeit abgelaufen ist und der Semaphor nicht mehr existiert, wird die Instanz von „Script“ normal ausgeführt.
Sinnvoll ist das Semaphore z.B. bei Triggern über Variablen.
Beispiele:
1.Telefonnummer im Örtlichen auflösen:
Wenn man eine Variable zurücksetzen möchte, welche aber das Script selbst triggert.
Script wird getriggert, Variable wird ausgelesen und der Wert weiterverarbeitet. Danach wird die Var zurückgesetzt, der String also wieder geleert. Normalerweise triggert das Schreiben der Variable das Script erneut. Aber ohne Nutzen. Mit Semaphore passiert das nicht.
Füllstandsmesser
Es wird durch den Füllstandsmesser ein Wert per COM1 übertragen. Zum Zerlegen des Strings muss dieser erstmal vollständig vorliegen. Bei meinen Versuchen habe ich festgestellt, dass der String aber in zwei Teilen „eintrudelt“. >> Ist übrigens auch bei den FHT-Daten so.
Bei diesem Event würde das Script doppelt getriggert, beim ersten und beim zweiten Teil. Aber beidemale kann man mit den Daten nix anfangen. Also beim ersten Trigger ein Semaphore anlegen, dann noch eine kurze Zeit warten und den String(Variable) vollständig auslesen.
Hab´ noch mal ein paar Fragen zum Semaphore.
Ich habe bezüglich PHP u. Proggen immer eine etwas länger Leitung, die zu entschuldigen wäre:o
Ich habe nun mal ein etwas zeitlich länger laufendes Script mit Semaphore ergänzt, welches normalerweise jede Minute neu getriggert wird.
Derzeit läuft das Script zwar noch keine Minute, aber man weiss ja nicht was noch kommt.
Wenn ich das jetzt richtig verstanden habe, dann bewirkt der „IPS_SemaphoreEnter“-Befehl, dass mindestens so lange in ms gewartet bis zum nächsten Scriptdurchlauf, wie (string: „Scriptname“, zeit in ms) angegeben ist.
D.h. wenn der vorhergehende Scriptdurchlauf noch nicht abgeschlossen ist u. das Script erneut getriggert wird, dann verfällt der Trigger.
Oder kommt der Trigger in eine „Warteschlange“ und wir nach diesen Millisekunden ausgeführt, sobald der vorhergehende Durchlauf abgeschlossen ist:confused:
Wenn ich das jetzt richtig verstanden habe, dann bewirkt der „IPS_SemaphoreEnter“-Befehl, dass mindestens so lange in ms gewartet bis zum nächsten Scriptdurchlauf, wie (string: „Scriptname“, zeit in ms) angegeben ist.
Nein. Der Befehl geht sofort weiter, wenn noch keine selbe Semaphore „gesperrt“ ist oder wartet maximal die Zeit in ms bis es zum nächsten Befehl geht.
Nun ist Frage2 wichtig, sodass du ein if() drumrumbauen musst, um zu erkennen, ob das warten abgebrochen wurde (dann Script beenden) oder ob du im Zeitrahmen bist und den Zeitkritischen inhalt (quasi innerhalb der if() ) ausführen kannst.
Oder kommt der Trigger in eine „Warteschlange“ und wir nach diesen Millisekunden ausgeführt, sobald der vorhergehende Durchlauf
Wenn du ein if() drumrummachst, verfällt der aufruf. Ohne if() ist die ganze Sache sinnlos, quasi falsch angewendet.
if (!IPS_SemaphoreEnter("Semaphore_Demo", 1)) { // Name von diesem Skript
echo "Das Skript wurde erneut getriggert, bevor es beendet wurde";
// !! Ausgabe erfolgt im Kernel / Debug !!
return;
}
Wieso steht das …Leave im Wiki vor dem eigentlichen Script u. bei Steiner´s Beispiel am Ende
u. wieso einmal
if(IPS_SemaphoreEnter
und dann wieder
if (!IPS_SemaphoreEnter
Oder anders ausgedrückt…
Müsste ich das dann so eintragen:
if(IPS_SemaphoreEnter("Scriptname", 1000))
{
Das eigentliche Script...
IPS_SemaphoreLeave("Scriptname");
}
wenn das komplette Script durchlaufen werden soll, bevor es erneut getriggt werden darf?
Wie verhält sich das dann mit den anderen {}Klammern im Script bei if-Anweisungen?
Nachdem ich’s jetzt auch verstanden und gleich in der Praxis angewendet habe, möchte ich euch meine Version nicht vorenthalten:
ips_logmessage("Debug","Start-Script");
while (!IPS_SemaphoreEnter("Semaphore_Demo", 100)) {
}
IPS_LogMessage("Debug","Run Script");
//Hier kommt das eigentliche Script
IPS_Sleep(5000); // nur zum Test
IPS_LogMessage("Debug","End Script");
IPS_SemaphoreLeave("Semaphore_Demo");
Alle Instanzen ab der zweiten Instanz warten bis die vorherige Instanz beendet ist und laufen danach eine nach der anderen ab. Ich hab das am obigen Beispiel mal testweise ausprobiert und es ist bei mir so. Werde das jetzt eingehend in meiner Anlage testen. Ich hoffe nur, es ist kein Zufall, dass die zweite, dritte, vierte,… Instanz wirklich nacheinander ausgeführt werden.
Wofür braucht man das: Ich habe mehrere Scripts, welche auf eine serielle Schnittstelle schreibend zugreifen. Damit es nicht zu einer bunten Mischung der Bytes für die Serielle kommt, werden die Scripts schön eines nach dem anderen abgearbeitet. Bis jetzt war das manchmal ein Chaos, wenn ich zugleich mehrere Lichter automatisch einschalten wollte.
„Zufall“ ist das nicht! Su musst nur darauf achten, dass die maximale Ausführungszeit des Scriptes nicht durch die „Warteschleife“ überschritten wird und das Script dann abbricht.
Dadurch würde auch das Semaphore gesetzt bleiben was einen weiteren Fehler hervor ruft…
Der Zweck ist zwar universell, aber die serielle Schnittstelle ist ein sehr gutes Beispiel.