Weather Doodles

Wednesday, January 2, 2008

The masthead on NAIS changes based on the local weather, temperature, and sunset and sunrise time. I added the daylight check at Doolies’s request. She didn’t understand why my weather doodle showed sunny at 5pm. This time of year, the sun sets at 4:29pm, and rises at 7:58am. I wish I was making this up.

First, I read in the XML file from the very helpful National Oceanic and Atmospheric Administration’s National Weather Service. They provide a number of great RSS feeds, of which I chose the hourly observations. I picked KRNT.xml, the feed for the Renton Municipal weather station, because it felt closest (knowing my geographic sense, I could be way off). Here’s the PHP code (remember, I can’t use file_get_contents() on a URL because of the PHP.ini security setting. I replaced it with the CURL call):

time()-30*60) { $ch = curl_init('http://www.nws.noaa.gov/data/current_obs/KRNT.xml'); $fp = fopen('weather.xml', 'w'); curl_setopt($ch,CURLOPT_FILE,$fp); curl_setopt($ch,CURLOPT_HEADER,false); curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); curl_setopt ($ch,CURLOPT_CONNECTTIMEOUT,3); $result=curl_exec($ch); curl_close($ch); fclose($fp); if ($result) { $xml_parser=xml_parser_create(); $data=file_get_contents('weather.xml'); xml_parse_into_struct($xml_parser,$data,$values,$index); $weather=$values[$index['WEATHER'][0]]['value']; $temp=$values[$index['TEMP_F'][0]]['value']; file_put_contents('weather',$weather.','.$temp); unlink('weather.xml'); } } $weathertitle='Seattle WA: '.$weather.', '.$temp.'° F'; $s.=''; ?>

The code checks the weather once every thirty minutes, and saves the parsed result to a flat file. I use this file as a cache so I don’t have to reparse the XML file each time. There is higher-level page cache (which I plan to write more about) that also uses flat files to take the load off the MySQL server, which seems to be the bottleneck in serving pages.

I plan to generalize the above code a bit in the future so when I travel, I can replace Seattle with my destination (and its corresponding weather station). While this would be a trivial change, it’s not very high on my list.

After I load the XML file, I use the PHP xml parser to parse the document and find the weather description and temperature. I called xml_parse_into_struct() to perform the parsing. I still don’t quite understand how the structure is created. Through trial and error, I found the appropriate structure and array elements.

For the daylight check, I used the convenient PHP functions date_sunrise() and date_sunset(). These functions use the longitude and latitude and return sunset and sunrise times for the requested day.

date_sunset(time(),SUNFUNCS_RET_TIMESTAMP,45,-122)) $doodle='night-'.$doodle; ?>

And then I have the weather parsing code. As I add more weather doodles, I continue to tweak the code. It turns out the weather service uses many phrases to describe weather conditions. Some examples: “Thunderstorm in Vicinity Hail Haze,” “Showers in Vicinity Fog/Mist,” and “Heavy Sand Storm.” At first, I created a huge switch/case statement to capture all of the phrases. After a bit of thought, I decided to fall back on simpler phrase searches through an if/else statement. I set it up as a hierarchy to ensure the most desirable doodle is selected, e.g., if it’s “Light Drizzle Fog/Mist” it chooses the fog doodle—mostly because it’s less common. Similarly, if there’s a mention of snow or frozen rain, it chooses the snow doodle.

I will add a more robust temperature/season check once I have more relevant doodles. I’m hemming and hawing because I’m not satisfied with the following code. But I’ll include it for completeness.

50) $doodle='sun.png'; else $doodle='sun-cold.png'; } ?>

My next step is to get doodling. It’s great to have all this code, but it’s wasted if my weather doodle is always the same. I plan to have a bunch of rain and cloudy doodles for the winter, and many sunny doodles for the summer. In Seattle, the word rain is much like the word snow is to Eskimos: you need many words (and doodles) to capture its essence.

 Seattle, WA | , ,