Weather LCD Display

WLC
Using Google's Weather API to display the current weather conditions in Los Angeles on the LCD. Larger Image

This Internet of Things example displays the current weather conditions on a text LCD. It uses a Google Weather API to retrieve a web page containing XML with weather data for Los Angeles. The Simple Plain XML parser library ported to mbed is used to parse the XML and retrieve the desired data fields for the LCD display. It is based on an earlier XML parser example and the Text-LCD library.

GDC
Google's Largest Server Farm is near a hydroelectric power plant in Oregon. It might wind up responding to your weather API call.

/media/uploads/4180_1/weatherchannel.jpg
The Weather Channel Studio in Atlanta.

The Weather Channel also has RSS feeds for many cities. The Weather Channel API is only available by paid subscription.

Wiring

The same hardware and wiring setup is used as the Internet LCD clock example, News LCD Display, and Geolocation LCD Display.

Ethernet Magjack Connector

MbedSparkfun Ethernet Breakout
TD+P1
TD-P2
RD+P7
RD-P8

Note: Different magjack connectors can use different pin outs even though they look the same. These pins are for connectors from Sparkfun in 2011. If you are having trouble with your initial network setup, try this example code first. Once it works, it will confirm correct wiring on the connector (at least on the input side). Magjack Pinouts are posted for other common connectors. More connections to the unused pins including one to 3.3V and a capacitor should be added for long cables, but this setup works well with short cables. If you still get the net error message, make sure that DHCP service is enabled for your mbed. On some networks, you need to add the module's MAC address to enable the DHCP server to give it an IP address. It times out with an error, if no IP address is returned in about fifteen seconds. If the weather does not display on the LCD after seeing "net OK", you may have DNS problems or a very slow network.

Text LCD

Mbed pinsText LCD pins
GNDGND
5V or 3.3V*VCC
VO to GND via 1k resistor
P15RS
GNDRW
P16E
N/CD0
N/CD1
N/CD2
N/CD3
P17D4
P18D5
P19D6
P20D7

Where N/C is not connected and the top left pin of the TextLCD’s header is GND and the right most pin is D7 in the LCD orientation shown in the images above. The resistor sets the contrast and some LCDs may need a different value or a contrast adjust potentiometer. See Text LCD for additional help, if needed.

(*) Note: some older LCDs may use 5V, but 3.3V is more common on current LCDs. If you cannot find a data sheet to confirm this, try 3.3V first and if the display is still blank (after double checking all other connections and code) it might need 5V. To save jumper wires, this setup uses the four bit interface to transfer ASCII characters to the LCD.

Example Code

#include "mbed.h"
#include "EthernetNetIf.h"
#include "HTTPClient.h"
#include "spdomparser.hpp"
#include "spxmlnode.hpp"
#include "spxmlhandle.hpp"
#include "TextLCD.h"
// Internet of Things weather display example: LCD displays LA current weather via internet Google API
// Adapted for LCD from http://mbed.org/users/hlipka/programs/spxmltest_weather/lif782 
TextLCD lcd(p15, p16, p17, p18, p19, p20); // rs, e, d0-d3
EthernetNetIf eth;
HTTPClient http;
HTTPResult result;
bool completed = false;
void request_callback(HTTPResult r) {
    result = r;
    completed = true;
}

void parseWeather(SP_XmlElementNode *node) {
    //extracts current weather XML data fields for LCD 
    SP_XmlHandle handle(node);
    SP_XmlElementNode * condition = handle.getChild( "condition" ).toElement();
    lcd.cls();
    lcd.printf("LA:");
    if (condition) {
        lcd.printf("%s ",condition->getAttrValue("data"));
    }
    SP_XmlElementNode * tempf = handle.getChild( "temp_f" ).toElement();
    if (tempf) {
        lcd.printf(" %sF\n",tempf->getAttrValue("data"));
    }
    SP_XmlElementNode * humidity = handle.getChild( "humidity" ).toElement();
    if (humidity) {
        lcd.printf("%s",humidity->getAttrValue("data"));
    }
}

int main() {
    // the eth and HTTP code has be taken directly from the HTTPStream documentation page
    // see http://mbed.org/cookbook/HTTP-Client-Data-Containers
    lcd.cls();
    lcd.printf("net setup");
    EthernetErr ethErr = eth.setup();
    if (ethErr) {
        lcd.printf("\n\rError in setup");
        return -1;
    }
    lcd.printf("\n\r net ok");

    SP_XmlDomParser parser;
    HTTPStream stream;

    char BigBuf[512 + 1] = {0};
    stream.readNext((byte*)BigBuf, 512); //Point to buffer for the first read
    //Google Weather API for Los Angeles - get web page with XML
    HTTPResult r = http.get("http://www.google.com/ig/api?weather=Los+Angeles", &stream, request_callback);
    while (!completed) {
        Net::poll(); //Polls the Networking stack
        if (stream.readable()) {
            BigBuf[stream.readLen()] = 0; //Transform this buffer in a zero-terminated char* string
            parser.append( BigBuf, strlen(BigBuf)); // stream current buffer data to the XML parser
            stream.readNext((byte*)BigBuf, 512); //Buffer has been read, now we can put more data in it
        }
    }
    lcd.cls();
    if (result == HTTP_OK) {
        lcd.printf(" Read complete\n\r");
    } else {
        lcd. printf(" Error %d\n", result);
        return -1;
    }

    SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() );
    SP_XmlElementNode * child2 = rootHandle.getChild( "weather" )
                                 .getChild( "current_conditions").toElement();
    if ( child2 ) {
        parseWeather(child2); //parses XML "current-conditions" info
    }

    if ( NULL != parser.getError() ) {
        lcd.printf( "\n error: %s\n", parser.getError() );
    }
}

The code sets up networking and reads a special Google web page containing XML data with weather using http.get(). Data extracted from this XML web page is then displayed in the LCD using the TextLCD library lcd.printf() function. Here is a typical web page of XML data in response to http://www.google.com/ig/api?weather=Los+Angeles

Google_Weather_API_XML_page

<?xml version="1.0" ?> 
- <xml_api_reply version="1">
- <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">
- <forecast_information>
  <city data="Los Angeles, CA" /> 
  <postal_code data="Los Angeles" /> 
  <latitude_e6 data="" /> 
  <longitude_e6 data="" /> 
  <forecast_date data="2012-04-20" /> 
  <current_date_time data="2012-04-21 00:47:00 +0000" /> 
  <unit_system data="US" /> 
  </forecast_information>
- <current_conditions>
  <condition data="Clear" /> 
  <temp_f data="65" /> 
  <temp_c data="18" /> 
  <humidity data="Humidity: 70%" /> 
  <icon data="/ig/images/weather/sunny.gif" /> 
  <wind_condition data="Wind: N at 5 mph" /> 
  </current_conditions>
- <forecast_conditions>
  <day_of_week data="Fri" /> 
  <low data="61" /> 
  <high data="73" /> 
  <icon data="/ig/images/weather/mostly_sunny.gif" /> 
  <condition data="Mostly Sunny" /> 
  </forecast_conditions>
- <forecast_conditions>
  <day_of_week data="Sat" /> 
  <low data="55" /> 
  <high data="72" /> 
  <icon data="/ig/images/weather/mostly_sunny.gif" /> 
  <condition data="Mostly Sunny" /> 
  </forecast_conditions>
- <forecast_conditions>
  <day_of_week data="Sun" /> 
  <low data="57" /> 
  <high data="68" /> 
  <icon data="/ig/images/weather/mostly_sunny.gif" /> 
  <condition data="Mostly Sunny" /> 
  </forecast_conditions>
- <forecast_conditions>
  <day_of_week data="Mon" /> 
  <low data="57" /> 
  <high data="68" /> 
  <icon data="/ig/images/weather/mostly_sunny.gif" /> 
  <condition data="Mostly Sunny" /> 
  </forecast_conditions>
  </weather>
  </xml_api_reply>

Note that the data needed is found above under -<current_conditions>. After reading the web page and finding -<current_conditions> , the XML parser is used in parseWeather() to extract the data fields needed for use in the LCD display. Change the city at the end of the URL to obtain weather for another city. In this code, long XML web pages from other URLs containing several thousand characters can consume all of the available RAM memory on mbed and cause out of memory errors. In such cases, file I/O could be used. Another option is to process the XML data as read streams in each block of data and release the memory buffers (to avoid running out of memory) as it is parsed in sequential order.

Import programweather_LCD_display

Displays weather info on text LCD using Google API

Video of Demo Code


When the USB cable is plugged in, mbed powers up and contacts the DHCP server to get an IP address. It gets an IP address and responds with "net OK". It then reads the web page containing the XML with the current weather, parses the XML to extract the data, and displays it on the LCD.

More on Web APIs

There are a large number of other web APIs (also called web services) available. This web API directory has almost 6,000 listed. Some are free, free for non-profit use, require registration and a key, or perhaps free for a limited number of calls, but most require a license and a paid subscription fee. The availability of web APIs is changing rapidly and checking the directory could be useful to find new resources. Google has a history of offering new APIs for free and then charging for them later. Some examples include the Google speech recognition and translation APIs. This could happen in the future with the Google weather API.

Ideas for Further Enhancements

1. Display your cities weather by changing the URL suffix.
2. Automatically update weather info every few minutes.
3. In case of a network error, delay several seconds and automatically retry.
4. Alternate between current conditions and the forecast.
5. Alternate with the Weather Channel RSS feed for the city.
6. Investigate using the IP address or GPS to automatically guess the city.
7. Add a severe weather alert alarm feature with pushbuttons and a speaker. The speaker will likely need a driver circuit. In the USA, see http://www.nws.noaa.gov/rss/ and http://alerts.weather.gov/.
8. Use a wireless network connection with a WiFly module or other wireless device.
9. Use Power over Ethernet (PoE) to power the clock and avoid the extra wires for power. Sparkfun has one PoE option.
10. Instead of pushbuttons, use touch switch input.
11. Add a temperature sensor and add indoor temperature to the display.
12. Upgrade to a larger display such as a color LCD or VGA.
13. Try the Yahoo Weather API. Here is an example: http://xml.weather.yahoo.com/forecastrss?p=USCA1116. The last argument value is the country state and zipcode.
13. Investigate using some of the other weather web APIs.


Report

5 comments on Weather LCD Display:

19 May 2012

Dear Jim, very interesting program and it works very well on French cities, but it doesn't works if I upgrate the HTTPClient Library ; several input files from this library couldn't be open > every "core/" and "api/" files. What is the solution with the new library ? Thanks CTophe

22 May 2012

There are some interactions between it and all of the different versions of the netservices library. I don't know exactly which versions of each will match up without errors. In any case, I think there is a new version of the netservices library coming soon from the mbed team that will work with the new RTOS - probably will want to upgrade to that when it comes out.

03 Oct 2012

.....As predicted Google has shut down their weather API. I am trying to get this up with an alternative. Will let you know if I succeed. W

04 Oct 2012

Ugh! Sad but true. Yahoo http://developer.yahoo.com/weather/ might be an option. Probably should also switch over to the new networking libraries.

02 May 2013

http://mbed.org/users/lballiet91/notebook/nokia-lcd-weather-application/ has a version running on Yahoo's Weather API for the Nokia color LCD. That code can be cut down for the simplier Text LCD with a little work. It has the parser mods and newer network libraries.

Please login to post comments.