Jump to content

[PHP] Wie Callbacks richtig einsetzen?


Recommended Posts

Servus,

 

ich würde gern mein "Equipment" gern per PHP steuern. Erste "erfolge" hab ich ja schon gehabt, aber so richtig zufrieden bin ich irgendwie noch nicht.

 

Zu schaffen macht mir irgendwie diese Callback-Möglichkeit in PHP. Das Script "steht" quasi jedes Mal solang der Callback läuft. selbst wenn ich z.B. angebe, dass bei einem Callback-Aktion z.B. was auf's Display geschrieben wird passiert da nix. Sobald aber der Callback zuende ist, führt er quasi alles aus  und schreibt wie wild auf dem Display rum... Ich hab auch spaßeshalber die Zahl der Callbacks hochzählen lassen und da passiert schon a bissl was.

 

Wie ist das denn gedacht dies zu nutzen? Aktuell arbeite ich nur mit dem CLI...

 

Gruß

Christian

Link zu diesem Kommentar
Share on other sites

PHP hat keine Threads. Das führt erstmal dazu, dass du selbst dispatchCallbacks() aufrufen musst. Wenn du dispatchCallbacks(1) dann werden eingehende Daten vom Socket gelesen und wenn es sich um Callbacks handelt werden diese ausgeführt, falls dafür Funktion registriert wurden.

 

Wenn du dispatchCallbacks(1) aufrufst, dann wird das eine Sekunde lang gemacht und dispatchCallbacks(1) returned auch erst nach einer Sekunde. Das heißt das dein Script an der Stelle für eine Sekunde "steht".

 

Du kannst auch dispatchCallbacks(0) aufrufen, dann werden nur die gerade verfügbaren Daten vom Socket gelesen ohne noch eine Sekunde auf weitere Daten zu warten.

 

Daher empfehlen ich dir dispatchCallbacks(0) aufzurufen. Du solltest weiterhin darauf achten dass du keine lange dauernden Dinge in den Callback Funktionen machst.

Link zu diesem Kommentar
Share on other sites

OK, danke erst mal.

 

Das macht das ganze zwar nicht unbedingt leichter ;-), aber ich hab mal was geschustert, was mehr oder weniger gut läuft. Findet Ihr im Wiki.

 

Ich hab nur ein großes Problem:

- beim RotaryPot läuft der Callback nach dem zweiten Durchgang der unendlichen While-Schleife nicht mehr... die Temperatur wird ständig abgefragt, die Position aber wie gesagt nach dem zweiten Durchlauf nicht mehr.

Der Dispatcher läuft ja 2 sekunden und startet dann neu

 

Aktuell kommt beispielhaft folgendes auf der Console an:

D:\>php.exe -f tinkerforgeV1.php
Rotary connected
LCD connected
rotpot: 39
pos:39.....^C

Nach jedem Durchlauf der Schleife wird ja ein Punkt ausgespuckt, aber ich kann mir da den Wolf drehen ;-)

rotpot: ist die Callback funktion und pos: wird ja nur einmal gelesen bevor es in die Schleife geht...

 

Ich hab den gesamten Code schon mal soweit auskommentiert das nur noch LCD und Rotary verbunden sind. Und es ist dann nur der Rotary-Callback aktiv.

 

Gruß Christian

Link zu diesem Kommentar
Share on other sites

Ich hab gerade noch ein Problem mit den Callbacks behoben. Wenn du in einem Callback einen Getter des selben Devices aufgerufen hast konnte das zu einer TimeoutException führen. Das ist in PHP Bindings Version 1.0.2 jetzt behoben.

 

Zu deinem Problem: Dein Script erzeugt in jeder connect_* Funktion eine neue IPConnection. Du solltest initial nur eine erzeugen un die dann in allen connect_* Funktion verwenden.

 

So wie dein Script jetzt ist dispatcht du Callbacks nur auf der zuletzt erzeugen IPConnection der du nur das Temperature Bricklet hinzugefügt hast. Ich denke das erklärt dein Problem :)

Link zu diesem Kommentar
Share on other sites

Also ich hab mir mal die neuesten Bindings gezogen 1.0.2 und meinen Code entsprechend optimiert/korrigiert.

 

sieht jetzt mal ganz nett aus und alles klappt soweit relativ gut. ohne diese Threads ists halt nicht so das wahre.

 

ich lasse den Dispatcher nun 1/10-Sekunde laufen und lasse dann entsprechend die Callback-Funktionen laufen.

 

Aktuell gibt mein Display folgendes aus:

- nen Titel

- die Position des Rotary Poti

- die Temperatur auf eine Nachkomma-Stelle gekürzt.

- die aktuelle Uhrzeit

 

Folgende "Features" gibt’s noch oben drauf:

- LCD blinkt einmal kurz auf, wenn die Temperatur über 25°C liegt.

- das LCD blinkt jetzt auch nicht ununterbrochen wenn der Grenzwert überschritten ist, sondern "nur" alle 10 Sekunden mal kurz als Hinweis.

- die Uhrzeit wird nur auf das LCD geschrieben wenn diese sich auch geändert hat (also quasi nur einmal pro Minute und nicht 10x pro Sekunde :-) )

Link zu diesem Kommentar
Share on other sites

Abhängig vom geplanten Einsatzzweck lässt sich ein längerer Callback auch mittels pcntl_fork() auslagern. Dazu gibt es ein paar einfache Klassen die öffentlich verfügbar sind, die den Aufwand zur Verwaltung erheblich reduzieren.

 

Die Frage ist schlicht was genau notwendige Arbeiten bzw. wie stark der Informationsaustausch zwischen den Prozessen dann wird, da dies schon eine Menge zusätzlichen Codes bedarf.

 

Auf nachfolgendem Link ist dazu ein Beispiel zu finden:

http://blog.motane.lu/2009/01/02/multithreading-in-php/

Link zu diesem Kommentar
Share on other sites

wenn ich das noch richtig im Kopf hab, sind die pcntl-Funktionen nicht auf Windows-Systemen verfügar... das nur so am Rande.

 

nur die *NIX-en wäre da noch ein Hinweis auf das PEAR-Modul System_Daemon.

 

Mal schaun. Noch ist das alles Bastelei bei mir. Evtl werd ich doch noch auf Java umsteigen, wenn ich Muse zum lernen hab :)

Link zu diesem Kommentar
Share on other sites

Wir hatten festgelegt das es standalone auf Linux und Windows sowie mit Apache funktionieren sollte.

 

pcntl_fork funktioniert nicht auf Windows oder mit Apache und andere Lösungen funktionieren nur mit Windows und unter Apache sieht man ganz alt aus. Daher haben wir uns für die Lösung ohne Threads entschieden.

 

Mal davon abgesehen: Wenn ich einen zweiten Prozess hab (wie einen  System_Daemon oder mit pcntl_fork) muss man immernoch pollen um die Daten die beim geforkten Prozess aufgelaufen sind abzuholen! Dadurch würde man nicht viel gewinnen.

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...