That's a lot of letters in the title! If you've looked into harvesting weather forecast data, then you might've run across them already. If not, lemme define the acronyms and provide some links for further reading. What we'll be doing is harvesting weather forecast data from the National Weather Service's National Digital Forecast Database. I'll show how to gather this data using ruby. We'll use open-uri to grab the XML response, and then use REXML to process the response from the NDFD. I've even done a lot of leg work here and I'll be documenting both the REST and the SOAP methods of querying this NWS database! First I'll make an interlude to consolidate useful reference links:
Next I'd like to take a brief moment to preface this article with NOAA's request regarding frequency of polling this service. Because it's free and excellent, we should all be thankful for this service and honor their request. The NDFD data available via the REST service is updated no more than hourly. As a result, we request developers using this REST service only make a request for a specific point no more than once an hour. The database is currently updated by 45 minutes after the hour. I have not noticed a similar request on the SOAP service, but imagine it also applies. And now I'll get on with the source. It's not complete yet, but to whet your appetite I'll paste in the guts to illustrate the awesome to come! Below is working code that shows proper request formatting and starts into error handling and result processing. #!/usr/bin/ruby def do_soap(t_begin, t_end, lat, lon) #WARNING: soap4r gem is broken in ruby 1.9. See: https://github.com/spox/soap4r-spox require 'soap/wsdlDriver' action = 'http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl' driver = SOAP::WSDLDriverFactory.new(action).create_rpc_driver begin response = driver.NDFDgen( lat, lon, 'time-series', t_begin, t_end, {:maxt => true} ) puts response rescue SOAP::FaultError puts "Whoops: there was an error processing the SOAP request." end end def do_rest(t_begin, t_end, lat, lon) rest_url = "http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdXMLclient.php" rest_query = "?lat=#{lat}&lon=#{lon}" + "&product=time-series&begin=#{t_begin}&end=#{t_end}" + "&maxt=maxt" require 'open-uri' require 'rexml/document' xml = open(rest_url + rest_query).read if(xml.match(/^<error>/)) puts "Whoops: there was an error processing the REST request." else document = REXML::Document.new(xml) document.elements.each("dwml/data/location/point") do |element| puts "Found at: #{element.attributes["latitude"]}, #{element.attributes["longitude"]}" end puts document end end t = Time.now t_begin = Time.local(t.year,t.mon, t.day) t_end = t_begin + 1 * 24 *3600 t_begin_formatted = "#{t_begin.year}-#{"%02d" % t_begin.month}-#{"%02d" % t_begin.day}T00:00:00" t_end_formatted = "#{t_end.year}-#{"%02d" % t_end.month}-#{"%02d" % t_end.day}T00:00:00" lat, lon = [32.04, -81.09] do_soap(t_begin_formatted, t_end_formatted, 0, 0) #Will error. do_rest(t_begin_formatted, t_end_formatted, 0, 0) #Will error. do_soap(t_begin_formatted, t_end_formatted, lat, lon) do_rest(t_begin_formatted, t_end_formatted, lat, lon) |