[Semaphore] Skript nur ausführen...

… (triggern) nachdem es beendet wurde oder andersausgedrückt:
verhindern, dass ein Skript zweimal gleichzeitig ausgeführt wird.
Dies erreicht man mit dem Befehl: IPS_Semaphore
http://www.ipsymcon.de/wiki/index.php/IPS_SemaphoreEnter
http://www.ipsymcon.de/wiki/index.php/IPS_SemaphoreLeave


<?
/*
*******************************
 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.

MST

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.

Richtig??

mfG Franz

… nein - nutsch nichts nachholen > return;

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.

mfG Franz

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.

Die dritte Instanz von „Script“ …

@Ralf,

bei meinen „echo’s“ habe ich mir schon etwas gedacht.

MST

:confused:

Das Skript wurde erneut getriggert, bevor es beendet wurde.

Dann würde ich es verstehen ;).

… „ein“ > „erneut“ … :confused:

Ich glaube ich muss meine Tastatur einmal zum Justieren bringen :smiley:

MST

Da muss ein bild dabei…

Mein gespinsel:

semaphore.gif

Danke Danke, für soviel Einsatz, Leute.

Das Prinzip leutet mir ein, dennoch, WOZU brauch man sowas?

Edit:

aua, lesen bildet: ‚verhindern, dass ein Skript zweimal gleichzeitig ausgeführt wird.‘

mfG Franz

… wenn der Postmann zweimal klingelt und dann nur einmal eine Ansage (WAV) kommt
und nur einmal das Bild der Webcam (Haustür) archiviert wird …

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.

  1. 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.

Ich hoffe, das hilft… :rolleyes:

weiter so steiner, jetzt hats Ding Dong gemacht
Danke

mfG Franz

Hallo zusammen,

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:

Zweite Frage:
Kann ich das so verwenden…

IPS_SemaphoreEnter("Scriptname", 1000);

eigentliches Script
....

IPS_SemaphoreLeave("Scriptname");

oder muss es so

if(IPS_SemaphoreEnter(...))

beginnen?

Ihr seht, ich hab noch viel Nachholbedarf, habe aber zur Zeit richtig Bock drauf…:smiley:

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.

paresy

Hmmm…

(Hab bitte Nachsicht!)
Dann verstehe ich das Beispiel aus der Wiki:

<?
 
if(IPS_SemaphoreEnter("Test", 1000)) {
  IPS_Sleep(5000);
  IPS_SemaphoreLeave("Test");
  echo "OK";
 } else {
  echo "FAIL";
 }
 
?>

und von steiner nicht:

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?

Du musst Dich schon an eine der beiden Varianten halten:

Fragst Du mit Negation, also

If(!IPS_Sem…
dann kommt das Script in die erfüllte Bedinung.

Wenn ohne „!“ dann muss

Return
in die Klammern.

Will sagen, wenn Du jetzt noch das „!“ hinzufügst, klappts!

Hallo!

Aaaah, danke!
Das war´s, was ich nicht verstanden habe.
Jetzt ist mir das (hoffentlich:o ) klar…

Hallo,

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.

Gruß
Erich

Hallo,

„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.

Gruß
Fabian