Problem mit PHP + Javascript: Variablen abfragen und übergeben

  • Ich hab ein kleines Problem. :lol:
    Damit ihr besser versteht um was es geht hol ich mal ein bisschen aus:


    Ich bau einen Roboter, der über einen Arduino und RaspberryPI gesteuert wird.
    Der Arduino ist an den RaspberryPI via USB angeschlossen.
    Auf dem RaspberryPI laufen 2 Scripts, ein mal zur Kommunikation zum Arduino und ein anderes Script als Schnittstelle zum (optionalen) WebInterface.


    Im Programm vom Arduino lege ich default Werte fest, die ich nicht noch mal im Web-Interface festlegen will - da ich sonst immer an 2 Stellen Änderungen vornehmen müsste...


    Nun habe ich das soweit zurecht gebastelt dass der Arduino beim einschalten die default Werte via USB an den RaspberryPI schickt und dieser sie zwischenspeichert.


    Die Kummunikation zwischen WebInterface und RaspberryPI regel ich über Javascript und WebSocket.


    Nun zu dem Problem:


    Ich möchte das WebInterface so zurecht basteln das ich erst eine Initialisierungs-Seite habe, über die Verbindung zum RaspberryPI hergestellt wird und die default Werte abgefragt werden. Erst danach soll die eigentliche Steuerungs-Seite angezeigt werden.


    Mit javascript kenne ich mich leider kaum aus - mit PHP aber umsobesser..


    Nun weiß ich leider absolut nicht wie ich in Javascript prüfen kann ob die benötigten Daten erfolgreich erhalten wurden (denn solange darf nicht die Steuerungsseite geöffnet werden), bzw wie ich bei erfolgreichem erhalten der Daten diese als PHP Variablen zwischenspeichern kann :huh:
    Also "ob" ich Werte empfangen habe prüfe ich schon, aber eben in Javascript. Nur wie veranlasse ich dann das laden der Steuerungsseite und wie speicher ich die Variablen als PHP-Variablen?


    Beim laden der Seite führe ich ein init() in javascript aus um den WebSocket zu öffnen, also genauer gesagt: <body onLoad='init();'>
    Dort kann ich auch das laden der default Werte veranlassen... Nur wie gesagt, wie speicher ich diese dann als PHP-Variable? :-/


    Dazu gesagt möchte ich GET möglichst vermeiden, lieber wäre mir die Übergabe via POST.
    Soweit ich das bisher verstanden habe brauche ich ein FORM mit type=hidden und zB id=default. In Javascript könnte ich dann document.getElementById('default').value="hallo"; setzen, was dann beim abschicken des FORM's als $_POST ankäme.... Aber ich will nicht extra einen Knopf drücken müssen, der soll das selbstständig machen :(



    Hoffentlich hab ich das einigermassen verständlich beschrieben :blush:



    :helpnew:

  • Für dieses Vorhaben kann ich dir nur jQuery empfehlen (oder ein ähnlichen JavaScript Framework). Das setze ich auch sehr viel bei meinem Shmart Home Projekt ein.
    Mit jQuery kannst du auf einfache weise per AJAX Daten hin und her schicken ohne ständig die kompletten Seiten neu laden zu müssen. Als Übertragungsformat eignet sich JSON am besten, das wird perfekt von JavaScript unterstützt und auch sehr gut von PHP. Zum abrufen von Daten kannst du dann die Methode jQuery.getJSON nehmen mir der du auch Parameter von der Seite per POST an PHP auf dem Webserver schicken kannst. Als Antwort vom Server schickst du einfach ein per json_encode() Codierten JSON String zurück der von der jQuery.getJSON Funktion in ein JSON Objekt umgewandelt wird und dann einfach abgefragt werden kann.


    Ablauf könnte also folgender sein:
    Startseite Laden -> 1s wartezeit -> AJAX Anfrage an PHP ob die Variablen vom Arduino da sind (kann auch mit zeitverzögerung so lange wiederholt werden bis das ergebnis i.O. ist) -> wenn i.O. mit window.location die Steuerungsseite laden (oder per AJAX die Steuerungsseite nachladen und im aktuellen Dokument einfügen)


    Dazu wird weder ein Button oder ein verstecktes Formular benötigt. Das ganze geht auch ohne JavaScript Libary aber ohne gute JavaScript Kenntnisse ist das eher ungünstig.


    In meinem Raspberry Pi SmartHome Control geht dieses System so weit das nur einmalig die Startseite geladen wird und alle anderen Funktionen laufen nur über AJAX und tauschen nur Teile der Seite immer wieder aus.

  • Die Frage ist einigermassen verworren, nehmen wir sie doch mal ein bisschen auseinander:


    * Wenn die Daten auf dem PI sind, kann man sie mit PHP auch von dort lesen,
    zumindest wenn man sie an einen Ort legt den PHP lesen kann


    * Jetzt gilt es noch zu warten, bis die Daten wirklich da sind. Die Frage ist,
    ob das ueberhaupt noetig ist, oder ob die zuletzt gespeicherten genommen
    werden koennen.


    * Wenn man unbedingt warten muss, dann kommt AJAX ins Spiel. Mit AJAX
    eine Abfrage an ein PHP-Script machen das prueft ob die Daten gueltig sind.
    Wenn die Daten gueltig sind, mit JavaScript die Formularseite aufziehen.

  • Auf jQuery und AJAX möchte ich eigentlich verzichten da oversized ;)
    habe auch schon AJAX ohne jQuery programmiert (bzw mit XMLHttpRequest) aber das erzeugt mir zu viel Last auf dem Webserver (und auch zu viele Logeinträge da ja ständig eine interne Anfrage an den Webserver stattfindet)


    Mein bisheriger Code verwendet innerHTML um einzelne Elemente, auch ohne die kompletten Seite neu zu laden, zu erneuern; also Statusmeldungen und Sensorwerte usw.


    Wie das ganze Theoretisch ablaufen müsste weiß ich auch ungefähr, nur fehlt mir halt Code an dem ich mich orientieren kann :(




    Die Daten sind im python Script hinterlegt, was ich ja über mein WebInterface via WebSocket anspreche. Ich will es vermeiden diese Variablen in eine Datei zu schreiben um die dann über PHP auszulesen.. Ich mag Ordnung ;)



    Google schon den ganzen Tag und probiere rum, aber nix will so richtig funktionieren =(


    Meine bisherigen Versuche sieht ungefähr wie folgt aus:


    index.php:


    websocket.js:


    control.js:


    ...ich hab jetzt insbesondere von der index.php nicht alles gepostet, aber falls nötig ergänz ich das auch noch :huh:


    Leider funktioniert das so noch nicht :wallbash:
    Auch fehlt mir noch der Part die defaultSettings als PHP-Variablen zugänglich zu machen.

  • Ich versteh' dein Anliegen leider noch nicht so ganz. Kannst Du vielleicht noch kurz erläutern was dein PHP-Script macht und wofür es diese Variablen braucht? Woher die Default Werte kommen? Und wo sie hinsollen? :s


    Edit: Ah. Jetzt hab ich's glaub ich verstanden.. Du holst Dir die Default Daten per Python und möchtest sie in PHP weiterverarbeiten?


    Edit 2: Vielleicht wäre der Inhalt deiner index.php wirklich nicht schlecht. :^^:

  • Ja genau.


    Mein Arduino hat zum Beispiel Werte für die Standard Pan und Tilt Position, die ich in meinem Steuerungs Webinterface brauche um die "range" Werte richtig zu setzen, um dann halt Pan oder Tilt entsprechend zu schwenken.


    Schalte ich den Arduino ein, sendet er die default Settings an ein python Script auf dem PI. Lade ich dann das WebInterface soll das diese Werte 'abholen' und die entsprechenden Sachen, also Schieberegler usw, einstellen bzw dort dann halt verwenden:

    PHP
    <label for="Tilt">Tilt:</label> 
    <output for="Tilt" id="TiltPos"><?php echo $Tilt_Start; ?></output>
    <br/>
    <input type="range" id="Tilt" min="<?php echo $Tilt_Max; ?>" max="<?php echo $Tilt_Min; ?>" value="<?php echo $Tilt_Start; ?>" class="vertical" orient="vertical" onInput="outputTilt(value);" onChange="WebSocket_Send('tilt:'+value);">
    <br/>
    <input type="range" id="Pan" min="<?php echo $Pan_Min; ?>" max="<?php echo $Pan_Max; ?>" value="<?php echo $Pan_Start; ?>" onInput="outputPan(value);" onChange="WebSocket_Send('pan:'+value);">
    <br/>
    <label for="Pan">Pan:</label> 
    <output for="Pan" id="PanPos"><?php echo $Pan_Start; ?></output>
  • Also hast Du keinen wirklichen Grund PHP zu benutzen wenn ich das richtig sehe?


    Speicher die default Werte doch einfach in deinem Python Programm zwischen. Wenn dein Web-Client eine WebSocket Verbindung öffnet, schicktst Du einfach die Initial Werte an den Browser.


    Ich würde Dir dazu raten, ein kleines Protokoll mit JSON Objekten zu bauen. Dann kannst Du in deinem JavaScript leichter unterscheiden, was Du mit den Daten machen sollst. Das kann dann für die Initial-Werte in etwa so aussehen:


    Code
    {
       event: "default_values",
       data: {
         tilt: 1234,
         pan: 1234
      }
    }


    Und für deine Live Werte so:

    Code
    {
       event: "live_values",
       data: {
         tilt: 1234,
         pan: 1234
      }
    }


    In deiner Websocket.js machst Du dann etwas in der Art:

    Code
    ws.onmessage = function(e) {
            var message = JSON.parse(e.data);
            if(message.event === "default_values"){
               // hier setzt Du die default werte
            } else if (message.event === "live_values"){
              // hier die aktuellen Werte
            }
    }


    Ich hoffe Du verstehst, was ich mir in etwa vorstelle?

  • Es bleibt leider weiterhin die Frage wie ich die Javascript-Variablen als PHP-Variablen verwenden kann - was ich bevorzugen würde


    Und wie verifiziere ich das alle benötigten Settings eingetroffen sind, bevor ich dann die ropi.php "freischalte" ?



    Mir ist btw bewusst das ich die Variablen auch im Python Script in eine Datei speichern und dann via PHP auslesen könnte - das betrachte ich aber als einen sehr dreckige Weg den ich nicht gehen möchte ;)



    //EDIT: Ich denke ich Terminier die Übergabe einfach indem ich ans Ende der defaultSettings ein END:END einfüge, anhand dessen ich dann erkennen kann dass das, das Ende der defaultSettings-Liste ist und setze dann receivedDefault = 'TRUE'; ... mal gucken ob das funktioniert

  • Ah. Alles klar! :)


    Ich finde deinen Ansatz aber trotzdem einwenig suboptimal, die Daten erst an den Client zu schicken und dann wieder zurück an den Server zu übergeben um die Variablen dann ins HTML zu schreiben und mit PHP wieder auszugeben.


    Wenn Du keine Javascript Bibliotheken verwenden möchtest, kannst Du alles tatsächlich nur mit 'document.getElementById("#")' und den entsprechenden Feldern und Methoden das HTML mit Werten befüllen. Das geht mit jQuery einwenig leichter. Die bessere Möglichkeit wäre sonst eine Template-Render-Bibliothek wie mustache.js zu verwenden.


    Dann kannst Du in deinem HTML Variablen setzen, die dann einfach befüllt werden. (Beispiel gibts hier: https://github.com/janl/mustache.js/#include-templates)


    Wenn Du auf deiner Methode bestehst, kommst Du um AJAX nicht rum.

  • Ich würde mich mittlerweile auch mit einer GET Übergabe zufrieden geben - solange ich auf AJAX oder jQuery verzichten kann...



    Wie kann ich über Javascript Variablen an ein PHP Script übergeben, ohne dabei die URL tatsächlich anzusurfen also zu öffnen?



    Ich hab es bereits mit:

    Code
    var img = new image();    
    img.src='include/functions.php?'+value+'='+value2;


    versucht, was ich in den Weiten des Internets gelesen habe - leider funktioniert das gänzlich gar nicht, es kommt nichts bei der functions.php an.


    Habs davor auch schon mit window.location sowie window.location.href und location.href probiert aber damit wird die functions.php tatsächlich angesurft und mir angezeigt - das will ich aber nicht :(

  • Ohne AJAX (egal ob mit XMLHttpRequest, JQuery oder einer anderen Bibliothek) wirst Du keine Parameter übergeben können, ohne die Seite aufzurufen. Was spricht denn eigentlich gegen AJAX?


    Wenn es Dir nur um das Befüllen der Variablen geht und Du mit meinen bisherigen Vorschlägen nicht weiterkommst, könntest Du die Variablen im HTML auch mit Python setzen.

  • Ah!! Ich glaub jetzt funktioniert es schon beinahe perfekt:

    Code
    img = new Image();    
    img.src='include/functions.php?'+value+'='+value2;


    Jetzt hab ich nur noch ein Problem das er sich ein bisschen im Kreis... mhmh



    Also ich mache das jetzt zZt so:
    Wie in Beitrag#5 bereits beschrieben hab ich ein <body onLoad='init();'> was WebSocket_Open() aufruft und dieser WebSocket Part wiederum sieht so aus:


    Für GetDefaultSettings() siehts so aus:


    Dann hab ich halt eine Function was die empfangenen Daten (die Antwort vom Python Script auf WebSocket_Send) vom WebSocket verarbeitet: parseResponse


    Und die include/functions.php sieht zZt so aus:



    Jetzt hab ich wie gesagt nur noch das Problem das nach aufruf der ropi.php trotzdem weiterhin WebSocket_Send('get.defaultSettings') ausgeführt wird :-/ :helpnew:

  • Deine Vorgehensweise finde ich immer noch alles andere als optimal.. Aber wenn es den Zweck soweit erfüllt..


    Rufst Du deine Skripte auch in der ropi.php auf? Wenn ja, öffnest Du damit ja beim jeden laden die Websocket Verbindung, holst Dir die default Werte, leitest an ropi.php wieder weiter, die Socket Verbindung wird geschlossen und beim nächsten Aufruf wieder geöffnet, holst Dir wieder damit in onOpen die default Werte und das Spiel beginnt von vorn. :geek:

  • Ja, das Problem hab ich leider auch schon identifiziert :D


    Entweder ich leg jetzt ein extra javascript an in dem nur diese besondere Handhabung enthalten ist, und lade das nur in der index.php ... was aber den Nachteil hätte das ich bei einem "on the fly" WebSocket Reconnect keine neuen defaultSettings Werte mehr kriegen könnte.


    Oder ich finde heraus wie ich ohne ajax eine javascript-session-variable definieren kann :-/


    Vermutlich muss ich mich auf einen Kompromiss einlassen =(

  • Weil mir AJAX zu viel Last auf dem Webserver erzeugt. Es wird - zumindest soweit ich weiß - ja ständig im Hintergrund eine Anfrage an den Webserver gerichtet (Polling), also zB ein Aufruf einer php Datei in der ein div definiert ist um dieses dann auf der Hauptseite zu aktualisieren.


    Ich fahre momentan eigentlich ganz gut mit document.querySelector bzw document.getElementById("...").innerHTML einzelne Textstellen zu aktualisieren


    Dazu kommt aber auch das ich diese jQuery Geschichte kompliziert und schwer zu verstehen finde :blush:
    [hr]
    Ha! Warum kompliziert wenns auch einfach geht!


    Hab die Lösung gefunden und war irgendwie ziemlich simpel. Hab nur die function:

    Code
    function LoadControllPage() {
      document.location="http://"+location.host+"/ropi.php";
    }


    so abgeändert:

    Code
    function LoadControllPage() {
      var check = window.location.pathname;
      if (check == "/" || check == "/index.php") {
        document.location="http://"+location.host+"/ropi.php";
      }
    }


    Und schon funktionierts, kein loop mehr :bravo2:


  • Weil mir AJAX zu viel Last auf dem Webserver erzeugt. Es wird - zumindest soweit ich weiß - ja ständig im Hintergrund eine Anfrage an den Webserver gerichtet (Polling)


    Wieso sollte er dauernd pollen wenn Du nur einen Request abschickst? Ich glaube Du verwechselst da etwas.


    Aber Du hast ja deine Lösung gefunden. :)