XML fetching question: Ethernet Shield

Hello,
I'm trying to get the time for london using the workweatheronline API
info:Time Zone API | World Weather Online

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

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

<localtime>2012-09-12 14:24</localtime>

So I have set the sketch to read the time after and to stop at '<'

#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();
}

Looking at the example on the page you linked, they show:

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.

Hi PaulS

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

sadly that didn't work.

Sadly, no modified code to look at...

The base URL for the Time Zone API is
World Weather API and Weather Forecast

#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();
}

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

    client.println("HOST: http://www.worldweatheronline.com");

No host name has http:// in it...

Neither

#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

#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

One last suggestion, then.

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

Loose the leading slash.

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

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.

The server name is the domain name of the site you're connecting to, in this case "www.worldweatheronline.com".

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

#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();
}

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.

//
// 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); 
}

Why isn't my version working then?

#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();
}

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.

Why isn't my version working then?

@stuarthooper
What message do you see in the serial monitor.
Compare with my working example above.
You should check the ip address from the yahoo server. May be you have to use a different. Make a ping in the command box.

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.

I provided 2 different ways and working sketches to read the yahoo weather xml.

  1. My own solution from an other thread
    Weather LCD display via XML - #5 by system - Project Guidance - Arduino Forum

  2. The fixed version from stuarthooper that worked on my board.

Zoomkat is right. These are two different code example. He tested successful version 1 which uses the TextFinder Library.

// Ethernet
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x13, 0x1D };
byte ip[] = { 78,149,131,230 };
byte gateway[] = { 10, 0, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };

IP doesn't match to the gateway IP.

It looks like your client can't make a connection to the Yahoo server.

Can you check your example sketch "WebClient" from the ethernet library. With this sketch you should be able to get response from the google server. After successful run of the Webclient sketch you can copy the ethernet settings to you weather sketch.

All of these services weather or time send xml data.

As I showed you in a earlier post I was able to receive the time data.

I also think the problem is in the ethernet connection and configuration. Gateway and Subnet a optional.

Did you check the WebClient example?

Yes, web client doesn't connect but my own sketch that sends and receives tweets using twitter client and the twitter library do work perfectly.

What ethernet configuration did you use in your working sketch? Copy these to your webclient sketch.