[Semaphore] Skript nur ausführen...

Hallo!

Su musst nur darauf achten, dass die maximale Ausführungszeit des Scriptes nicht durch die „Warteschleife“ überschritten wird und das Script dann abbricht.

Keine Sorge, bei mir handelt es sich um Zeiten im Millisekunden-Bereich. Also bis jetzt funktionierts auch super:D

Nett finde ich auch das Feature, dass IPS mittels einer Fehlermeldung daran erinnert wenn das Semaphore nicht geschlossen wird (Ich hatte anfänglich noch einen kleinen Fehler im Script):

ScriptError: HOCO_E_Zaehlerkasten.ips.php ~ Sender: RunScript ~ Result: Warning: Semaphore ‚HOCO_Encode‘ was not released!

Gruß
Erich

Hi!

Noch ´ne kurze Frage, rein zum Verständnis…
Die Millisekunden, die ich im Semaphore_Enter angebe, müssen mehr sein, als das Script ingesamt laufen würde, oder bedeuten die, dass das Script einfach solange Pause macht, bevor es den nächsten Trigger zulässt?

Ich glaube, ich habe das noch nicht „vollends“ verstanden…:confused:

Hi Nancilla,

keine Angst - DU BIST NICHT ALLEINE.

Ich verfolge diese Thread schon seit längerem mit grosser Interesse - habe es aber auch immer noch nicht vollends ‚geschnallt‘. :confused:

Entweder brauche ich eine Erklärung für ‚Oldies über 50‘ oder mal ein echtes Anwendungsbeispiel, dass man nachvollziehen kann.

Gruss babba (Dieter aus Wiesbaden)


if (!IPS_SemaphoreEnter("Semaphore_Demo", 1))
 { 
  return;
 }

//Script was ablaufen soll

IPS_SemaphoreLeave("Semaphore_Demo"); 


So da will ich auch mal meinen Senf dazu geben ud es versuchen in einfachen Worten zu beschreiben. Habe mal aus Steiners Beispiel das wesentliche hergenommen.

Also im ersten Teil wird geprüft ob das Script (hier:„Semaphore_Demo“) schon läuft.
Ist dies der Fall und das Script wurde durch irgendeinen Trigger nochmal aufgerufen ist die Bedingung erfüllt und es erfolgt das return und somit das verlassen des Scripts.

Wurde das Script das erste mal aufgerufen wird es ganz normal abgearbeitet und kann während der Abarbeitung auch nicht gestört also nochmal aufgerufen werden, da es ja durch den SemaphoreEnter Befehl gesperrt ist.
Am Ende wird es durch den IPS_SemaphoreLeave Befehl wieder zum erneuten ausführen freigegeben.

MfG Thomas

Hallo Thomas,

Das leuchtet mir ein:) , aber wie hoch sollte die Zeit in Millisekunden gewählt werden?
Reicht eine Millisekunde? Sind die 1000 Millisekunden im Wiki http://www.eyep.de/wiki/index.php/IPS_SemaphoreEnter einfach nur ein Wert, oder hat das einen Grund, dass die so hoch angesetzt wurden?
Irgend so ein Sicherheitswert… setzen wir eben mal 1000 ms (1s) ein…?

Ich probier’s mal mit der Oldies-Variante:

Stell Dir vor, du bist auf einer Feier. Viele Leute, aber nur eine Toilette! Dein Freund verspürt einen Drang und besucht das stille Örtchen. Beim Betreten hängt er das Schild „besetzt“ raus SEMAPHORE WIRD GESETZT : IPS_SemaphoreEnter(„Semaphore_Demo“, 1).

Jetzt musst du auch mal und gehst zum stillen Örtchen. Dort angekommen überprüfst du, ob es frei ist [i]IPS_SemaphoreEnter(„Semaphore_Demo“, 1)
[/i]. Leider - es ist besetzt. Du wartest eine vordefinierte Zeit IPS_SemaphoreEnter(„Semaphore_Demo“, 1). Doch dein Vorgänger hält scheinbar eine längere Sitzung. Also gehst du wieder zum Tisch zurück { return;}

Wenn dein Freund die Toilette verlässt, nimmt er sicherlich auch das „besetzt“-Schild wieder weg IPS_SemaphoreLeave(„Semaphore_Demo“)

Hoffe, das war anschaulich genug :smiley:

Verwirrend ist sicherlich, dass der Befehl IPS_SemaphoreEnter 3 Dinge ausführt:

[ol]
[li]Er überprüft das Semaphore.
[/li][li]Er setzt das Semaphore, falls es frei ist.
[/li][li]Ist es nicht frei, wartet er eine gewisse Zeit und überprüft nochmal ob es frei ist.
[/li][/ol]

Gruß
Erich

Das hängt von der Laufzeit deines Scriptes ab. Wenn 2 in etwa zugleich starten, wie lange muss das 2. warten, bis das 1. fertig ist.

Gruß
Erich

Köstliche Oldies Variante. :smiley:

Gruß Thomas

Hallo Erich,

also das Toilettenbeispiel habe ich auch verstanden:D
Sollte man so in die Wiki aufnehmen:cool:

Wenn ich dann die Zeit zu klein nehme beansprucht es die Performance mehr, weil öfters versucht wird, dass Script neu zu starten, als wenn ich die Zeit größer setze, richtig? Also eine Frage der Abschätzung, wie lange läuft das Script u. wann kommt ein neuer Trigger?!

Hallo,

bei der Vorgaengerversion vom RRDTool wurde immer eine Logdatei geschrieben, die ich dann weiter verarbeitet habe. Da im Graphbuilder abhaengig von der Anzahl der Graphen das RRDTool mehrfach schnell hintereinander laeuft, konnte es passieren, dass die Logdatei fuer das Lesen und anschliessende Loeschen gesperrt war. Um dann ein auftretendes Problem zu umgehen, ist dort der Befehl angewendet.

Im Moment ist der Code im Graphbuilder noch nicht bereinigt, Ihr koennt Euch das ganze also als Beispiel ab Zeile 67 anschauen.

Es wird geprueft, ob das Semaphore gesetzt wurde und falls ja, maximal 2 Sekunden gewartet. Wenn innerhalb dieser Zeit die Freigabe erfolgte, wird weitergemacht (Zeile 68), anderenfalls kehrt das Programm durch return zurueck (Zeile 83).

Das Script befindet sich bei installiertem WIIPS und registrierem RRD Modul im Verzeichnis:

web_data/rrd/exe

und heisst: RRD_Graphbuilder.ips.php

Gruss Torro

Das Beispiel mit der Toilette war köstlich :smiley:

Logischerweise hat ein Datentelegramm das dann bei mir im Debug-Fenster 3x erscheint, auch den gleichen Zeitstempel.
Ist es nicht so dass IPS_Semaphore nur die Skriptausführung zeitweise verhindert, jedoch nicht vermeiden kann? Es wird dennoch 3x ausgeführt, nur eben mit Wartezeit !?
Das ganze hier passt auch zu diesem Thread.
Es ist nämlich so, und das sehe ich ganz gut bei meinem KS300 Skript: Obwohl alles auf ‚OnChange‘ steht, wird dennoch das Skript 3x hintereinander ausgeführt, was bei einer ellenlangen Stringvariable (zur Generierung des HTML Code) äusserst störend ist.

Hier wäre ich für einen Lösungsansatz äusserst dankbar, weil mir fällt nix ein, ausser das so hinzunehmen.

Franz

Hallo Franz,

nein, das ist so nicht korrekt. Das was Du siehst, ich nicht das, was tatsaechlich passiert. Du bekommst die Microsekunden nicht angezeigt, und diese unterscheiden sich.

Ist es nicht so dass IPS_Semaphore nur die Skriptausführung zeitweise verhindert, jedoch nicht vermeiden kann? Es wird dennoch 3x ausgeführt, nur eben mit Wartezeit !?

Das Script wird 3x ausgefuehrt, aber eben nur bis zur Semaphorepruefung. Wenn die positiv ausfaellt (es ist also vorhanden) - dann musst Du programmtechnisch das Script beenden - bspw. durch Return.

Gruss Torro

Danke, danke, danke - im speziellen an Thomas und an Erich.

Wobei Erich den Vogel abgeschossen hat - ENDLICH hat es auch bei mir ‚geschnackelt‘ und Erich: „you made my day“.

Mit dem nun vorliegenden Verständnis kann ich nun hoffentlich meine gerade fertig gestellte Heizungskesselsteuerung - wesentlich sicherer betreiben.

Für diejenigen die es interessiert:
Die Kesselsteuerung ist eine eigenständige Prozessorsteuerung (mit dem Freescale 9S12C32) die so alle erdenklichen Betriebsarten fahren kann (Vorlaufsteuerun, Rücklaufsteuerung, Slave Mode usw.). Sie kann autark arbeiten oder aber - und das war mein Ziel - als Slave, wobei IPS als Master die notwendige Zieltemperatur berechnet und über die serielle Schnittstelle jede Minute an die Steuerung sendet, die so lange sie diesen minütlichen Befehl erhält als Slave arbeitet. Unabhängig davon sendet die Steuerung Statussignale wie Brenner EIN und Brenner aus an IPS - hier habe ich noch ab und an Probleme diesen kleinen String in einem Stück zu erwischen, aber ich bin wohl auf dem richtigen Weg. Ausserdem kann ich über den Designer alle Betriebsparameter lesen und auch schreiben.

Das war’s für heute - Danke noch mal für die Erklärungen.

Gruss aus Wiesbaden

Dieter (alias babba)

Danke für die Info, aber Fakt ist, was IPS_Semaphore anbelangt steht ich echt auf dem Schlauch.

Wie könnte ich das denn an diesem Skript einbauen, so dass das Skript nicht 3x ausgeführt wird? Ich muss das ehrlich mal in einem Beispiel sehen, sonst schnall ich das NIE !

/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : HTML-Weather.ips.php
Trigger  : 
Interval : 
*/
$content = "<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
<title>Untitled Document</title>
<style type=\"text/css\">
<!--
.style3 {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; }
.style4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; }

body { background-color: #C0C0C0; }
-->
</style>
</head>

<body scroll = no>
<table width=\"466\" border=\"1\" cellspacing=\"0\" bordercolor=\"#000000\" bgcolor=\"#FFFFFF\">
  <tr>
    <td height=\"28\" colspan=\"3\" bgcolor=\"#FFCC33\"><span class=\"style3\">Weatherstation Backyard</span></td>
  </tr>
  <tr>
    <td width=\"135\" height=\"34\" class=\"style4\">Temperature</td>
    <td width=\"193\"><span class=\"style4\">".number_format(GetValueFloat("KS300_TEMPERATURE"), 2, ".", "." )." °C</span></td>
    <td width=\"124\" rowspan=\"4\" align=\"left\" valign=\"top\"><img src=\"http://www.weatherpixie.com/displayimg.php?place=ELLX&type=C&trooper=12\"></td>
  </tr>
  <tr>
    <td height=\"35\"><span class=\"style4\">Moisture</span></td>
    <td><span class=\"style4\">".number_format(GetValueInteger("KS300_MOISTURE"), 2, ".", "." )." %</span></td>
  </tr>
  <tr>
    <td height=\"37\"><span class=\"style4\">Windspeed</span></td>
    <td><span class=\"style4\">".number_format(GetValueFloat("KS300_WIND_SPEED"), 2, ".", "." )." km/h</span></td>
  </tr>
  <tr>
    <td height=\"37\"><p class=\"style4\">Rain Amount<br />
      24 hours</p>
      </td>
    <td><span class=\"style4\">".number_format(GetValueFloat("RAIN_TODAY"), 2, ".", "." )." liter/m²</span></td>
  </tr>
</table>
</body>
</html>";
SetValueString("HTML_WEATHER_DATA_KS300", $content);
echo $content;


Danke im Voraus für jegliche Hilfe

Franz

Hallo Franz,

die Lösung für Dein Problem ist ganz einfach:

if (!IPS_SemaphorEnter($IPS_SELF, 1)) return;
// Skript-Befehle ...
// Skript-Befehle ...
// Skript-Befehle ...
IPS_SemaphorLeave($IPS_SELF);

Was geschieht hier?
Der erste Trigger startet das Skript.
Das Skript versucht ein Semaphor zu setzen.
Ist noch keines gesetzt, so ist die Aktion erfolgreich.
Ist bereits eines gesetzt, so wartet das Skript 1ms und versucht es dann noch einmal.
Da aber das Skript sicher länger als 1ms läuft, kommen die nachfolgenden Trigger nie zum Zuge.
Damit ist sichergestellt, dass das Skript nur ein einziges Mal abgearbeitet wird.

Gruß
HJH

Aber nur, wenn die Abstände der Triggerzeitpunkte kleiner als die Laufzeit des Scriptes sind!! Mag jetzt funktionieren, aber wenn du irgendwann mal die Hardware änderst, oder sich das Programm-Timing verschiebt, geht es möglicherweise plötzlich nicht mehr.
Habe da eine andere Idee (siehe diesen Thread). Ist aber nur mal Theorie - noch nicht ausprobiert!

Gruß
Erich

Danke dir,

nur eines hab ich dann falsch verstanden. Ich dachte immer, dass die Trigger-Events gestapelt werden, und nachdem dann Semaphore_Leave kam, dann die anderen beiden nachgeholt werden würden !?
Dieses IPS_Semaphore hab ich so richtig auf dem Magen, hmmmm, der liegt dort sehr schwer. Oder ich werde einfach nur alt…

Franz

Hallo,

ich habe das nun beigefügt, das Skript wird dennoch weiterhin 3x durchlaufen. Das mit dem Semaphore klappt wohl nicht.
Ich probier nun mal noch ein kleines IPS_Sleep einzubauen. Villeicht läuft das Skript doch unter einer Millisekunde durch

Franz

Hallo Franz,

So ins Blaue hinein… wenn ich das sonst so vergleiche…
Probier mal:

if (!IPS_SemaphorEnter($IPS_SELF, 1)) 
{
return; 
}

Ich werde es tun, aber morgen. Ich bin jetzt zu müde dafür. Mit IPS_Sleep(100); bevor dem IPS_SemaphoreLeave geht es mal

Franz