Go Down

Topic: XML per AJAX in HTML einbinden (Read 7386 times) previous topic - next topic

mr_sol

Hallo

Vielleich hat jemand von euch eine Idee oder Hinweis.

Ich möchte per AJAX die aktuellen Daten meines Arduino+Ethernet einbinden.
Ein direkter Zugriff per Browser klappt.
Ein xml testfile von meinen host per AJAX klappt auch

XML Daten von von Arduion per AJAX liefert mit Status=0 (quasi nix)

an was kann es liegen (ev. am Access-Control-Allow-Origin - erlaubt ajax direkten zugriff auf externen host)

Hier mein Quellcode


Code: [Select]

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x4D, 0x97 };
byte ip[] = { 192, 168, 0, 12 };

Server server(80);

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/xml");
  client.println("Access-Control-Allow-Origin: http://192.168.0.1/");
  client.println();
  client.print("<node id='IDNR'>");
  client.print("<sensor>1234</sensor>");
  client.print("</node>");
  delay(10);
  client.stop();
  }   
  delay(30);                           
}



Code: [Select]

<html>
<body>

<script type="text/javascript">
var xmlhttp;
var xmlDoc;
function callback(xhr)
{
    xmlDoc = xhr.responseXML;
alert(xmlDoc);
}

if (window.XMLHttpRequest)
{
    xmlhttp = new XMLHttpRequest();
}
else
{
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.open("GET", "http://192.168.0.12/", true);

xmlhttp.onreadystatechange = function ()
{
    if (xmlhttp.readyState != 4) return;
    if (xmlhttp.status != 200 && xmlhttp.status != 304) {
alert(xmlhttp.status);
return;
    }
callback(xmlhttp);
};

xmlhttp.send(null);

</script>

</body>
</html>



Vielen Dank im Voraus

udoklein

Vieleicht verrätst Du noch etwas mehr? Welcher Browser, welches OS, wie genau kann man das nachstellen? HastDu schon mal mit den üblichen Debugtools Firebug, Fiddler2 und was es sonst so gibt schon mal nachgeschaut?
Check out my experiments http://blog.blinkenlight.net

udoklein

Was mir gerade auffällt. Dein Output sieht nur aus wie XML, ist es aber nicht. XML fängt normalerweise so an:
Code: [Select]

<?XML>
Check out my experiments http://blog.blinkenlight.net

mr_sol

Vielen Dank für deine Antwort


Quote
Welcher Browser, welches OS

Browser FF4.0; Windows XP

Code: [Select]
<?XML>
Glaube ich fast nicht, sollte nicht der Content-Type: text/xml ausreichen


mr_sol

Noch eine Anmerkung und Mögliche Vermutung:

Kann es am "same origin policy" liegen?
Die XML Daten liegen ja auf einen anderen host als die HTML/AJAX Seite.

(http://molily.de/js/sicherheit.html#same-origin-policy)

df6ih

Also ich würde den Ansatz verwerfen mit XML.

Das müsstest du via Java, PHP, C# .... parsen um etwas ertägliches damit anfangen zu können. Dazu hast du es nicht als Datei vorliegen und ich befürchte das kostet dich deine letzten Haare.

In der Internetwelt schreiben wir sowas mal eben auf eine Terrabyte Platte, aber so ein kleines Arduinchen ist dann doch Matsche ;)

mr_sol

Das ist nur ein Testbeispiel. Das Ergebnis sind dynamische XML Daten, und kein starres XML File. (Sensorwerte werden in einer klaren XML Struktur an den Browser geschickt).

Warum AJAX: HTML5 Template wird aufgebaut und jede Sekunde werden die neuen Daten von Arduino abgefragt. Es sollte nicht jedesmal die komplette Bildschirmmaske aufgebaut werden, sonder nur die Position mit den Sensorwerten.

mikeZ337


Kann es am "same origin policy" liegen?

Ich denke, dass das die Ursache sein könnte.

Selber habe ich das immer so gelöst, dass per AJAX ein lokales Script (PHP z.B.) aufgerufen wird, dieses lädt die XML Daten (ich ziehe JSON vor, ist weniger aufwändig) des Arduinos und reicht diese weiter.
duemilanove / OSX & WIN
Arduino & Teensy: http://bit.ly/13rbdtQ

mr_sol

Per PHP ist es problemlos. Ich möchte ohne apache und php auskommen (absoluter minimalismus).
Das Template wir zuerst von der SD Card gelesen, dann erfolgt die Datenaktuallisierung per ajax.

Ziel: Board an LAN anstecken - Browser starten - IP eingeben - losgehts....

TriB

Hallo zusammen,

um eine möglichst kleine Seite zu schreiben und den Speicher des Ardu zu entlasten, habe ich auf dem Ardu eine Funktion, die den PIN entgegen nimmt und als Text den Status zurück sendet.
Die Webseite hat eine Schleife, die dann alle relevanten Pins abfragt und schicke Ein/Aus-Schalter anzeigt, bzw. den aktuellen Wert des Analog pins.
Etwas Trickreich war eigentlich nur, das die Seite die Antwort des Ardu nicht als weitere Seite anzeigt, sondern richtig verarbeitet.

Das geht dann in etwa so:
Code: [Select]
  // the file to be read
  pageURL = new java.net.URL("www.MeinArdu.dyndns.oder.so");

  // step 1, open the URL
  var openConnection = pageURL.openConnection;
  theConnection = openConnection();

  // step 2, connect to server
  var t=theConnection.connect;
  t();

  // step 3, read the file using HTTP protocol
  var getContent = theConnection.getContent;
  var theURLStream = getContent();

  // step 4, get an handle and fetch the content length
  var readStream = theURLStream.read;
  var gcl = theConnection.getContentLength;
  gcLen = gcl();

  // and finally, read into a variable
  theText =""
  for (i = 1; i <gcLen; i++)
  {
   theText += new java.lang.Character(readStream())
  }

Der Code ist noch etwas veraltet. Habe die aktuellen Sourcen gerade nicht da.

sui

#10
Aug 29, 2011, 12:51 pm Last Edit: Aug 29, 2011, 12:55 pm by sui Reason: 1

Quote
Welcher Browser, welches OS

Browser FF4.0; Windows XP


Firebug AddOn installieren => Netzwerk Tab => Entsprechenden Request aufklappen => Antwort Tab
Dann kannst Du erstmal sehen was und wie valide die ankommenden Daten sind.




Wenn Speicherplatz nicht das Problem ist, würde ich persönlich ein Framework wie jquery vorziehen. JSON ist für Ajax (trotz des Namens) durchaus auch gängiger und dürfte schon alleine wegen der geringeren Datenmenge einfacher mit dem Arduino zu generieren sein (letzendlich aber Geschmacksache).


Quote

Glaube ich fast nicht, sollte nicht der Content-Type: text/xml ausreichen


Der Content-Type ist höchstens ein Hinweis an den Browser, was er denn von dem Dokument halten soll. Wenn Du ein JPEG mit XML Content Type versendest, wird der XML-Parser schließlich auch nichts damit anfangen können.

(Edit: PS: Und XML-Parser sind schon bei allerkleinsten Fehlern ziemlich zickig...)

udoklein

@mr_sol: Du schreibst "... glaube ich nicht ...". Hast Du es ausprobiert? Dein Program funktioniert nicht. Debuggen bedeutet systematisch Fehler auszuschliessen. Wie auch andere schon angemerkt haben sind XML Parser häufig sehr penibel.
Check out my experiments http://blog.blinkenlight.net

mr_sol

Erstmal vielen dank für eure Ideen und Unterstützung

Hier die verbesserte pde:
Code: [Select]

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x4D, 0x97 };
byte ip[] = { 192, 168, 0, 12 };

Server server(80);

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/xml");
    client.println();
    client.print("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
    client.print("<node id=\"IDNR\">");
    client.print("<sensor>1234</sensor>");
    client.print("</node>");
    delay(10);
    client.stop();
  }   
  delay(30);                           
}



JS habe ich auf Post umgestellt:
Code: [Select]

<html>
<body>

<script type="text/javascript">
var xmlhttp;
var xmlDoc;
function callback(xhr)
{
    xmlDoc = xhr.responseXML;
alert(xmlDoc);
}

if (window.XMLHttpRequest)
{
    xmlhttp = new XMLHttpRequest();
}
else
{
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.open("POST", "http://192.168.0.12/", true);

xmlhttp.onreadystatechange = function ()
{
    if (xmlhttp.readyState != 4) return;
    if (xmlhttp.status != 200 && xmlhttp.status != 304) {
alert(xmlhttp.status);
return;
    }
callback(xmlhttp);
};

xmlhttp.send(null);

</script>

</body>
</html>




Leider Liefert ajax eine Status 0 Meldung (statt 200). Rufe ich Arduino direkt per BrowserURL auf klappt es einwandfrei (an der Firewall kann es nicht liegen)

Hier mit Firebug
[img]ajax.jpg[img]

mr_sol

Ich hatte was übersehen beim debugging - jetzt klappt Status 200

Es liegt am XML, bei Betrachtung mit FireBug -> XML zeigt er einen Fehler im XML an. Verstehe ich nicht

XML ist valid....woran kann's dann liegen?

andreasw

Das Problem ist der Cross-Site-Schutz des Browsers.
Zum Umgehen gibt es versch. Möglichkeiten:
* Cross-Site-Schutz ausschalten
* PHP-Script auf dem Server als Umleitung benutzen
* Yahoo YQL als Vermittler benutzen

Gruß
Andreas

Go Up