Hallo!
Folgendes Problem: Mein Arduino ruft über HTTP eine Seite auf:
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:
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:
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.
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...
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:
// 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;
}
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:
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;
}
#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...
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:
CURRENT TIME 1327349909
Folgender Code wertet das dann aus:
#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.
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';
}
}
//---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;