ClearOS‎ > ‎Ruby‎ > ‎

NOAA NWS NDFD

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:
General information about the NDFD: http://www.weather.gov/ndfd/
Definition of element names for queries: http://www.weather.gov/forecasts/xml/docs/elementInputNames.php
Definition of available elements: http://www.nws.noaa.gov/ndfd/definitions.htm


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)
Comments