C/C++ Programm über PHP-Befehl ausführen

  • Hallo zusammen,

    kurz und knapp erklärt: Ich möchte über PHP die GPIO Schnittstelle des Raspberrys ansprechen. Die entsprechende HTML-Seite habe ich soweit fertig.
    Bei Betätigung eines darauf befindlichen Buttons soll dann ein entsprechendes C/C++ Programm ausgeführt werden.

    Ist das so überhaupt möglich bzw. sinnvoll? Oder habt ihr eine andere Lösungsmöglichkeit? :helpnew:


    Vielen Dank schon mal für die Unterstützung.
    Gruß,
    Timmi

  • FAQ => Nützliche Links / Linksammlung => [PHP] Anleitung zum schalten von GPIO
    FAQ => Nützliche Links / Linksammlung => [Python] Webserver, Websocket und ein bisschen AJAX

    Ob das Sinnvoll ist kann man nicht beantworten solange man nicht weiß was dein C/C++ Programm macht ;)

  • Ich habe mir ein ferngesteuertes Fahrzeug gebaut. Im Prinzip möchte ich z.B. über den Buttons "Vorwärts" ein C-Programm aufrufen was mir die entsprechenden GPIOs setzt.
    C bzw. C++ ist mir dahingend aber wichtig da ich das in der Schule gelernt habe und weiternutzen möchte.

    Gruß,
    Timmi

  • Naja, über PHP ein C++ Programm aufrufen um dann GPIO's zu schalten? :-/ Würde ich nicht als Sinnvoll betrachten...
    Entweder C++ oder PHP weg lassen - also eine Brücke ist da zu viel... Oder wie im 2.Link beschrieben pures Python nutzen. Oder das C++ als Daemon laufen lassen und mithilfe von FIFO oder Socket ansprechen. Aber ständig C++ Programm starten, Aktion ausführen, wieder beenden etc - nur wegen GPIO's schalten, ist nicht sehr effektiv

  • Ich hatte mir gedacht das das nicht das sinnvollste ist :D
    Aber wie kann ich denn von meiner Website das C++ Programm starten?

    Oder anders gefragt, wie würdest du soetwas angehen?

    Gruß,
    Thomas

  • Hat er doch gesagt. Entweder das cpp Programm als daemon laufen lassen - quasi als Server, der immer läuft - und dann von der Website aus mit diesem kommunizieren. Oder eben direkt von php die gpios ansteuern. Wie das geht steht in meigrafd's Tutorial.

  • Dein C-Programm muss halt auf Kommandos hoeren. Es gibt da verschiedene Moeglichkeiten, die einfachste ist eine sogenannte Message Queue unter Linux:

    https://www.cs.cf.ac.uk/Dave/C/node25.html
    http://php.net/manual/en/function.msg-get-queue.php

    Die kannst du sowohl von C aus erzeugen und auf Eingaben warten, als auch von PHP aus Daten darein schreiben.

    Named Pipes und generell sockets sind auch eine Moeglichkeit, allerdings dem Anfaenger nicht zu empfehlen da nicht Nachrichten-basiert. Sondern byte-basiert. Das bedeutet das du nicht garantiert bekommst, dass du eine Nachricht die du abschickst - zB "robot move forward 10" - auch so bekommst. Sondern nur "robot move f" - und danach beim naechsten lesen "orward 10". Das macht das verarbeiten der Daten deutlich komplizierter, weil man ein Protokoll entwickeln muss.

  • Nein, natuerlich nicht. Aber die anderen Wege sind auch nicht einfacher. Wenn du zwischen verschiedenen Rechner Nachrichten verschicken willst, wirst du lernen muessen, wie das geht.

    Ich kann nur empfehlen sich kleine Beispiele zu schreiben, ein C-Programm das auf eine eingehende Nachricht wartet, und ein PHP-Skript das die verschickt. Und dann von da aus weiter.

  • Naja also das erste was Er klären müsste wäre ob er wirklich PHP nutzen will.
    Wenn er seine Webseite auf Basis von PHP ausgebaut hat ist eben der Nachteil das bei jedem Absenden eines Befehls die komplette Seite neu geladen wird. Man könnte zwar auch in der Basis der Webseite auf PHP verzichten und via JavaScript Befehle an eine separate PHP leiten welches wiederum das C++ Programm bedient, aber über wie viele Ecken will man denn noch einbauen? :s Jede Ecke ist eine mögliche Fehlerquelle und eine zusätzliche Verzögerung. Man sollte also über so wenig wie möglich Ecken gehen um ans Ziel zu gelangen... Den kürzesten Weg, nicht den Bequemsten.

    Genau so wie es für Python Web-Frameworks gibt gibts das auch für C++, wie zB Wt. Wenn er also unbedingt bei C++ bleiben und sich weiterentwickeln möchte dann wäre es IMHO das Sinnvollste das Web-Interface direkt in sein C++ einzubetten.
    Alternativ benötigt er WebSocket in seinem C++ Programm und muss das als Daemon auslegen also permanent laufen lassen.. Oder er schreibt die Befehle in eine FIFO Datei und lässt sein C++ Programm diese Datei auslesen...
    Alle anderen Möglichkeiten fügen nur unnötig weitere Ecken mit ein...


  • Naja also das erste was Er klären müsste wäre ob er wirklich PHP nutzen will.
    Wenn er seine Webseite auf Basis von PHP ausgebaut hat ist eben der Nachteil das bei jedem Absenden eines Befehls die komplette Seite neu geladen wird. Man könnte zwar auch in der Basis der Webseite auf PHP verzichten und via JavaScript Befehle an eine separate PHP leiten welches wiederum das C++ Programm bedient, aber über wie viele Ecken will man denn noch einbauen?

    IMHO wäre das schon noch praktikabel, da die Javascript- und PHP-Anteile überschaubar bleiben.

    Javascript:

    Code
    function runScript(name) {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "runit.php?path="+path, true);
        xhttp.send();
    }


    /var/www/html/runit.php:

    PHP
    <?php
        $file = $_GET["path"];
        exec("sudo ./".$file);
    ?>

    /etc/sudoers:

    Code
    www-data     ALL = NOPASSWD: /var/www/html/meinscript

    Dein html:

    Code
    <button onclick="runScript('vorwaerts');">Vorwärts</button>
    <button onclick="runScript('rueckwaerts');">Rückwärts</button>

    Im Ordner /var/www/html brauchst du dann deine C-Programme mit den Namen vorwaerts, rueckwaerts...

    Die Beispiele hier sind alle aus dem Kopf geschrieben und nicht getestet, müssen nicht funktionieren.

    Einmal editiert, zuletzt von WitheredMud39507 (23. Mai 2016 um 11:24)

  • @ DiHydrogenOxide: Genau so etwas hatte ich mir vorgestellt. Weil so kann ich in meiner gewohnten C-Umgebung bleiben (wo ich mich mittlerweile ganz gut zu recht finde) und trotzdem alles per Website aufrufen.
    Gibt es da weitere Quellen zu, wo ich mehr finde? Weil ich habe nach genau solchen Dingen gesucht, aber nie wirklich so etwas gefunden wie du jetzt hier schreibst.

    @ Rest: Euch natürlich auch vielen Dank.

    Gruße,
    Timmi

    Einmal editiert, zuletzt von Timmi (23. Mai 2016 um 11:42)

  • Ach du liebe Guete. Mit dem Code reisst du eine scheunentorgrosse Sicherheitsluecke. Da uebergebe ich fuer $file einfach mal mal "../../../bin/rm -rf /" - und dann ist der PI platt. Und wenn nicht beim ersten mal, dann rate ich mal ein bisschen rum wieviele ../ ich einfuegen muss....

    Und ausserdem loesst es nicht wirklich das Problem. Denn die Steuerung eines Roboters/Autos muss *permanent* laufen. Das tut sie aber in diesem Fall nicht - jedes der Programme die du aufrufst kann nur kurz laufen, die GPIOs irgendwie setzen, und dann muss es sich beenden. Damit hast du aber keine Kontrolle ueber das Fahrzeug, insbesondere nicht, wenn du auf Sensoren zusaetzlich reagieren musst/willst.

    Ich habe so ein Browser-gesteuerten Roboter schon mal gebaut (mit Python, aber das spielt keine Rolle fuer eine Betrachtung hier).

    Das Hauptprogramm sieht etwa so aus:

    Code
    zeitstempel = jetzt()
    while True:
           if neues_commando: 
                neues_commando.ausfuehren()
                zeitstempel = jetzt()
           else if jetzt() - zeitstempel > 1sekunde:
                notstop()

    Im Fall von zB Kollisionssensoeren wuerde man das natuerlich entsprechend aufbohren. Der Punkt aber ist: es muss bestaendig Kontrolle ausgeuebt werden.

    Und der oben stehende Code hat noch ein Problem: du startest ein Programm. Das setzt die GPIOs. Wenn du jetzt aber schnell hintereinander auf einen Knopf drueckst, startest du zwei Programme gleichzeitig - mit unvorhersehbarem Ergebnis.

    Lange Rede, kurzer Sinn: eine wirkliche Loesung ist das nicht. Es erfuellt halt nur "irgendwie ein Programm aus PHP aufrufen"...

  • Die Sicherheitslücke im Bezug auf den User www-data habe ich häufiger gelesen. Sehe ich aber nicht als problematisch da ich den PI nur eigenständig betreibe und er keinen Zugang zum Internet hat.

    Wie hast du das denn bei dir gemacht? Womit stellst du die Verbindung zwischen Browser und GPIO her? PHP und Python? Oder nur Python? Ich kenne mich da leider nicht so gut aus.

  • Meine Situation ist noch eine Spur komplizierter, weil ich eine Loesung wollte, die einen Roboter in einem WLAN von einem WLAN einige tausend Kilometer entfernt steuern laesst. Dadurch brauche ich eine Architektur bei der sowohl Roboter als auch Browser jeweils auf einen Server zugreifen, der die Nachrichten des einen als auch des anderen weiterleitet. Und alles ist in Python geschrieben. Webserver, Roboter-Controller. Der Browser-Code ist natuerlich JavaScript, da hat man keine Wahl.

    Letztlich ist das aber nicht so gross anders als bei dir: ich habe einen Controller auf dem Roboter laufen, der genau die Struktur hat, wie ich sie oben beschrieben habe:

    https://github.com/deets/jetbot-3…rcontrol.py#L37

    In einer Schleife warte ich auf neue Kommandos, wenn diese nich innerhalb einer gewissen Zeit eintreffen, erzeuge ich ein kuenstliches Stop-Kommando.

    Und die Kommandos werden dann einfach abgearbeitet.

    Dann gibt es einen Webserver, der mit Javascript im Browser Tastendruecke auswertet. Wenn eine Taste gedrueckt wird, faengt der Browser an, Nachrichten zu schicken - zB "forward" - und wiederholt diese auch periodisch, um eben nicht die "nichts gekommen, dann Stopp"-Logik auszuloesen.

    Fuer deinen Fall koennte man theoretisch problemlos einen Webserver und den Controller in einer Anwendung gleichzeitig betreiben, jeweils in einem eigenen Ausfuehrungsthread.

    Aber das ist in C bzw. C++ so eine Sache... ich wuerde das nicht machen. Ich wuerde stattdessen einen Controller in C++ schreiben, wie ich ihn oben in Python geschrieben habe. Und mit den message-queue Aufrufen in http://man7.org/linux/man-pages/man3/mq_receive.3.html auf eine eingehende Nachricht warten. Mit Timeout.

    Und dann wuerde ich halt in PHP einen Webserver schreiben der halt vom Browser per Javascript geschickte Nachrichten einfach in die Message-Queu stopft.

    Zum Schluss sei mir eine Bemerkung gestattet: ich halte deine Entscheidung an C festhalten zu wollen fuer schwierig. Dir fehlt offensichtlich viel Erfahrung im Programmieren. Nun ist das Problem "Roboter steuern ueber den Browser" grundsaetztlich ambitioniert. Aber vertrau mir wenn ich dir sage: es *braucht* kein C (ich hab's ja in Python gemacht), aber C wird dir das Leben im Gegensatz zu Python *sehr*, *sehr*, *sehr* (und jetzt muessten noch ein paar sehr kommen...) viel schwerer machen. Du solltest das wirklich gut ueberlegen - weil frustriert aufzugeben nicht schoen ist.

  • Vielen Dank für die ausführlichen Erläuterungen dazu. Ich entnehme dem ganzen das ich besser auf Python umschwenke, anstatt später frustfrei aufzugeben. Und wie du schon selbst erkannst hast sind meine Programmierkenntnisse noch nicht so ausgereift. Da stimme ich dir zu.

    Ich würde mich einfach erstmal mit Python etc. auseinander setzen und ggf. zu einem späteren Zeitpunkt noch einmal melden :-).

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!