Go Down

Topic: Weather LCD display via XML (Read 4114 times) previous topic - next topic

kenneth87

Good day,

I'm starting a project on displaying the weather of the area i'm in (i.e. Sydney) on a LCD via an arduino uno with ethernet shield.

first, how do you get the xml code? i've seen some examples that links to google weather but the google weather link is not working?
appreciate it if someone could teach me how to get the xml code?

An example or sample code would be helpful too!

cheers!

Webmeister

You can use the Yahoo Weather API. I implemented a project in my book.
See my blog post regarding the stop of Google Weather
http://arduino-praxis.ch/2012/08/google-stoppt-weather-api/

I will post the code soon.

kenneth87

Thanks for the info mate. Looking forward to have a look at your code.

cheers!

kenneth87

Good day Webmeister,

Would you be kind to provide a sample code for the implementation of weather using yahoo's api?

Also if there's anyone that could help, i will appreciate it heaps!

Cheers!

Webmeister

To read the XML from Yahoo Weather API you can use the TextFinder library.

Before you read the weather data you need to get the ID (woeid) from your city.

Example: Zurich/Switzerland
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D%22Schweiz%20Z%C3%BCrich%22&format=xml

You will find the ID in the field <woeid>

Code to read the Yahoo Weather API

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[] = { 10, 0, 1, 101 };
byte gateway[] = { 10, 0, 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);
}




dbutt

Thanks for this code, it was super helpful. Does anyone know how to read in the forecasted temperature, not just the current?  I modified the code above to search for "High" or even "Forecast" which seems to appear in the raw RSS feed, but it doesnt return anything.  In fact finder.getvalue() doesn't return anything after the "Current Conditions", to me indicating that somehow the the forecast isn't part of the RSS link in the code above (even thought it appears when you look at the RSS in a browser).  I'm trying to get the forcasted High and Low and the chance of rain as a number (although that doesn't appear in the RSS so I might have to look elsewhere).  Any help would be immensely appreciated.

Webmeister

@dbutt

Please show us your modified code.

To find data in the xml stream you can also use the method finder.getString

dbutt

THanks for the response.  My goal is to use the code to find the high and low temps (and eventually chance of rain) and then change the color of some LEDs depending on the range.  I've left the LED part out until I can figure out how to read in the right information. 
I've tried searching for "High", "Low", "Forecast", which all appear (at least to me) in the source RSS feed.  If I search for "Current Conditions" that does work.

Here is my code:
Code: [Select]
//Source:
// Read Yahoo Weather API XML
// 03.09.2012
// http://arduino-praxis.ch


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

#include <TextFinder.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x73, 0xC5 };
//byte ip[] = { 10, 0, 1, 101 };
byte gateway[] = { 10, 0, 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);
  // Start Serial Port
  Serial.begin(9600);
  Serial.println("Setup...");
}


void loop()
{
  if (client.connect(server, 80))
  {
    // Call Wetter-API
    // w: ID from your City
    // Alternate access
    // 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("GET /forecastrss/60660_f.xml HTTP/1.0"); //I read on another forum that this link might provide more data
    client.println("HOST:xml.weather.yahoo.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);
    }
   
   
    // High Temperature
   // if(finder.find("temp=") )  original
   if(finder.find("Forecast:") )
    {
     long temperature = finder.getValue();
     Serial.print("High Temp F:  ");
     Serial.println(temperature);
   }
   else
   {
     Serial.print("No Temperature Data");
   }
   
   
    // Low Temperature
   // if(finder.find("temp=") ) original
   if(finder.find("Low") )
    {
     long temperature = finder.getValue();
     Serial.print("Low Temp F:  ");
     Serial.println(temperature);
   }
   else
   {
     Serial.print("No Temperature Data");
   }
   
         
  // END XML
  }
  else
  {
    Serial.println("Disconnected");
  }

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

Webmeister

I suggest that you copy the XML code to your text editor. Now you can identifiy the data you want to read.

To read the current condition use the following code:
Code: [Select]

char currentcond[50];
// Current Condition
    if ( (finder.getString("<b>Current Conditions:</b><br />", "</br> ",currentcond,50)!=0) )
    {
      Serial.print("Current Cond:  ");
      Serial.println(currentcond);
    }

dbutt

Thanks.  Yes I can get Current Conditions to print, but not anything after that.  Using your same code for instance and changing Current Conditions for Forecast won't print the Forecast, which is immediately following Current Conditions in the xml code.  I'm also interested just in the number of HIgh and Low, not all the text bit (so that I can easily apply an if statement for a number range).  Any ideas on why your code or the finder.getvalue() wont work for the Forecasted High and Lows.

Thanks.

Dan

Webmeister

As you can see in the XML Code the data for forecast is a datastring divided by HTML-Tags <BR>

Code: [Select]
<BR /><b>Forecast:</b><BR />
Tue - Mostly Sunny. High: 77 Low: 55<br />
Wed - Partly Cloudy. High: 68 Low: 48<br />
Thu - Partly Cloudy. High: 66 Low: 50<br />
Fri - Mostly Sunny. High: 68 Low: 48<br />
Sat - Sunny. High: 69 Low: 47<br />
<br />


Therefore it isn't possible to retrieve a value for HIGH by using finder.getValue()
It needs a more complex function to read the single values.

In this case I would use a PHP-Script which reads the data and puts them in a simple xml stream. In the second step you can use your Arduino board to read the output of the xml stream and display them in the serial monitor or on a display.

m4ttflynn

#11
Jan 29, 2013, 02:19 pm Last Edit: Feb 05, 2013, 01:03 am by m4ttflynn Reason: 1
Hello all,
This is my first arduino project, and I've modified the script above to output my local temperature as a voltage that I can send to another system.  Any insight as to why I'm not reading any output from pin 3 with this script?:

Quote

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

//TempRSS.pde

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

byte mac[] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
byte ip[] = { XX, XX, XX, XX };
byte gateway[] = { XX, XX, XX, 254 };
byte subnet[] = { 255, 255, 255, 0 };
// Server Yahoo
IPAddress server(87,248,122,181);

EthernetClient client;
TextFinder  finder( client ); 


void setup()
{
  // Start Ehternet
  Ethernet.begin(mac, ip);
  pinMode(3, OUTPUT);
  int pwm = 0;
}


void loop()
{
  if (client.connect(server, 80))
  {
    // http://weather.yahooapis.com/forecastrss?w=2445915&u=f
    client.println("GET /forecastrss?w=2445915&u=f HTTP/1.0");
    client.println("HOST:weather.yahooapis.com\n\n");
    client.println();
  }
  else
  {
    //connection failed- insert fault?
  }
  if (client.connected())
  {
    // Temperature
    if(finder.find("temp=") )
    {
     int temperature = finder.getValue();
     int pwm = (temperature*2.55);
     analogWrite(3, pwm);
   }
   else
   {
     //insert fault output?
   }
  // END XML
  }
  else
  {
    //insert fault output?
  }
  client.stop();
  client.flush();
  delay(60000);
}





Thanks!
-Matt

billroy

No idea.  But you might try printing the value of pwm before the analogWrite to see what's going on.

-br


m4ttflynn

Oh, by the way I'm using an UNO with a PoE ethernet shield... would I need an lcd to troubleshoot?

Thanks!
-Matt

billroy

If it were my problem I'd connect via USB for debugging and use Serial.print().

You can't debug what you can't see.

-br

Go Up