Monday, July 4, 2011, 12:11
Posted by Administrator
		For the last couple of days I have been working the chat server and client that I made last semester. Adding additional features to it has been slow but satisfying work.
A weather function has been at the top of my list for things I wanted to see myself implement, so last night I decided to get to working on making something to retrieve the weather.
I've been using the 
bash script below to get weather information for months now:
#!/bin/bash
var_url="http://www.google.com/ig/api?weather=72959&hl=en"
var_weather_wget=`wget -q $var_url -O -`
var_weather_xml=`echo "$var_weather_wget" | sed 's/<forecast_conditions>.*//'`
var_weather=`echo "$var_weather_xml" | sed 's/></>\n</g'`
var_date=`echo "$var_weather" | grep -e '<forecast_date' | \
sed -e 's/<forecast_date data="//' -e 's/"\/>//'`
var_city=`echo "$var_weather" | grep -e '<city' | \
sed -e 's/<city data="//' -e 's/"\/>//'`
var_condition=`echo "$var_weather" | grep -e '<condition' | \
sed -e 's/<condition data="//' -e 's/"\/>//'`
var_temp_f=`echo "$var_weather" | grep -e '<temp_f' | \
sed -e 's/<temp_f data="//' -e 's/"\/>//'`
var_temp_c=`echo "$var_weather" | grep -e '<temp_c' | \
sed -e 's/<temp_c data="//' -e 's/"\/>//'`
var_humidity=`echo "$var_weather" | grep -e '<humidity' | \
sed -e 's/<humidity data="//' -e 's/"\/>//'`
var_wind=`echo "$var_weather" | grep -e '<wind' | \
sed -e 's/<wind_condition data="//' -e 's/"\/>//'`
echo "Date: $var_date - City: $var_city"
echo "Condition: $var_condition"
echo "Temp: $var_temp_c C"
echo "$var_humidity"
echo "$var_wind"
This has been working well, but I wanted to make something more extensible with Java that I could add to my chatserver and run with any zipcode instead of just having it set to one location.
After finagling around a little I was able to come up with something I'm liking pretty well that fit great into the server I'm putting together:
This has been working well, but I wanted to make something more extensible with Java that I could add to my chatserver and run with any zipcode instead of just having it set to one location.
After finagling around a little I was able to come up with something I'm liking pretty well that fit great into the server I'm putting together:
/*   < <  Current Weather > >      |
    Forecast from Google's API     |
           Spike  Snell            |
               2011                |
----------------------------------*/
import java.io.*;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class weather {
	public static void main(String[] args) throws Exception {
		if (args.length > 0)
			System.out.println(toString(args[0]));
		else
			System.out.println("Please enter a valid 5 digit zipcode. Example: java weather 72701");
	}
	public static BufferedReader read(String url) throws Exception {
		return new BufferedReader(new InputStreamReader(new URL(url).openStream()));
	}
	public static String toString(String zip) throws Exception {
		
		// variables to hold the weather
		String date = null;
		String city = null;
		String condition = null;
		String tempC = null;
		String humidity = null;
		String wind = null;
		
		// declare the pattern and matcher
		Pattern p;
		Matcher m;
		
		// check to make sure the string is the right number of characters
		if (zip.length() != 5) 
			return "Please enter the correct number of digits.";
		
                // and make sure all 5 of the characters are numbers
		p = Pattern.compile("\\d{5}");
		m = p.matcher(zip);
		if (m.find() == false)
			return "Please enter a valid 5 digit zipcode.";
		// open up a connection to google's weather API
		BufferedReader reader = read("http://www.google.com/ig/api?weather="+ zip);
		String page = reader.readLine();
		// get the date
		p = Pattern.compile("<forecast_date data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			date = m.group(1);
		// get the city
		p = Pattern.compile("<city data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			city = m.group(1);
		// get the condition
		p = Pattern.compile("<condition data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			condition = m.group(1);
		// get the temperature in C
		p = Pattern.compile("<temp_c data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			tempC = m.group(1);
		// get the humidity
		p = Pattern.compile("<humidity data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			humidity = m.group(1);
		// get the humidity
		p = Pattern.compile("<wind_condition data=\"(.*?)\"/>");
		m = p.matcher(page);
		if (m.find() == true)
			wind = m.group(1);
		// if the date is still null there was a problem
		if (date == null) {
			return "There was a problem retrieving the weather.";
		}
		else {
			// return the forecast
			return city + " - " + date + 
			       "\nCondition: " + 
			       condition+ "\nTemp: " + 
			       tempC + " *C\n" + 
			       humidity + "\n" + 
			       wind;
		}
	}
}
What it does is taken in a command line argument for the zipcode and after a bit of error checking (Making sure the zipcode is actually 5 numbers) it grabs the data from 
google's weather API, runs it through some regexes to grab the data I want and then returns everything as a string.
Here is an example of it in use:
nrg@AKIRA ~/Desktop $ java weather 72701
Fayetteville, AR - 2011-07-04
Condition: Mostly Cloudy
Temp: 27 *C
Humidity: 74%
Wind: S at 5 mph
Any feedback on improving this code or any other comments about it would be much appreciated.