Sometimes, it is really nice to know what the weather is like without having to look out a window. Similarly, it is nice to know what the weather will be like in the future. Fortunately, getting weather information isn't that difficult.
For my needs, I wanted to get the weather data for a few cities in the Golden State, and have the data spoken to me by a computer.
For accessing the weather data, I headed over to http://api.wunderground.com/weather/api/ and signed up for a free API account. The free account limits me to 500 API calls per day and 10 calls per minutes. Since I am only interested in getting weather data a few times a week, the limits for the free account are of no real concern.
After getting my API key, it was time to fire up geany and smash out some Ruby code to do what I need to do, which is:
- get the data from the API
- save the data in a file
- transform the data into a more speakable string
- speak the string!
Enter the Ruby
require 'open-uri'
require 'json'
require 'fileutils'
key='########'
city=ARGV[0]
forecast_num = ARGV[1].to_i || 0
#was city defined?
unless city
puts 'you must enter a city name (or zip code)'
exit()
end
#define some file locations
this_dir = File.dirname(__FILE__)
data_file = File.join(this_dir, "#{city}.json")
temp_file = data_file+".tmp"
#if the data file doesn't exist or it is more than an hour old
if not File.exists?(data_file) or File.mtime(data_file) < Time.now() - (1/24.0)
#we need to dowload fresh data
url="http://api.wunderground.com/api/#{key}/forecast/q/CA/#{city}.json"
uri = URI.parse(url)
begin
#read the text
txt = uri.read
#write to the temp file
open(temp_file, "w") do |f|
f.puts txt
end
#mv the temp file, clobber if necessary
FileUtils.mv(temp_file, data_file, :force => true)
rescue
puts "Failed to get weather data"
end
end
#process the text from the data_file
txt = IO.read(data_file)
weather = JSON.parse(txt)
forecasts = weather['forecast']['txt_forecast']['forecastday']
title = forecasts[forecast_num]['title']
forecast = forecasts[forecast_num]['fcttext']
#do some regex processing of the forecast
forecast = forecast.gsub(/mph/, "miles per hour")
forecast = forecast.gsub(/([0-9]+)F/, '\1 Fahrenheit')
#remove any %20 from the city
city = city.gsub(/%20/,' ')
string = (forecast_num.zero?) ? "" : "Forecast "
string += "for #{city}. #{title}. #{forecast}"
#speak the string
`speak_string "#{string}"`
#comply with Section 2(d) @ http://www.wunderground.com/weather/api/d/terms.html
puts "This data is from Wunderground.com"
Just to make it a bit easier for me to get the weather or the forecast, this script is running on Cronos (my Minnowboard Max voice input machine) and is triggered via Blather when I say "what is the weather" or "what is the forecast". SWEET SAUCE!
Oh, the script references a command named "speak_string" which is a very simple wrapper for Festival and it looks like
echo "$1" | festival --tts
Now quite reading, and go talk to a computer.... or look out the window and see some weather.