Redfly - PHP Request starten

Hi Marcus (und alle anderen die mitlesen),
also ich habe den Sketch jetzt mehr oder weniger fertig, damit einmalig ein Eintrag in die DB vorgenommen wird. Das Problem was sich bei mir ergibt ist, dass ich fast jedes mal den Router neustarten muss und auch das Arduino-Bord damit eine Verbindung statt findet. Damit ich den Test einer Sketch-Änderung jedoch testen kann benötige ich jedes mal ein Update, jedoch verbindet sich das Shield dann nicht mehr. Kann ich das Problem irgendwie umgehen/beheben?

mfg
Balli

hier der Stand des Sketches:

#include <RedFly.h>

// IP Einstellungen
byte ip[]        = { 192,168,  1,138 }; // IP Adresse des Shields
byte netmask[]   = { 255,255,255,  0 }; // Subnetzmaske
byte gateway[]   = { 192,168,  1,  1 }; // Gateway IP
byte dnsserver[] = { 192,168,  1,  1 }; // DNS-Server IP



byte serverIP[] = {0,0,0,0}; // früher mal server[] - ich hab spaßhalber mal Nullen eingesetzt, da ich hoffe dass es nach dem Aufruf von getip() überschrieben wird.

#define HOSTNAME "hemitheconyx-caudicinctus.de"  // Hostname zu dem verbunden werden soll



uint8_t http=0xFF;   //socket handle, HTTP-Fehler
uint16_t http_len=0; //receive len
char http_buf[512];  //Receive-Buffer

//serial format: 9600 Baud, 8N2
void debugout(char *s)  { RedFly.disable(); Serial.print(s);   RedFly.enable(); }
void debugoutln(char *s){ RedFly.disable(); Serial.println(s); RedFly.enable(); }

void setup()
{
  uint8_t ret;
  ret = RedFly.init(); // Redfly initialisieren
  if(ret) // Falls Redfly einen Fehler verursacht, bekommt "ret" einen Rückgabewert
  {
    debugoutln("INIT ERR"); //there are problems with the communication between the Arduino and the RedFly
  }
  
  else
  {
    //Nach Netzwerken scannen
    RedFly.scan();

    //dem Netzwerk beitreten
    ret = RedFly.join("RedFly", "1*******", INFRASTRUCTURE);
	
    if(ret)
    {
      debugoutln("JOIN ERR");
      for(;;); //do nothing forevermore
    }
    else
    {
	  // Redfly IP-Konfiguration einstellen, begin(1) benutzt DHCP, andernfalls die jeweilige Konfiguration	
      ret = RedFly.begin(ip, dnsserver, gateway, netmask);
	  
      if(ret) // Eventuellen Fehler abfangen
      {
        debugoutln("BEGIN ERR");
        RedFly.disconnect();
        for(;;); //Endlosschleife
      }
      else
      {
        if(RedFly.getip(HOSTNAME, serverIP) == 0) //DNSname von HOSTNAME auflösen und in serverIP speichern,
        {
          http = RedFly.socketConnect(PROTO_TCP, serverIP, 80); // Verbindung zum Server per IP aufbauen
          if(http == 0xFF)
          {
            debugoutln("SOCKET ERR");
            RedFly.disconnect();
            for(;;); //do nothing forevermore
          }
          else
          {
            //HTTP Request senden...
            RedFly.socketSendPGM(http, PSTR("GET http://"HOSTNAME"/php/db.php?passwort=******* HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));
          }
        }
        else
        {
          debugoutln("DNS ERR");
          RedFly.disconnect();
          for(;;); //do nothing forevermore
        }
      }
    }
  }
}


void loop()
{
  uint8_t sock, buf[32];
  uint16_t rd, len;
  Serial.println("Ausgabe");
  if(http == 0xFF) //no socket open
  {
    return;
  }

  sock = 0xFF; //0xFF = return data from all open sockets
  rd = RedFly.socketRead(&sock, &len, buf, sizeof(buf));
  if(sock == http)
  {
    if((rd != 0) && (rd != 0xFFFF))
    {
      if((http_len+rd) > sizeof(http_buf))
      {
        rd = sizeof(http_buf)-http_len;
      }
      memcpy(&http_buf[http_len], buf, rd);
      http_len += rd;
    }

    if((rd == 0xFFFF) || (len == 0)) //connection closed or all data received
    {
      //close connection
      RedFly.socketClose(sock);

      //show http buffer
      http_buf[sizeof(http_buf)-1] = 0;
      debugout(http_buf);
    }
  }
}

Ohne genauer geschaut zu haben vermute ich mal, das Dein Problem darin begründet liegt, das Du die HTTP-Versbindung im setup() aufbaust, das aber nur einmal nach einem Start des Arduino (oder Reset) abgearbeitet wird. Danach behandelst Du einmalig die evtl. vorhandene HTTP-Verbindung in loop() und danach geht die loop() in den Leerlauf auf alle Ewigkeit. Beschreib doch mal bitte, was Du genau machen willst und über was die HTTP-Requests angestossen werden.

und btw: Bitte übergib keine Passwörter zur datenbank per GET, sondern per POST-Request:

RedFly.socketSendPGM(http, PSTR("POST /php/db.php HTTP/1.1\r\n Host: "HOSTNAME"\r\npasswort=******\r\n"

Sonst machst du deine Datenbank extrem angreifbar. Der GET-Request war nur zum testen ob es überhaupt funktioniert.

letztendlich möchte ich eine Verbindung zum Internet aufbauen (Test, wenn keine Verbindung, dann Verbinde), wenn eine Verbindung besteht führe http-request aus. Nur habe ich das Gefühl das die Verbindung nicht wirklich aufgebaut wird.
mfg
balli
das passwort für diese db ist nicht so von interesse,aber ich ändere das eben mal fix

Okay, die Verbindung zum WLAN kann ich jetzt immer herstellen, das liegt am DHCP des ROuters, ich dachte ich kann das deaktivieren-Pustekuchen-kann ich nicht ernstzunehmend abstellen, daher muss es heissen:

ret = RedFly.begin(1);

Hi Forum,
leider muss ich euch mit trivialen Fragen nerven, aber ich finde mich einfach mit den API-Beschreibungen noch nicht so zu recht wie ich mir das selbst wünsche (war leider sehr naiv in der Vorstellung die Programmiersprache ist bestimmt ähnlich einfach wie java und co).
Drum hier meine Frage:

RedFly.socketSendPGM(http, PSTR("GET http://"HOSTNAME"/php/db2.php?wert=5050 HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));

Anstelle von 5050 möchte ich jetzt einen Zahlenwert verschicken, der vorher in einer Variablen festgeschrieben wurde.
Wie stelle ich das an mit:

RedFly.socketSendPGM(http, PSTR("GET http://"HOSTNAME"/php/db2.php?wert="wert" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));
RedFly.socketSendPGM(http, PSTR("GET http://"HOSTNAME"/php/db2.php?wert="+wert+" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));

und ähnlichen Konstruktionen hatte ich keinen Erfolg.
mfg
balli

Es gibt keine trivialen Fragen - nur triviale Lösungen :smiley:

RedFly.socketSendPGM(http, PSTR("GET /php/db2.php?wert="+wert+" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));

müsste eigentlich funktionieren...

EDIT: natürlich nur, wenn die Variable Wert ein String ist, wenn nicht musst du den integer(?)-wert z.B. mit itoa() oder sprintf in den String einfügen.

EDIT 2: Code nachgereicht - allerdings blind

char wertbuffer[5]; // maximal 5 stellen, also 99999
sprintf(wertbuffer, "%d", wert); 

RedFly.socketSendPGM(http, PSTR("GET /php/db2.php?wert="+ wertbuffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));

RedFly.socketSendPGM(http, PSTR("GET /php/db2.php?wert="+ wertbuffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));

Das funktioniert nicht - PGM/PSTR steht für Daten im Flash. Beim AVR-Mikrocontroller muss man zwischen den Speicherbereichen (Flash/RAM) unterscheiden.

Schaut euch mal das WebClient und WebServer Beispiel an. Diese benutzen die vereinfachten Client/Server Klassen, die sehr ähnlich wie die original Klassen des Arduino Ethernet Shields sind.

Bei Debugausgaben auf der seriellen Schnittstelle (z.B. über Serial.println()) muss das RedFly-Shield immer erst deaktiviert werden. Daher auch die debugout() Funktionen in den Beispielen.

Gruß
Andreas

Ahhhh! Erleuchtung, danke Andreas. Deshalb also funktioniert die Übergabe der Konstante HOSTNAME, die ja nur Defined wird und mit einer Variable nix gemein hat, und eine normale Variable nicht...

EDIT:
Was passiert also, wenn man statt

RedFly.socketSendPGM(http, PSTR("GET /php/db2.php?wert="+ wertbuffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n"));
RedFly.socketSend(http, "GET /php/db2.php?wert="+ wertbuffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n");

benutzt?

Weil Werte die mittels "define" definiert werden VOR dem eigentlichen compilieren durch den Präprozessor ersetzt werden. Das ist eine reine Textersetzung, die schon im Quellcode stattfindet. Daher bekommt der Compiler am Ende nur einen einzigen String.

Leider Funktioniert die Variante auch nicht, das Umwandeln in ein String /Char Funktioniert, jedoch sagt er mir dennoch folgenden Fehler:

wlan.cpp: In function 'void loop()':
wlan:107: error: invalid operands of types 'const char [23]' and 'char [5]' to binary 'operator+'

wenn ich dieses tue (beide varianten der gleiche Fehler):

 cm = microsecondsToCentimeters(duration);
  itoa(cm,buffer,10);
  char wertbuffer[5]; // maximal 5 stellen, also 99999
  sprintf(wertbuffer, "%d", 5); 
  
  RedFly.socketSend(http, "GET /php/db2.php?wert="+ wertbuffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n");
//RedFly.socketSend(http, "GET /php/db2.php?wert="+ buffer +" HTTP/1.1\r\nHost: "HOSTNAME"\r\n\r\n");

vielen dank für eure Geduld.

Hallo Forum,
leider gottes muss ich euch mit diesem Thema weiter aufn leim gehen. Es gelingt mir einfach nicht dynamischen Inhalt in den Request einzufügen. Beim einfach Redfly Client-Beispiel(ohne Socket) stellt das Board gar keine Verbindung her, wobei in der Analyse nicht einmal das Passwort übergeben wird!daher kann ich mit den Beispielen von Andreas leider nicht viel anfangen.
mfg und abermals tausend Dank
balli

Hi @all,Hi Andreas W.,
leider habe ich bis dato auch mit sämtlichen Versionen des WebClients (den ich in der Example-Version immer noch nicht zum laufen bekomme(das Passwort und die SSID werden nicht übertragen)) getestet und versucht, ich bekomme aber leider keine Daten dynamisch übermittelt.
Kann mir jemand vielleicht ein anderes Beispiel oder Tutorial zeigen?
mfg
Balli

C-Strings kann man nicht so einfach addieren, das ist Dein Problem. Du kannst aber eine Instanz der Klasse "String" verwenden, um die Teile zusammen zu sezten und dann daraus wieder einen C-String machen. Oder, wenn Du eh schon sprintf verwendest, gleich den ganzen String so erzeugen:

  char wertbuffer[100]; //Puffer groß genug wählen 
  sprintf(wertbuffer, "GET /php/db2.php?wert=%d HTTP/1.1\r\nHost: %s\r\n\r\n", 5, HOSTNAME); 
  
  RedFly.socketSend(http, (char*) &wertbuffer);

Achtung, ist ungetestet. Sollte vom Ansatz aber korrekt sein.

Danke mkl für deine Antwort,
aber magst du mir das Ganze einmal erklären.
Ich habe es einmal versucht:

char wertbuffer[100]; //Puffer groß genug wählen -Ball: "Der String der Abschließend gesendet wird"
  sprintf(wertbuffer, "GET /php/db2.php?wert=%d HTTP/1.1\r\nHost: %s\r\n\r\n", 5, HOSTNAME); //Balli:"String wird an Buffer übergeben, das%d dient als Platzhalter und wird durch die 5 ersetzt"
  
  RedFly.socketSend(http, (char*) &wertbuffer); //Balli: Senden des entsprechenden Get-Befehls

mfg
balli

Gibt es denn Fehler vom Compiler, oder funktioniert es einfach nicht?

char wertbuffer[100];

Das definiert einfach einen 100 Byte großen Puffer, der den String aufnehmen soll. Also ein char[100] Array.

sprintf(wertbuffer, "GET /php/db2.php?wert=%d HTTP/1.1\r\nHost: %s\r\n\r\n", 5, HOSTNAME);

Schreibt den kompletten String in den Puffer, wobei die Platzhalter %d und %s durch die übergebenen Werte ersetzt werden.

RedFly.socketSend(http, (char*) &wertbuffer); //Balli: Senden des entsprechenden Get-Befehls

Sollte auch als

RedFly.socketSend(http, wertbuffer); //Balli: Senden des entsprechenden Get-Befehls

funktionieren. Das (char*) &wertbuffer hatte ich eher als Verdeutlichung verwendet was gemacht wird. Ich vermute mal, das RedFly.socketSend() einen C-String, also char* als Parameter erwartet. Das "&" Sorgt dafür, das nicht der Wert von "wertbuffer", sondern dessen Adresse im Speicher als Parameter verwendet wird. Also der Zeiger auf das Array. Allerdings ist das vom Typ "char[100]" nicht vom Typ "char", daher wird es auf den passenden Typ "gecasted".
Mario.

Hi Mario,
es scheint tadellos zu funktionieren. Nur je nach Geschwindigkeit kommt mein MySQL nicht hinterher (aber das war zu erwarten).
Ich danke euch allen!
Jetzt noch Daten lesen und dann kann ich dazu auch mal nen Tutorial schreiben, dann muss sich nicht jeder diesen Thread durchlesen.

mfg
Balli