Pages: [1]   Go Down
Author Topic: Arduino als HTTP Client - Daten auslesen  (Read 1688 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo!
Folgendes Problem: Mein Arduino ruft über HTTP eine Seite auf:
Code:
GET /alarm/ardu/?i=5 HTTP/1.0

Die Variable "i=5" wird dynamisch generiert. Dort bekommt er als Antwort z.B. folgendes zurück:
Code:
HTTP/1.0 200 OK
Vary: Cookie
Content-Type: text/html; charset=utf-8
Set-Cookie: csrftoken=219fc26c9243f30f57807b2b73b5c86e; expires=Thu, 17-Jan-2013 09:43:25 GMT; Max-Age=31449600; Path=/
Connection: close
Date: Thu, 19 Jan 2012 09:43:25 GMT
Server: lighttpd/1.4.28

63
Mich interessiert nur die letzte Zahl. In diesen Fall 63. Die Zahl kann von 0-255 gehen. Wie bekomme ich diese Zahl in eine Variable gespeichert? Den String könnte ich dann ja so umwandeln:
Code:
int ausgabe = readString.toInt();

MfG
senden9
Logged

Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Aus dem Kopf würde ich sagen etwa so smiley

int ausgabe = atoi(antwort.substring((antwort.indexOf("\n\n") + 1));

Dabei setze ich voraus, dass die Antwort des Servers (Variable "antwort") als String-Objekt vorliegt. Ich hoffe, dass die beiden Zeilenumbrüche mit "\n\n" erkannt werden, wenn nicht probier mal "\r\n\r\n". Das "+1" musst Du evtl. auch ändern. substring gibt den String einschließlich des Zeichens an der index-Position zurück, wenn "\r\n\r\n" funktioniert, wirst Du die +1 ändern müssen.
« Last Edit: January 19, 2012, 05:55:39 am by nachtaktiv68 » Logged

twitter: @darktom

Weinsberg, Germany
Offline Offline
God Member
*****
Karma: 3
Posts: 773
A Coder's Tale
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Alternativ könntest Du die Ausgabe des Servers so lange Zeichen für Zeichen durchgehen bis Du einen Zeilenumbruch gefolgt von Zahlen gefolgt von einem Zeilenumbruch findest.

Dann würdes Du mit einem 3 Byte grossen char-Array auskommen (bzw. wieviele Nummern Deine Zahl maximal haben kann plus eins) statt (in aktuellen Fall) mindestens 277 Bytes für die String-Variable zu verbraten...

Speicher ist kostbar! smiley-wink
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, ich habe mich gerade am Vorschlag von Jogurt versucht. Es berietet mit Kopfzerbrechen. Hier mein Code:
Code:
int CR = 0;
int LF = 0;
unsigned int http_counter = 0;
unsigned int cr_http_counter = 0;


while(client.connected()){
    if (client.available()) {
      char c = client.read();
      if (c == 13){
        CR ++ ; //ascii Carriage Return
        cr_http_counter = http_counter;
      }
      if (c == 10 & CR & (http_counter == (cr_http_counter + 1))){
        LF ++ ; //ascii Carriage Return
      }
      http_counter ++;
    }
  }
Ich muss irgendwie Abfragen ob 2x die Sequenz CR LF kommt. Bin ich auf dem richtigen Weg? Wie gesagt es bereitet mir Kopfzerbrechen.
Logged

Weinsberg, Germany
Offline Offline
God Member
*****
Karma: 3
Posts: 773
A Coder's Tale
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Also wenn Du wirklich sicher bis dass nur und ausschließlich eine Zahl als Nutzdatum zurück kommt und Du auch nicht mehr brauchst, dann würde ich was in der Richtung ansetzen:
Code:
// Max. Anzahl an Zahlen! 6->1, 68->2, 680->3 etc...
#define MAXLEN 2

char buffer[MAXLEN+1];
byte bufferpos = 0;
boolean invalid = false; // Falsche Zeichen in der Zeile?
long retval = -1; // Nix...

void loop() {
  while (client.connected() && retval == -1) {
    if (client.available()) {
      char c = client.read();
      if (c>='0' && c<='9' && !invalid) { // zwischen 0 und 9, also eine Zahl, und sonst nix in der Zeile
        if (bufferpos>MAXLEN) {
          Serial.println("ZU LANGE!!!"); // Zu klein dimensionierter Puffer!
          invalid = true;
        } else
          buffer[bufferpos++] = c; // Zahl merken, dann zur naechsten Speicherzelle weitergehen
      } else if (c == '\r' || c == '\n') { // CR oder LF
        buffer[bufferpos] = '\0'; // "Ganz hinten" Stringende markieren
        if (bufferpos > 0) // In der letzten Zeile waren Zahlen, also NICHT zuruecksetzen!
          retval = atoi(buffer);
        invalid = false;
      } else {
        bufferpos = 0; // Keine Zahl, also Speicher an den Anfang zuruecksetzen!
        invalid = true; // Irgendwas anderes, ein Buchstabe oder ein Sonderzeichen oder so...
      }
    }
  }
  if (retval != -1){
    // Zahl gefunde, also jetzt was damit machen...
  }
  bufferpos = 0; // Klar zum naechsten Durchgang...
  invalid = false;
  retval = -1;
}
Ist aber nicht getestet, daher ohne Gewähr... smiley-wink
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo, sorry das ich erst jetzt wieder antworte.
Leider klappt der Code nicht. Der retval bleibt -1. Laut Serial.write(c); wird die HTML Seite korrekt übertragen. nur an der Auswertung scheitert es.
Ich hier der zuständige Code:
Code:
void webserver(){
  if (client.connect()) {
    Serial.println("connected");
    client.print("GET ");
    client.print(webpraefix);
    client.print("?i=");
    client.print(expanderRead(expander1),DEC);
    client.print(" HTTP/1.0\r\n\r\n");
    Serial.print("input:");
    Serial.println(expanderRead(expander1),DEC);
  }
  else {
    Serial.println("connection failed");
  }
  while (client.connected() && retval == -1) {
    if (client.available()) {
      char c = client.read();
      Serial.write(c);
      if (c>='0' && c<='9' && !invalid) { // zwischen 0 und 9, also eine Zahl, und sonst nix in der Zeile
        if (bufferpos>MAXLEN) {
          Serial.println("ZU LANGE!!!"); // Zu klein dimensionierter Puffer!
          invalid = true;
        } else
          buffer[bufferpos++] = c; // Zahl merken, dann zur naechsten Speicherzelle weitergehen
      } else if (c == '\r' || c == '\n') { // CR oder LF
        buffer[bufferpos] = '\0'; // "Ganz hinten" Stringende markieren
        if (bufferpos > 0) // In der letzten Zeile waren Zahlen, also NICHT zuruecksetzen!
          retval = atoi(buffer);
        invalid = false;
      } else {
        bufferpos = 0; // Keine Zahl, also Speicher an den Anfang zuruecksetzen!
        invalid = true; // Irgendwas anderes, ein Buchstabe oder ein Sonderzeichen oder so...
      }
    }
  }
  if (retval != -1){
    // Zahl gefunde, also jetzt was damit machen...
    expanderWrite(retval, expander2); // Testweise in die Expandr schreiben...
      // 0 = Alles ein // 255 = alles aus
  }
  Serial.println(retval);
  Serial.println("disconnecting.");
  client.stop();
  Serial.println(retval,BIN);
  Serial.println(retval,DEC);
  Serial.println("___");

  bufferpos = 0; // Klar zum naechsten Durchgang...
  invalid = false;
  retval = -1;
}
Code:
#def.h
...

byte server_ip[] = {
  192,168,1,160}; //Server IP
#define server_port  80
char webpraefix[] = "/alarm/ardu/"; //pfad zum script

long server_rw_previous = 0;

//---HTTP-Verbinfung---//
// Max. Anzahl an Zahlen! 6->1, 68->2, 680->3 etc...
#define MAXLEN 3

char buffer[MAXLEN+1];
byte bufferpos = 0;
boolean invalid = false; // Falsche Zeichen in der Zeile?
long retval = -1; // Nix...
Für einen hilfreichen Tipp wäre ich sehr dankbar.
« Last Edit: January 23, 2012, 04:50:22 am by senden9 » Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Schau Dir mal http://www.arduino.cc/playground/Code/TextFinder an. Um mir  UDP / NTP zu ersparen und da meine Wetterstation eh als Webclient arbeitet, habe ich mir eine Funktion gebaut, die den aktuellen Unix-Timestamp über einen Webrequest bekommt:
Die Ausgabe unter der URL sieht wiefolgt aus:
Quote
CURRENT TIME 1327349909
Folgender Code wertet das dann aus:
Code:
#include <Ethernet.h>
#include <TextFinder.h>
...
Client client(server, 8888);
TextFinder finder( client);
...
void getTime() {
  if (client.connect()) {
    Serial.print("connected... ");
    client.println("GET /time HTTP/1.0");
    client.println("Host: wetter.office.das-tierhausi.de");
    client.println();
  } else {
    Serial.println("connection failed");
  }
  if (client.connected()) {
    gettime = 0;
    if(finder.find("CURRENT TIME")){   
         gettime = finder.getValue(',');
         Serial.print(gettime);
         Serial.println(" seconds since 1970");         
    }
    if(gettime == 0){
      Serial.println("No time. ");
    }   
    client.stop();
    //time offset abziehen
    //damit kann immer mittels time + millis() / 1000 der aktuelle timestamp berechnet werden.
    time = gettime - millis() / 1000;
  }
}
Der "Trick" sind die beiden Zeilen "if(finder.find("CURRENT TIME")){  ", hier wird nach dem Markierungsstring gesucht, und
"gettime = finder.getValue(',');". Damit wird der nächste Wert nach dem Markierungsstring ermittelt. Das klappt bei mir hervorragend.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die Lösung:
Code:
void webserver(){
  //snprintf(out_string, 9, "%d", expanderRead(expander2));

  if (client.connect()) {
    Serial.println("connected");
    client.print("GET ");
    client.print(webpraefix);
    client.print("?i=");
    client.print(expanderRead(expander1),DEC);
    client.print(" HTTP/1.0\r\n\r\n");
    Serial.print("input:");
    Serial.println(expanderRead(expander1),DEC);
  }
  else {
    Serial.println("connection failed");
  }
  while (client.connected() && retval == -1) {
    if (client.available()) {
      char c = client.read();
      Serial.write(c);
      if (CR_LF_counter == 4) {
        if (bufferpos>MAXLEN) {
          Serial.println("ZU LANGE!!!"); // Zu klein dimensionierter Puffer!
          invalid = true;
        }
        else
          buffer[bufferpos++] = c; // Zahl merken, dann zur naechsten Speicherzelle weitergehen
      }
      else if (c == '\r' || c == '\n') { // CR oder LF
        CR_LF_counter++;
      }
      else {
        bufferpos = 0; // Keine Zahl, also Speicher an den Anfang zuruecksetzen!
        CR_LF_counter = 0;
        //invalid = true; // Irgendwas anderes, ein Buchstabe oder ein Sonderzeichen oder so...
      }
    }
  }
  if (bufferpos > 0) // In der letzten Zeile waren Zahlen, also NICHT zuruecksetzen!
          retval = atoi(buffer);
  if (retval != -1){
    // Zahl gefunde, also jetzt was damit machen...
    expanderWrite(retval, expander2); // Testweise in die Expandr schreiben...
    // 0 = Alles ein // 255 = alles aus
  }
  Serial.println(retval);
  Serial.println("disconnecting.");
  client.stop();
  Serial.println(retval,BIN);
  Serial.println(retval,DEC);
  Serial.println("___");

  bufferpos = 0; // Klar zum naechsten Durchgang...
  invalid = false;
  retval = -1;
  CR_LF_counter = 0;
  for(int x = 0; x <= (MAXLEN + 1); x++){
    buffer[x] = '\0';
  }
}

Code:
//---HTTP-Verbinfung---//
// Max. Anzahl an Zahlen! 6->1, 68->2, 680->3 etc...
#define MAXLEN 3

char start_key[10] = "WCzS2ttsE";
char buffer[MAXLEN+1];
byte bufferpos = 0;
boolean invalid = false; // Falsche Zeichen in der Zeile?
long retval = -1; // Nix...
int CR_LF_counter;
Danke für eure Hilfe!!!
Logged

Pages: [1]   Go Up
Jump to: