Ok
Dank dir schon mal für die Mühe!
Ok
Dank dir schon mal für die Mühe!
Schaut ruhig mal auf meiner Homepage vorbei:
http://kampis-elektroecke.de
Oder folge mir auf Google+:
Daniel Kampert
Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.
Gruß
Daniel
So, ich habe mal in der php.ini die Fehleranzeige eingeschaltet. Da kommt dann bei meinem Senden-Programm, die Meldung, dass er /dev/ttyAMA0 nicht öffnen kann. Über echo kommt keine Fehlermeldung. Leider komm ich grad nicht weiter, da meine 2GB Karte voll ist. Ich muss erstmal das Backup von gestern zurückspielen und dann gibt es Essen. Die Probleme hatte ich alle mit dem Apache nicht...
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Hey,
danke fuer die Muehe.......wie hast du dir den Fehler anzeigen lassen?
Per PHP ueber den Shell_exec Befehl oder hast du das via C Programm getestet?
Aber die Erkenntnis bestaetigt meine Theorie, dass es sich um ein Rechteproblem handelt.
Nur die Frage ist....wie stelle ich es um.
Was sagt den dein Bauchgefuehl? Hat man mit Apache weniger Probleme als mit Lighttpd?
Weil Performancetechnisch ist das Raspberry Pi durch die Raspian Distribution ja recht gut dabei, sodass ich denke das da Apache nicht so ins Gewicht schlagen sollte.......
Schaut ruhig mal auf meiner Homepage vorbei:
http://kampis-elektroecke.de
Oder folge mir auf Google+:
Daniel Kampert
Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.
Gruß
Daniel
Der Fehler wird mir auf dem WebIf angezeigt, da ich $output einfach noch mit einblende.
Was mich stört ist, dass ich als user root arbeite. Es wird mir auch root als php-Benutzer angezeigt. Ich deinstalliere gerade php und danach lighthttp um dann (ab morgen) den apache zu testen.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
So, Apache hat auch nicht geholfen.
Ich nutze jetzt das senden Programm, welches per sudo aufgerufen wird. Dazu muss noch die Passwortabfrage deaktiviert werden.
Also Befehlin die Konsole eingebenCode:visudo
Dort dann die Zeile
am Ende einfügen.Code:www-data ALL=(ALL) NOPASSWD: /var/scripte/senden
Jetzt wird für das eine Senden Programm kein Kennwort bei sudo verlangt.
Meine Webseite zum Testen:
Mein Senden Programm:Code:<html> <head> <title>Raspberry Pi PHP- Server - UART Test</title> </head> <body> <h1>Raspberry Pi PHP- Server - UART Test</h1> <div id="nav"><a href="index.php?safemode=1">Safemode?</a> <a href="index.php">Neu laden</a></div> <div id="main"><h2>RasPi-Sendetest<h2><br> <?php header("Cache-Control: no-cache, must-revalidate"); echo "<br>"; echo "Befehl eingeben"; echo "<br>"; if (isset($_GET["safemode"])) { if( ini_get('safe_mode') ){ echo "<br>Safemode an<br>"; }else{ echo "<br>Safemode aus<br>"; } }; if (isset($_POST["befehl"])) { if ($_POST["befehl"]!=""){ $befehl="sudo /var/scripte/senden ".$_POST["befehl"]; $output = shell_exec($befehl); } }; echo "<form method='post' action='index.php'>"; echo "<input type='text' maxlength='40' size='40' id='1' name='befehl' value='HalloWelt' />"; echo "<br>"; echo ".$output" ?> <input type="submit" value="Senden"> </form> </div> </body>
Code:// Compile with: GCC /var/scripte/senden.c -o /var/scripte/senden //#include <iostream> //using namespace std; #include <sys/types.h> //nicht benötigtes scheint keinen Platz zu verschwenden... #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #define BAUDRATE B19200 char MODEMDEVICE[]= "/dev/ttyAMA0"; // !!! int fd; // File descriptor struct termios newtio={}; unsigned char send(char c) { int res=write(fd, &c, 1); if (res<0) printf("Fehler beim Senden\n"); return res; } int init() { /*** Init ***/ //O_RDONLY, O_WRONLY or O_RDWR - //O_NDELAY (geht weiter, wenn keine Daten da sind und gibt "-1" zurueck) // man 2 open fuer mehr Infos - see "man 2 open" for more info // O_NOCTTY No ControllTeleType fd = open(MODEMDEVICE, O_WRONLY | O_NOCTTY); if (fd < 0){ printf("Fehler beim oeffnen von %s\n", MODEMDEVICE); exit(-1); } memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; //setzt die neuen Porteinstellungen newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; /* set input mode (non-canonical, no echo, ...) */ newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 1; /* blocking read until 1 chars received */ tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &newtio); return fd; } int einmal() { int i=0; int anzahl=0; int laenge=0; char *ptr; FILE *in; extern FILE *popen(); char buff[30]; char rueckgabe[30]=""; if(!(in = popen("pidof senden", "r"))){ exit(1); } fgets(buff, sizeof(buff), in); pclose(in); laenge=strlen(buff); for(i=0;i<laenge;i++) { if(buff[i]==' ') anzahl++; } return anzahl; } int main(int argc, char** argv) { char c; char vBuf[100]="",*pBuf; char buffer [100]=""; char buffer1 [100]=""; int i=0; int anzahl; anzahl=einmal(); if (anzahl>0){ anzahl++; sleep(anzahl); } init(); if (argc == 1) { //Wenn nichts angegeben, dann Uhrzeit und Datum senden time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (buffer,80,"U%H:%M:%S",timeinfo); //Uhh:mm:ss pBuf=buffer; strcat(pBuf,"\r"); while(pBuf && *pBuf) //Zeichen einzeln senden send(*pBuf++); strftime (buffer,80,"D%d.%m.%y",timeinfo); //Dtt.mm.yy pBuf=buffer; strcat(pBuf,"\r"); sleep(1); while(pBuf && *pBuf) //Zeichen einzeln senden send(*pBuf++); }else{ //Sonst Parameter einlesen und senden if(strlen(argv[1])>75){ //Puffer im AVR ist auf 80 gestellt strncpy(buffer,argv[1],76); buffer[76]='\0'; }else{ strcpy(buffer,argv[1]); if (argc >2){ for (i=2;i<argc;i++){ if(strlen(buffer)+strlen(argv[i])>75){ strcat(buffer," "); strncat(buffer,argv[i],(76-strlen(buffer))); buffer[76]='\0'; break; //exit for in c... }else{ strcat(buffer," "); strcat(buffer,argv[i]); } } } } int o=0; for(i=0;i<strlen(buffer);i++){ buffer1[o]=buffer[i]; if (buffer1[o]==164){ //ä buffer1[o]= 228; } if (buffer1[o]==188){ //ü buffer1[o]= 252; } if (buffer1[o]==182){ //ö buffer1[o]= 246; } if (buffer1[o]==132){ //Ä buffer1[o]= 196; } if (buffer1[o]==156){ //Ü buffer1[o]= 220; } if (buffer1[o]==150){ //Ö buffer1[o]= 214; } if (buffer1[o]==159){ //ß buffer1[o]= 223; } if (buffer1[o]==138){ //& buffer1[o]= 38; } if (buffer1[o] != 195){ //Initialisierung Umlaut o++; } } pBuf=buffer1; strcat(pBuf,"\r"); //CHR(13) anfügen, damit der AVR auswertet while(pBuf && *pBuf){ //Zeichen einzeln senden send(*pBuf++); } } close (fd); return 0; }
Geändert von peterfido (13.09.2012 um 16:44 Uhr)
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Danke für die Tipps.
Ich schaue es mir mal an.
Wie funktioniert das mit dem C Programm?
Ist das ein Programm was nur 1x ausgeführt wird wenn man auf nen Button drückt oder wie muss ich das verstehen?
Bzw. kannst du mir ein bischen näher erklären wie ich die Interaktionen in einem Webinterface mit einem C-Programm koppeln kann, so das über das Webinterface Daten an ein C-Programm gegeben werden?
Schaut ruhig mal auf meiner Homepage vorbei:
http://kampis-elektroecke.de
Oder folge mir auf Google+:
Daniel Kampert
Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.
Gruß
Daniel
Das hier vorgestellte sendet das, was als Parameter übergeben wurde, an die UART und wird dann gleich wieder beendet. Wird es nur so, also ohne Parameter aufgerufen, sendet es die Uhrzeit mit einem U voran, sowie eine Sekunde später das Datum mit einem D voran. Ansonsten werden Umlaute noch angepasst und als letztes ein CR gesendet.
Das funktioniert bei mir sehr zuverlässig. Einige Strings müssen in Häkchen gesetzt werden, da sonst bestimmt Zeichen einen Strich durch die Rechnung machen. Aufgefallen sind mir da die Klammern und das Kaufmannsund.
Darüber hinaus prüft es noch, ob es bereits läuft und macht pro bereits laufende Instanz eine Sekunde Pause. So wird verhindert, dass mehrere Strings durcheinander gemischt werden und nur Murks ankommt.
Ich habe mein Protokoll darauf hin aufgebaut, dass das erste Zeichen angibt, was da jetzt kommt. U für Uhrzeit, D für Datum R für Radiosender I für Interpret, T für Titel, S für Anzahl der Titel in der Senderliste, C für aktuelle Position in der Liste und V für aktuelle Lautstärke. Alles bis auf U und D übernimmt aber ein anderes Programm, welches über das "senden" Programm Informationen zum AVR schickt.
Der Rückkanal AVR>>Raspi erfolgt über ein anderes Programm, welches ständig im Hintergrund läuft. Immer, wenn Daten über UART eintreffen, werden diese dann von diesem Programm ausgewertet und entsprechend gehandelt. Da musste ich allerdings das Protokoll ertwas erweitern: Seit ich eine definiertes Zeichen als Indiz für einen neuen Datensatz nutze, läuft es fehlerfrei durch. Ohne dieses Zeichen musste ich hin und wieder einen Befehl doppelt senden.
Meine Experimente, wo nur ein Programm in beide Richtungen agiert, waren zwar auch erfolgreich, jedoch stieg durch die ständige Loop die Prozessorlast teilweise auf über 30% nur für das Programm an, was ich nicht wollte. Mit den 3 Programmen bin ich so gut wie immer im einstelligen Prozentbereich für diese. Das 3. Programm überwacht alle 2 Sekunden den Status des MPD und schläft dazwischen immer. Nur bei Änderungen werden Informationen über "senden" an den AVR gemeldet. Ansonsten prüft es auch noch per pidof, ob das Empfänger Programm noch läuft und startet es, wenn es dieses nicht findet. Umgekehrt prüft das Empfänger Programm auch den Status des Überwachers, wenn eine Zeichenkette eingetroffen ist (Also nach dem chr(13)). Das gegenseitige Überwachen kommt aber im nächsten Step raus und wird per Cronjob minütlich durch ein Programm namens Wachhund übernommen. Das ist auch schon fertig und überwacht dann zusätzlich noch den MPD.
Ich kann auch über den AVR alle aktuellen Werte anfordern, was in der Testphase von Vorteil ist, wenn der AVR neu startet, der Raspi aber durchläuft. Dazu sendet er ein bestimmtes Zeichen (CHR(). Das erkennt der Empfänger und beendet den MPD Überwacher und startet ihn darauf neu, was zur Folge hat, dass alle aktuellen Werte zum AVR geschickt werden.
Um eine Kommunikation mit einem Programm per php zu realisieren, gibt es mehrere Möglichkeiten. Ich würde ein Programm mit Parametern aufrufen und für den Rückkanahl die Ausgabe auswerten. Dieses müsste dann im Beispiel im $output ankommen. Wie es bei Leerzeichen und anderen Zeichen, wie die oben erwähnten Klammern, sowie & reagiert, habe ich noch nicht getestet. Kann ich aber mal eben schnell probieren. Dazu melde ich mich später nochmal.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Lesezeichen