Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Pages: [1] 2   Go Down
Author Topic: Online-Abfrage von Bahn-Verbindung  (Read 1994 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich möchte von der Deutschen Bahn Verbindungsdaten abfragen. Es gibt diese Seite:

http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?

Hier mein Code:

Code:
void loadBahnData()
{
Serial.println("Lade Bahn-Daten");
// http://81.200.198.90/bin/trainsearch.exe/dox?
byte ipBahn[] = {81,200,198,90};
// char hostname[] = "http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?";
// char url[] = "/bin/trainsearch.exe/dox?";
char output[1500] = "";
// char buf[100] = "";
char c;
short pos = 0;

// strcat(buf, "GET ");
// strcat(buf, url);
// strcat(buf, " HTTP/1.1");

// Serial.println(buf);

Client clientBahn(ipBahn,80);

if (clientBahn.connect())
{
Serial.println("Mit Server verbunden");
clientBahn.println("GET /bin/trainsearch.exe/dox? HTTP/1.1");
clientBahn.println("Host: reiseauskunft.bahn.de");
clientBahn.println("Connection: keep-alive");
clientBahn.println("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0");
clientBahn.println("Accept-Encoding: gzip");
clientBahn.println("Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7");
clientBahn.println("Cache-Control: no-cache");
clientBahn.println("Accept-Language: de,en;q=0.7,en-us;q=0.3");
clientBahn.println("Referer: http://reiseauskunft.bahn.de/bin/detect.exe/dox?");
clientBahn.println("");
clientBahn.println("");

while (clientBahn.available())
{
c = clientBahn.read();
Serial.print(c);
output[pos] = c;
output[pos+1] = '\0';
pos++;
}
Serial.println(output);

clientBahn.stop();
lastBahnUpdate = millis();
} else {
Serial.println("Verbindung zum Server gescheitert");
}
Serial.println("Laden der Bahn-Daten abgeschlossen");
}

Das bekomme ich:

Lade Bahn-Daten
Mit Server verbunden

Laden der Bahn-Daten abgeschlossen

Sieht jemand, warum das nicht funktioniert? Die Verbindung zum Server scheint ja zu klappen, aber ich erhalte keine Daten smiley-sad Eigentlich müsste ich das Abfrage-Formular erhalten, auf das ich dann mit einem POST-Request antworten möchte.

Danke und Gruss, Thomas
Logged

twitter: @darktom

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 274
Posts: 22162
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Welchen Arduino Hast Du?
Einen UNO?
Meiner Ansicht hast Du einen schönen Bufferüberlauf; die Internetseite ist bereits 3500 Byte lang ohne, irgendwelche Infos
Grüße Uwe
Logged

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

Hallo Uwe,

ich habe einen Mega 2560 im Einsatz, und klar, das ist noch völlig quick and dirty. Aber eigentlich müsste ich ja die eingelesenen Zeichen angezeigt bekommen?

Wobei ich sowieso daran dachte, das Einlesen nach Empfang der Zeile

<form action="http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?ld=9649&amp;rt=1&amp;use_realtime_filter=1&amp;OK" method="post" style="display:inline">

abzubrechen, denn die brauche ich dann für die eigentliche Anfrage. Ich kann damit nicht direkt anfangen, weil die Nummer mittendrin "ld=" sich jedesmal ändert und scheinbar sowas wie eine Session-ID ist. Also muss ich erst das Formular laden und dann einen Klick auf den Submit-Button simulieren.

Die Ethernet-Kommunikation funktioniert bei diesem Prototypen übrigens, also daran kann's nicht liegen smiley

Gruss Thomas
Logged

twitter: @darktom

Offline Offline
Sr. Member
****
Karma: 2
Posts: 260
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

ich glaube ich sehe das Problem in dem Sketch!

Du sendest den Request an den Server und direkt danach (vom Arduino gesehen microsekunden später) erwartest du schon, dass du eine Antwort vom Server bekommen hast.
Das dauert in der Realität doch etwas länger, und da in dem moment while (clientBahn.available()) false ist, wird die while schleife einfach übersprungen und die connection danach gestoppt.

Du musst also dafür sorgen, dass etwas gewartet wird bis der Server eine Antwort gesendet hat.

Mit einem einfachen delay() ist das etwas unzuverlässig, da du nie wirklich wissen kannst wie lange der Server braucht zum Antworten.

Stattdessen geb ich dir mal diesen groben Codeschnipsel:
Code:

boolean end_connection = false;
unsigned long connection_timeout_start = millis();
int connection_timeout = 10; // 10 seconds
while(true) // schleife die läuft, bis sie durch break; beendet wird.
  {
       // checken ob 10 sekunden schon um sind, wenn ja beenden der schleife einleiten.
      if( ((unsigned long) millis() - connection_timeout_start) >= (connection_timeout * 1000))
      {
       end_connection = true;
      }
   // ankommende zeichen verarbeiten         
   while (clientBahn.available())
{
c = clientBahn.read();
Serial.print(c);
output[pos] = c;
output[pos+1] = '\0';
pos++;

// wenn endzeichen vom http-server gesendet wird, beenden der schleife einleiten
                if(c == ?endcharakter?) // welches zeichen am ende einer HTTP-Connection gesendet wird müsstest du mal rausfinden
                {
                   end_connection = true;
                }

                // verlassen der schleife, wenn notwendig
                if(end_connection == true)
                {
                client.stop();
                client.flush();
               break;
                }
}


     

Welches zeichen am Ende einer HTTP-Connection gesendet wird weiß ich nicht, da ich den obenstehenden Codeschnipsel ein wenig anders verwendet habe. Vom Prinzip her sollte es aber klappen..


PS: Warum rufst du nicht gleich deinen POST-Request auf?
Ich glaube es ist nicht notwendig zuerst die Formularseite aufzurufen..
Logged

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

Genial, vielen Dank, ich mache mich an die Arbeit smiley

Ich ging davon aus, dass ich das Formular benötige wegen dieser Nummer "ld":

<form action="http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?ld=9649&amp;rt=1&amp;use_realtime_filter=1&amp;OK" method="post" style="display:inline">

Aber vielleicht irre ich mich ja auch, ich werde es jedenfalls auch auf dem direkten Weg versuchen!

Viele Grüße, Thomas
Logged

twitter: @darktom

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

Fall Du den Parameter "ld=xxx" doch benötigst, dann schau Dir mal http://www.arduino.cc/playground/Code/TextFinder an. Du musst ja nicht die gesamte Webseite in den Speicher lesen, wenn Du nur einige Bytes benötigst. Die Lib liest die Daten aus einem Stream und müllt daher nicht den Speicher zu. Wenn Du es geschafft hast, Deinen HTML-Request loszuschicken, musst Du ja auch noch die Antwort parsen, hier kann die TextFinder Lib sicher auch helfen.

Mario.
Logged

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

So, ich habe stundenlang herumprobiert, leider erfolglos.

Code:
void loadBahnData()
{
Serial.println("Lade Bahn-Daten");
byte ipBahn[] = {81,200,198,90};
char c;

Client clientBahn(ipBahn,80);
TextFinder finder(clientBahn);

// char pre_string[] = "<form action=\"";
// char post_string[] = "\" method=";

char pre_string[] = "dox?ld=";
char post_string[] = "&amp;rt=1";

int length = 10;
char buf[length];
char tmp[120];

clientBahn.connect();

delay(5);

if (clientBahn.connected())
{
Serial.println("Connected. Lade Abfrage-Formular...");
clientBahn.println("GET /bin/trainsearch.exe/dox? HTTP/1.1");
clientBahn.println("Host: reiseauskunft.bahn.de");
clientBahn.println("Connection: keep-alive");
clientBahn.println("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0");
clientBahn.println("Accept-Encoding: gzip");
clientBahn.println("Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7");
clientBahn.println("Cache-Control: no-cache");
clientBahn.println("Accept-Language: de,en;q=0.7,en-us;q=0.3");
clientBahn.println("Referer: http://reiseauskunft.bahn.de/bin/detect.exe/dox?");
clientBahn.println("");
clientBahn.println("");
delay(1000);

if(finder.getString((char *)&pre_string, (char *)&post_string, (char *)&buf, length) != 0)
{
while (clientBahn.available())
{
c = clientBahn.read();
}
clientBahn.flush();
sprintf(tmp, "POST /bin/trainsearch.exe/dox?ld=%s&rt=1&use_realtime_filter=1&OK HTTP/1.1", buf);
Serial.print("Request: "); Serial.println(tmp);
Serial.println("Lade Ergebnis-Seite...");
clientBahn.println(tmp);
clientBahn.println("Host: reiseauskunft.bahn.de");
clientBahn.println("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0");
clientBahn.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*//*;q=0.8");
clientBahn.println("Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
clientBahn.println("Accept-Encoding: gzip, deflate");
clientBahn.println("Connection: keep-alive");
clientBahn.println("Referer: http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?");
clientBahn.println("");
clientBahn.println("date=10.02.12&productClassFilter=1&trainname=874&stationFilter=80&start=Suchen");
clientBahn.println("");
clientBahn.println("");

delay(1000);

Serial.println("==============================");

while (clientBahn.available())
{
c = clientBahn.read();
Serial.print(c);
}
clientBahn.flush();
clientBahn.stop();
}
} else {
Serial.println("Can't connect");
}
lastBahnUpdate = millis();
Serial.println("Laden der Bahn-Daten abgeschlossen");
}

Ich habe mir den POST-Request mit Firebug angeschaut, mein Request seht haargenau gleich aus wie im Browser (habe mit Firebug geschaut). Jetzt bekomme ich als Antwort auf den Request immer nur die Suchmaske, ohne Daten... hat jemand eine Idee was ich noch probieren könnte?

Gruß Thomas
Logged

twitter: @darktom

Heidelberg
Offline Offline
Full Member
***
Karma: 1
Posts: 207
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hast du mal versucht das verhalten in einem normalen Browser zu simmulieren ? Da passiert das gleiche!

Was du tun musst ist das Formular zu spammen, sozusagen, das heisst den Inhalt der POST Variablen zu injizieren, es wird ja da die Zugnummer und der Select erwartet.

Ich befürchte, dass das ohne weiteren Server nicht funktioniert und wenn da bei der Bahn irgendwer für Sicherheit der Server zuständig ist, wird er das unterbinden.
Logged

 

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

Werden von der Seite evtl. Cookies gesetzt, die Du beim Request wieder mitschicken musst?
Logged

Heidelberg
Offline Offline
Full Member
***
Karma: 1
Posts: 207
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cookies sind vollkommen egal

Hier hast du ein Beispiel mit zwischemgeschalteten Linux und curl direktive: http://blog.trollmaker.com/article10/arduino-led-notification-for-gmail-on-linux

Das Funktionsprinzip ist bei beiden Anwendungen etwa identisch, es müssen POST Variablen transportiert werden, die normalerweise der Server auf der Gegenseite erledigt.
Logged

 

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

Cookies sind nicht zwingend egal. Es mag durchaus sein, das in diesem Fall Cookies keine Rolle spielen, aber das kann man nicht verallgemeinern. Wird ein Cookie als Session-Cookie verwendet, z.b. um SPAM-Anfragen zu verhindern, dann spielt das schon ein Rolle.

Unabhängig davon habe ich mit telnet mal ein wenig gespielt und siehe da, es muss nicht zwingend POST sein :-)

Du kannst Deine Parameter auch einfach per GET an den Request-String anhängen. Was ich allerdings gemacht habe ist die "&amp;" in einfache "&" zu ändern, so wie es das Protokoll vorsieht. Vor allem sieht man, das Du den Request auf das GET und den "Host" Parameter eindampfen kannst. Das spart wieder Speicher für Dein Programm, weil Du die ganzen Strings wie Useragent etc. nicht mehr brauchst. Auch der LD-Parameter ist nicht notwendig, Du kannst direkt mit dem "GET /bin/trainsearch.exe/dox?date=10.02.12&productClassFilter=1&trainname=874&stationFilter=80&start=Suchen HTTP/1.1" die Abfrage lostreten.
Siehe hier:
Quote
telnet reiseauskunft.bahn.de 80
Trying 81.200.198.90...
Connected to reiseauskunft.bahn.de.
Escape character is '^]'.
GET /bin/trainsearch.exe/dox?date=10.02.12&productClassFilter=1&trainname=874&stationFilter=80&start=Suchen HTTP/1.1
Host: reiseauskunft.bahn.de

HTTP/1.1 200 OK
Date: Fri, 10 Feb 2012 08:52:47 GMT
Server: Apache
Transfer-Encoding: chunked
Content-Type: text/html; charset=ISO-8859-1

e35
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Deutsche Bahn - </title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<meta http-equiv="expires" content="-1" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
<meta name="viewport" content="width=device-width; initial-scale=1.0;" />
<meta name="format-detection" content="telephone=no" />
<meta name="HandheldFriendly" content="true" />
<link rel="shortcut icon" href="http://www.img-bahn.de/v/861/img/favicon.ico" />
<link rel="apple-touch-icon" type="image/x-icon" href="http://www.img-bahn.de/v/861/img/apple-touch-icon.png"/>
<link rel="stylesheet" type="text/css" href="bahn_mobile.min.css" />
<link rel="stylesheet" type="text/css" href="http://www.img-bahn.de/v/861/css/hafas_mobile.css" />
<link rel="stylesheet" type="text/css" href="notouch.min.css" />
</head>
<body >
<div id="doc">
<div id="header">
<div class="logo"><img src="http://www.img-bahn.de/v/861/img/ua_xhtml/l_bahnmobile.gif" alt="DB - Deutsche Bahn" height="15" width="60" /></div>
<div id="branding">
<div class="bar1"> </div>
<div class="bar2"> </div>
</div>
</div>
<div id="content">
<h1>
<img class="prio1Icon" src="http://www.img-bahn.de/v/861/img/ua_xhtml/icon_echtzeit_grau_22x22.gif" height="22" width="22" alt="" /> <span class="bold">Fahrtinformationen</span>
</h1>
<div class="haupt bold">
ICE  874&nbsp;(Zuglauf vom: 10.02.12)</div>
<table class="ovTable">
<tr>
<th class="arrival ovHead2 bold" colspan="2">an<br />ab</th>
<th class="station ovHead2 bold">Halt<br />Aktuelles</th>
</tr>
<tr class="current">
<td>
09:52
</td>
<td>&nbsp;</td>
<td>aktuelle Zeit </td>
</tr>
<tr>
<td class="arrival tqdetail">
09:58
<br />
10:00
</td>
<td class="tqdetail rt top">
<span class="bold green">(+0)</span>
<br />
<span class="bold green">(+0)</span>
</td>
<td class="station tqdetail top">
Braunschweig Hbf
<br />
</td>
</tr>
<tr>
<td class="arrival tqdetail">
10:16
<br />
10:18
</td>
<td class="tqdetail rt top">
<span class="bold green">(+0)</span>
<br />
<span class="bold green">(+0)</span>
</td>
<td class="station tqdetail top">
Wolfsburg Hbf
<br />
</td>
</tr>
<tr>
<td class="arrival tqdetail">
11:11
<br />
&nbsp;
</td>
<td class="tqdetail rt top">
<span class="bold green">(+0)</span>
<br />
&nbsp;
</td>
<td class="station tqdetail top">
Berlin-Spandau
<br />
</td>
</tr>
<tr>
<td class="arrival tqdetail">
11:25
<br />
&nbsp;
</td>
<td class="tqdetail rt top">
<span class="bold green">(+0)</span>
<br />
&nbsp;
</td>
<td class="station tqdetail top">
Berlin Hbf
<br />
</td>
</tr>
<tr>
<td class="arrival tqdetail">
11:37
<br />
&nbsp;
</td>
<td class="tqdetail rt top">
<span class="bold green">(+0)</span>
<br />
&nbsp;
</td>
<td class="station tqdetail top">
Berlin Ostbahnhof
<br />
</td>
</tr>
</table>
<div class="bline">
<a class="nebenbtn" href="http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?">Zur&#252;ck</a>
</div>
</div>
<div id="footer">
<ul class="footer">
<li class="rline"><a class="footerlinks" href="http://reiseauskunft.bahn.de/bin/detect.exe/dox?">Startseite</a></li>
<li ><a class="footerlinks" href="http://reiseauskunft.bahn.de/bin/help.exe/dox?tpl=imprint&amp;">Impressum</a></li>
</ul>
</div>
<p class="webtrack">
<img src="http://t.bahn.de/b/ss//5/169869896?AQB=1&amp;gn=MOBI_ASK_DEU_de_Zuginfo&amp;ch=MOBI_ASK_DEU_de&amp;ev=event48,event19&amp;AQE=1" width="5" height="5" alt="" />
</p>
</div>
</body>
</html>

0

Connection closed by foreign host.

Logged

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

Vielen Dank für eure Mühe! Ich bin krank zu hause und werde heute mittag ausgiebig Gelegenheit haben, mich damit zu befassen.

Cookies hab ich im Browser mal gesperrt, die Abfrage funktioniert trotzdem, daran kann es also nicht liegen.

Was mir nicht so klar ist: Wenn ich die Anfrage mit dem Firefox oder sonst einem Browser machen kann, warum kann ich sie dann nicht mit dem Arduino machen, der letztendlich genauso mit dem Server kommunizieren kann? Ich vermute, die Antwort steckt in diesen Sätzen:

"Was du tun musst ist das Formular zu spammen, sozusagen, das heisst den Inhalt der POST Variablen zu injizieren, es wird ja da die Zugnummer und der Select erwartet.

Ich befürchte, dass das ohne weiteren Server nicht funktioniert und wenn da bei der Bahn irgendwer für Sicherheit der Server zuständig ist, wird er das unterbinden."


Das ist mir nicht so ganz klar. Bei meiner Anfrage übergebe ich doch die POST-Daten?

Naja aber wahrscheinlich funktioniert es ja mit der GET-Methode wie mkl0815 schrieb smiley
Logged

twitter: @darktom

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe mir das mal angeschaut und würde aus meinen bescheidenen Kentnissen folgendes feststellen.
Das Formular ist im prinzip ja eine mischung aus post und get!

Als ziel für das Formular steht ja eine URL drinne die GET-Variablen enthält.
Diese sind aber fix.
Diese ID ist anscheind immer gleich. Weil bei mir steht das selbe.
Du mußt also dein Formular an diese Adresse senden:
Code:
http://reiseauskunft.bahn.de/bin/trainsearch.exe/dox?ld=9642&amp;rt=1&amp;use_realtime_filter=1&amp;OK
Und dabei die POST-Variablen mit senden.

Code:
<select class="sqproduct nofullwidth" name="date" id="date">
<option value="10.02.12" >heute</option>
<option value="11.02.12" >morgen</option>
</select>
Für das Datum.
z.b. date=10.01.12

Code:
<select class="sqproduct nofullwidth" name="productClassFilter" id="productClassFilter">
<option value="1" >ICE</option>
<option value="2" >IC/EC</option>
<option value="4" >IR/D</option>
<option value="8" >RE/RB</option>
</select>
Für die Zugart
z.b. productClassFilter=1

Code:
<input class="text" type="text" name="trainname" id="trainname" value="" />
Die Zugnummer:
z.b. trainname=08154711

Code:
<input type="hidden" name="stationFilter" value="80" />
Der scheint auch fix zu sein
stationFilter=80

Code:
<input type="submit" class="hauptbtn" name="start" value="Suchen" />
Der Submit-Button
start=Suchen

Wie man beim Arduino POST-Werte setzt weiß ich nicht.
Aber so sollte es gehen
Danach bekommst du ja eine Antwort.
wie die dann aussieht schauen wir dann....
Logged

Heidelberg
Offline Offline
Full Member
***
Karma: 1
Posts: 207
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

POST Variablen lassen sich nicht "setzen", GET natürlich schon, aber die alleine lassen garnichts zu.

Ist doch aber auch klar: So lange ich einen Client simmuliere muss ich auch mit jedem anderen Client (=Browser) in der Lage sein das nachzumachen.

Und so lässt sich relativ einfach feststellen, dass der eingeschlagene Weg (ohne weitere Unterstützung) ein Holzweg ist.

Mindestens das cURL müsste als Befehl in der Arduino Umgebung funktionieren, was es aber allem Anschein nach nicht tut.
Logged

 

0
Offline Offline
Faraday Member
**
Karma: 26
Posts: 3525
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

1) Ich würde sowas grundsätzlich nicht per Arduino machen
2) Wenn ich sowas machen würde, dann würde ich alle Requests immer durch einen Debugproxy (z.B. Fiddler2) schieben. Das erleichtert die Fehlersuche ganz ungemein.
Logged

Check out my experiments http://blog.blinkenlight.net

Pages: [1] 2   Go Up
Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Jump to: