Go Down

Topic: XML fetching question: Ethernet Shield (Read 2566 times) previous topic - next topic

StuHooper

Hello,
I'm trying to get the time for london using the workweatheronline API
info:http://www.worldweatheronline.com/time-zone-api.aspx

I have adapted the twitterclient sketch in the Ethernet library in order to access this informaton.
I have removed my MAC and API Key from this sketch below. In the Serial Monitor it doesn't get past
Quote
making HTTP request...

This leads me to believe there is something wrong with my "void connectToServer()" section. This is my first time trying to  GET information from an XML. Some guidance would be appreciated.

Thank you

The XML time that I need is between
Code: [Select]
<localtime>2012-09-12 14:24</localtime>
So I have set the sketch to read the time after <localtime> and to stop at '<'


Code: [Select]

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


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  *** MY MAC CODE GOES IN HERE**** };
IPAddress ip(*** MY IP GOES IN HERE******);

// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

char serverName[] = "http://www.worldweatheronline.com/feed/tz.ashx";  // time URL

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
  // reserve space for the strings:
  currentLine.reserve(256);
  time.reserve(150);

// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // attempt a DHCP connection:
  Serial.println("Attempting to get an IP address using DHCP:");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed to get an IP address using DHCP, trying manually");
    Ethernet.begin(mac, ip);
  }
  Serial.print("My address:");
  Serial.println(Ethernet.localIP());
  // connect to Time Server:
  connectToServer();
}



void loop()
{
  if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();

      // add incoming byte to end of line:
      currentLine += inChar;

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        currentLine = "";
      }
      // if the current line ends with <localtime>, it will
      // be followed by the time:
      if ( currentLine.endsWith("<localtime>")) {
        // time is beginning. Clear the time string:
        readingTime= true;
        time = "";
      }
      // if you're currently reading the bytes of the time,
      // add them to the time String:
      if (readingTime) {
        if (inChar != '<') {
          time += inChar;
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the time:
          readingTime = false;
          Serial.println(time);   
          // close the connection to the server:
          client.stop();
        }
      }
    }   
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(serverName, 80)) {
    Serial.println("making HTTP request...");
    // make HTTP GET request to server:
    client.println("GET key=******MY API KEY GOES IN HERE*********&q=london&format=xml");
    client.println("HOST: http://www.worldweatheronline.com/feed/tz.ashx");
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}   

PaulS

Looking at the example on the page you linked, they show:
http://www.worldweatheronline.com/feed/tz.ashx?key=xxxxxxxxxxxxxxxxx&q=SW1&format=xml
as the value to dump in a browser window.

The host, then, is www.worldweatheronline.com.
The GET request, then, is "feed/tz.ashx?key=xxxxxxxxxxxxxxxxx&q=SW1&format=xml".

That's what I'd try, anyway.

StuHooper

Hi PaulS

sadly that didn't work. I'm quite confused by this.

PaulS

Quote
sadly that didn't work.

Sadly, no modified code to look at...

StuHooper

Quote
The base URL for the Time Zone API is
http://www.worldweatheronline.com/feed/tz.ashx
- http://www.worldweatheronline.com/time-zone-api.aspx

Code: [Select]

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


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  *** MY MAC CODE GOES IN HERE**** };
IPAddress ip(*** MY IP GOES IN HERE******);

// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

char serverName[] = "http://www.worldweatheronline.com/feed/tz.ashx";  // time URL

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
  // reserve space for the strings:
  currentLine.reserve(256);
  time.reserve(150);

// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // attempt a DHCP connection:
  Serial.println("Attempting to get an IP address using DHCP:");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed to get an IP address using DHCP, trying manually");
    Ethernet.begin(mac, ip);
  }
  Serial.print("My address:");
  Serial.println(Ethernet.localIP());
  // connect to Time Server:
  connectToServer();
}



void loop()
{
  if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();

      // add incoming byte to end of line:
      currentLine += inChar;

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        currentLine = "";
      }
      // if the current line ends with <localtime>, it will
      // be followed by the time:
      if ( currentLine.endsWith("<localtime>")) {
        // time is beginning. Clear the time string:
        readingTime= true;
        time = "";
      }
      // if you're currently reading the bytes of the time,
      // add them to the time String:
      if (readingTime) {
        if (inChar != '<') {
          time += inChar;
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the time:
          readingTime = false;
          Serial.println(time);   
          // close the connection to the server:
          client.stop();
        }
      }
    }   
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(serverName, 80)) {
    Serial.println("making HTTP request...");
    // make HTTP GET request to server:
    client.println("GET /feed/tz.ashx?key=(APIkey)&q=london&format=xml");
    client.println("HOST: http://www.worldweatheronline.com");
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}   

Webmeister

The easiest way to read XML data is to use the TextFinder Library
http://www.arduino.cc/playground/Code/TextFinder

See my example of fetching XML data from Yahoo Weather API
http://arduino.cc/forum/index.php/topic,121992.msg920175.html#msg920175

PaulS

Code: [Select]
    client.println("HOST: http://www.worldweatheronline.com");
No host name has http:// in it...

StuHooper

Neither

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  *** MY MAC CODE GOES IN HERE**** };
IPAddress ip(*** MY IP GOES IN HERE******);

// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

char serverName[] = "www.worldweatheronline.com/feed/tz.ashx";  // time URL

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
  // reserve space for the strings:
  currentLine.reserve(256);
  time.reserve(150);

// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // attempt a DHCP connection:
  Serial.println("Attempting to get an IP address using DHCP:");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed to get an IP address using DHCP, trying manually");
    Ethernet.begin(mac, ip);
  }
  Serial.print("My address:");
  Serial.println(Ethernet.localIP());
  // connect to Time Server:
  connectToServer();
}



void loop()
{
  if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();

      // add incoming byte to end of line:
      currentLine += inChar;

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        currentLine = "";
      }
      // if the current line ends with <localtime>, it will
      // be followed by the time:
      if ( currentLine.endsWith("<localtime>")) {
        // time is beginning. Clear the time string:
        readingTime= true;
        time = "";
      }
      // if you're currently reading the bytes of the time,
      // add them to the time String:
      if (readingTime) {
        if (inChar != '<') {
          time += inChar;
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the time:
          readingTime = false;
          Serial.println(time);   
          // close the connection to the server:
          client.stop();
        }
      }
    }   
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(serverName, 80)) {
    Serial.println("making HTTP request...");
    // make HTTP GET request to server:
    client.println("GET /feed/tz.ashx?key=(APIkey)&q=london&format=xml");
    client.println("HOST: www.worldweatheronline.com");
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}   

or
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  *** MY MAC CODE GOES IN HERE**** };
IPAddress ip(*** MY IP GOES IN HERE******);

// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

char serverName[] = "http://www.worldweatheronline.com/feed/tz.ashx";  // time URL

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
  // reserve space for the strings:
  currentLine.reserve(256);
  time.reserve(150);

// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // attempt a DHCP connection:
  Serial.println("Attempting to get an IP address using DHCP:");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed to get an IP address using DHCP, trying manually");
    Ethernet.begin(mac, ip);
  }
  Serial.print("My address:");
  Serial.println(Ethernet.localIP());
  // connect to Time Server:
  connectToServer();
}



void loop()
{
  if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();

      // add incoming byte to end of line:
      currentLine += inChar;

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        currentLine = "";
      }
      // if the current line ends with <localtime>, it will
      // be followed by the time:
      if ( currentLine.endsWith("<localtime>")) {
        // time is beginning. Clear the time string:
        readingTime= true;
        time = "";
      }
      // if you're currently reading the bytes of the time,
      // add them to the time String:
      if (readingTime) {
        if (inChar != '<') {
          time += inChar;
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the time:
          readingTime = false;
          Serial.println(time);   
          // close the connection to the server:
          client.stop();
        }
      }
    }   
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(serverName, 80)) {
    Serial.println("making HTTP request...");
    // make HTTP GET request to server:
    client.println("GET /feed/tz.ashx?key=(APIkey)&q=london&format=xml");
    client.println("HOST: www.worldweatheronline.com");
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}   


Worked

PaulS

One last suggestion, then.
Code: [Select]
    client.println("GET /feed/tz.ashx?key=(APIkey)&q=london&format=xml");
Loose the leading slash.

Code: [Select]
    client.println("GET feed/tz.ashx?key=(APIkey)&q=london&format=xml");

StuHooper

No joy.

I'll have a look through some text books and get back to this thread.
I've contacted the staff as well to make sure it's not something at their end.

That wasted an afternoon.

PeterH

The server name is the domain name of the site you're connecting to, in this case "www.worldweatheronline.com".
I only provide help via the forum - please do not contact me for private consultancy.

Webmeister

I checked your sketch and changed some lines (Fixed IP, Server IP, Serial Begin)
Here is a working version. See the result in the serial monitor:


worldweatheronline-xml by Arduinopraxis

Code: [Select]

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


// Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
byte ip[] = { 10, 0, 1, 101 };
byte gateway[] = { 10, 0, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };

// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

//char serverName[] = "http://www.worldweatheronline.com/feed/tz.ashx";  // time URL

// Server
IPAddress server(81,201,134,251);

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
 // reserve space for the strings:
 currentLine.reserve(256);
 time.reserve(150);
 
 // Start Serial Port
 Serial.begin(9600);
 Serial.println("Setup...");
 // Start Ethernet
 Ethernet.begin(mac, ip);

 // connect to Time Server:
 connectToServer();
}



void loop()
{
 if (client.connected()) {
   if (client.available()) {
     // read incoming bytes:
     char inChar = client.read();

     // add incoming byte to end of line:
     currentLine += inChar;

     // if you get a newline, clear the line:
     if (inChar == '\n') {
       currentLine = "";
     }
     // if the current line ends with <localtime>, it will
     // be followed by the time:
     if ( currentLine.endsWith("<localtime>")) {
       // time is beginning. Clear the time string:
       readingTime= true;
       time = "";
     }
     // if you're currently reading the bytes of the time,
     // add them to the time String:
     if (readingTime) {
       if (inChar != '<') {
         time += inChar;
       }
       else {
         // if you got a "<" character,
         // you've reached the end of the time:
         readingTime = false;
         Serial.println(time);  
         // close the connection to the server:
         client.stop();
       }
     }
   }  
 }
 else if (millis() - lastAttemptTime > requestInterval) {
   // if you're not connected, and two minutes have passed since
   // your last connection, then attempt to connect again:
   connectToServer();
 }
}

void connectToServer() {
 // attempt to connect, and wait a millisecond:
 Serial.println("connecting to server...");
 //if (client.connect(serverName, 80)) {
 if (client.connect(server, 80)) {  
   Serial.println("making HTTP request...");
   // make HTTP GET request to server:
   client.println("GET /feed/tz.ashx?key=(yourkey_here)&q=london&format=xml");
   client.println("HOST: www.worldweatheronline.com");
   client.println();
 }
 // note the time of this connect attempt:
 lastAttemptTime = millis();
}  

zoomkat

I modified the previously posted code to fit my router setup and it seems to get weather data from somewhere and is displayed in the serial monitor.

Code: [Select]

//
// Read Yahoo Weather API XML
// 03.09.2012
// http://arduino-praxis.ch


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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
byte ip[] = { 192, 168, 1, 102 };
byte gateway[] = { 192, 168, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };

// Server Yahoo
IPAddress server(87,248,122,181);

EthernetClient client;
TextFinder  finder( client ); 

char place[50];
char hum[30];


void setup()
{
  // Start Ehternet
  Ethernet.begin(mac, ip);
  // Start Serial Port
  Serial.begin(9600);
  Serial.println("Setup...");
}


void loop()
{
  if (client.connect(server, 80))
  {
    // Call Wetter-API
    // w: ID from your City
    // http://weather.yahooapis.com/forecastrss?w=12893459&u=c
    ///
    Serial.println("Connect to Yahoo Weather...");
    client.println("GET /forecastrss?w=12893459&u=c HTTP/1.0");
    client.println("HOST:weather.yahooapis.com\n\n");
    client.println();
    Serial.println("Connected...");
  }
  else
  {
    Serial.println(" connection failed");
  }


  if (client.connected())
  {
   
    // Humidity
   if ( (finder.getString("<yweather:atmosphere humidity=\"", "\"",hum,4)!=0) )
   {
     Serial.print("Humidity:  ");
     Serial.println(hum);
   }
   else
   {
     Serial.print("No Humidity Data");
   }
   
   
    // Place/City
    if ( (finder.getString("<title>Conditions for ", " ",place,50)!=0) )
    {
      Serial.print("City:  ");
      Serial.println(place);
    }
   
   
    // Temperature
    if(finder.find("temp=") )
    {
     int temperature = finder.getValue();
     Serial.print("Temp C:  ");
     Serial.println(temperature);
   }
   else
   {
     Serial.print("No Temperature Data");
   }
   
         
  // END XML
  }
  else
  {
    Serial.println("Disconnected");
  }

  client.stop();
  client.flush();
  delay(60000);
}

Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

StuHooper

Why isn't my version working then?

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x13, 0x1D};
byte ip[]={78,149,131,230 };
// initialize the library instance:
EthernetClient client;

const unsigned long requestInterval = 60000;  // delay between requests

char serverName[] = "http://www.worldweatheronline.com/feed/tz.ashx";  // time URL
IPAddress server (81,201,134,251);

boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds

String currentLine = "";            // string to hold the text from server
String time = "";                  // string to hold the time
boolean readingTime = false;       // if you're currently reading the time

void setup() {
  // reserve space for the strings:
  currentLine.reserve(256);
  time.reserve(150);
 
  // Start Serial Port
  Serial.begin(9600);
  Serial.println("Setup...");
  // Start Ethernet
  Ethernet.begin(mac, ip);

  // connect to Time Server:
  connectToServer();
}


void loop()
{
  if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();

      // add incoming byte to end of line:
      currentLine += inChar;

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        currentLine = "";
      }
      // if the current line ends with <localtime>, it will
      // be followed by the time:
      if ( currentLine.endsWith("<localtime>")) {
        // time is beginning. Clear the time string:
        readingTime= true;
        time = "";
      }
      // if you're currently reading the bytes of the time,
      // add them to the time String:
      if (readingTime) {
        if (inChar != '<') {
          time += inChar;
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the time:
          readingTime = false;
          Serial.println(time);   
          // close the connection to the server:
          client.stop();
        }
      }
    }   
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(server, 80)) {
    Serial.println("making HTTP request...");
    // make HTTP GET request to server:
    client.println("GET /feed/tz.ashx?key=92b48f5ddc131933121209&q=london&format=xml");
    client.println("HOST: www.worldweatheronline.com");
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}   

zoomkat

Quote
Why isn't my version working then?


Your code appears to be "different" from the code I used. I suggest you try the code that worked for me to see if you have hardware issues or just issues with your code.
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

Go Up