noaaer 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in noaaer.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ raise 'hi'
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'noaaer')
5
+
6
+ begin
7
+ file = File.open(File.join(File.dirname(__FILE__), '..', 'data', 'stations.yml'), 'w')
8
+ puts 'Downloading station list from NOAA...'
9
+ doc = Noaaer::HttpService.new.get_station_list
10
+ puts 'Converting station list to YAML...'
11
+ Noaaer::StationWriter.new(doc).write(file)
12
+ puts "Done."
13
+ end
@@ -0,0 +1,185 @@
1
+ module Noaaer
2
+ #
3
+ # Representation of the current conditions for a given observation point.
4
+ #
5
+ class CurrentConditions
6
+
7
+ class <<self
8
+ private :new
9
+
10
+ def from_xml(doc) #:nodoc:
11
+ new(doc)
12
+ end
13
+ end
14
+
15
+ def initialize(doc) #:notnew:
16
+ @doc = doc
17
+ end
18
+
19
+ #
20
+ # Time object containing the time at which these conditions were observed at the NOAA station
21
+ #
22
+ def observed_at
23
+ @observed_at ||= Time.parse(text_from_node('observation_time_rfc822'))
24
+ end
25
+
26
+ #
27
+ # Text description of the current weather conditions, e.g. "Fair"
28
+ #
29
+ def weather_description
30
+ @weather_description ||= text_from_node('weather')
31
+ end
32
+ alias_method :weather_summary, :weather_description
33
+
34
+ #
35
+ # NWS code representing weather type. This distills the #weather_description
36
+ # into one of a much more manageable set of possibilities. Possible values are:
37
+ #
38
+ # - <code>:skc</code> - Clear
39
+ # - <code>:wind</code> - Windy
40
+ # - <code>:few</code> - A Few Clouds
41
+ # - <code>:sct</code> - Partly Cloudy
42
+ # - <code>:bkn</code> - Mostly Cloudy
43
+ # - <code>:ovc</code> - Overcast
44
+ # - <code>:ra1</code> - Light Rain
45
+ # - <code>:ra</code> - Rain
46
+ # - <code>:shra</code> - Rain Showers
47
+ # - <code>:tsra</code> - Thunderstorms
48
+ # - <code>:ip</code> - Hail
49
+ # - <code>:fzra</code> - Freezing Rain
50
+ # - <code>:mix</code> - Wintry Mix
51
+ # - <code>:sn</code> - Snow
52
+ # - <code>:fg</code> - Fog
53
+ # - <code>:smoke</code> - Smoke
54
+ # - <code>:dust</code> - Dust/Sand
55
+ # - <code>:mist</code> - Haze
56
+ # - <code>:svrtsra</code> - Tornado
57
+ # - <code>:fzrara</code> - Freezing Rain/Rain
58
+ # - <code>:raip</code> - Rain/Hail
59
+ # - <code>:rasn</code> - Rain/Snow
60
+ # - <code>:hi_shwrs</code> - Showers in Vicinity
61
+ # - <code>:hi_tsra</code> - Thunderstorm in Vicinity
62
+ #
63
+ # See http://www.weather.gov/xml/current_obs/weather.php for the NWS's list of possible
64
+ # descriptions and their type codes.
65
+ #
66
+ def weather_type_code
67
+ @weather_type_code ||= text_from_node('icon_url_name').gsub(/^n|\.jpg$/, '').to_sym
68
+ end
69
+
70
+ #
71
+ # Return the NWS image URL for the current weather as string
72
+ #
73
+ def image_url
74
+ @image_url ||= "#{text_from_node('icon_url_base')}#{text_from_node('icon_url_name')}"
75
+ end
76
+
77
+ #
78
+ # The current temperature in the requested units.
79
+ #
80
+ # conditions.temperature #=> temperature in fahrenheit
81
+ # conditions.temperature(:c) #=> temperature in celsius
82
+ # conditions.temperature(:kelvin) #=> anything else raises an exception
83
+ #
84
+ def temperature(unit = :f)
85
+ text_from_node_with_unit('temp', unit, :f, :c).to_i
86
+ end
87
+
88
+ #
89
+ # The current relative humidity percentage (0-100)
90
+ #
91
+ def relative_humidity
92
+ text_from_node('relative_humidity').to_i
93
+ end
94
+
95
+ #
96
+ # The current cardinal or ordinal direction that the wind is coming from (e.g., "Northwest")
97
+ #
98
+ def wind_direction
99
+ text_from_node('wind_dir')
100
+ end
101
+
102
+ #
103
+ # The current direction that the wind is coming from degrees (e.g. 330)
104
+ #
105
+ def wind_degrees
106
+ text_from_node('wind_degrees').to_i
107
+ end
108
+
109
+ #
110
+ # The current wind speed in miles per hour as a float (e.g., 3.45)
111
+ #
112
+ def wind_speed
113
+ text_from_node('wind_mph').to_f
114
+ end
115
+
116
+ #
117
+ # The current wind gust in miles per hour as a float, or nil if none
118
+ #
119
+ def wind_gust
120
+ text_from_node('wind_gust_mph').to_f
121
+ end
122
+
123
+ #
124
+ # The current barometric pressure
125
+ #
126
+ # conditions.pressure #=> pressure in inches
127
+ # conditions.pressure(:mb) #=> pressure in millibars
128
+ # conditions.pressure(:psi) #=> anything else raises an exception
129
+ #
130
+ def pressure(unit = :in)
131
+ text_from_node_with_unit('pressure', unit, :in, :mb).to_f
132
+ end
133
+
134
+ #
135
+ # The current dew point.
136
+ #
137
+ # conditions.dew_point #=> dew point in fahrenheit
138
+ # conditions.dew_point(:c) #=> dew point in celsius
139
+ # conditions.dew_point(:kelvin) #=> anything else raises an exception
140
+ #
141
+ def dew_point(unit = :f)
142
+ text_from_node_with_unit('dewpoint', unit, :f, :c).to_i
143
+ end
144
+
145
+ #
146
+ # The current heat index
147
+ #
148
+ # conditions.heat_index #=> heat index in fahrenheit
149
+ # conditions.heat_index(:c) #=> heat index in celsius
150
+ # conditions.heat_index(:kelvin) #=> anything else raises an exception
151
+ #
152
+ def heat_index(unit = :f)
153
+ text_from_node_with_unit('heat_index', unit, :f, :c).to_i
154
+ end
155
+
156
+ #
157
+ # The current wind chill
158
+ #
159
+ # conditions.wind_chill #=> wind chill in fahrenheit
160
+ # conditions.wind_chill(:c) #=> wind chill in celsius
161
+ # conditions.wind_chill(:kelvin) #=> anything else raises an exception
162
+ #
163
+ def wind_chill(unit = :f)
164
+ text_from_node_with_unit('windchill', unit, :f, :c).to_i
165
+ end
166
+
167
+ #
168
+ # The current visibility in miles
169
+ #
170
+ def visibility
171
+ text_from_node('visibility_mi').to_f
172
+ end
173
+
174
+ private
175
+
176
+ def text_from_node(element_name)
177
+ @doc.xpath("/current_observation/#{element_name}[1]/child::text()").first.to_s
178
+ end
179
+
180
+ def text_from_node_with_unit(element_name, unit, *allowed_units)
181
+ raise ArgumentError, "Unknown unit #{unit.inspect} - allowed units are #{allowed_units.inspect}" unless allowed_units.include?(unit)
182
+ text_from_node("#{element_name}_#{unit}")
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,108 @@
1
+ module Noaaer
2
+ #
3
+ # A Forecast object represents a multi-day forecast for a particular place. The forecast for a given day can
4
+ # be accessed using the [] method; e.g. (assuming +forecast+ is a forecast for 12/20/2008 - 12/24/2008):
5
+ #
6
+ # forecast[1] #=> ForecastDay for 12/21/2008
7
+ # forecast.length #=> 4
8
+ #
9
+ class Forecast
10
+
11
+ class <<self
12
+ private :new
13
+
14
+ def from_xml(doc) #:nodoc:
15
+ new(doc)
16
+ end
17
+ end
18
+
19
+ def initialize(doc) #:noinit:
20
+ @doc = doc
21
+ end
22
+
23
+ #
24
+ # The number of days provided by the forecast
25
+ #
26
+ def length
27
+ @length ||= @doc.find(%q{/dwml/data/time-layout[@summarization='24hourly'][1]/start-valid-time}).length
28
+ end
29
+
30
+ #
31
+ # Get the ForecastDay for day i
32
+ #
33
+ # forecast[1] #=> returns the ForecastDay for the second day
34
+ #
35
+ def [](i)
36
+ forecast_days[i]
37
+ end
38
+
39
+ private
40
+
41
+ def forecast_days
42
+ @forecast_days ||= begin
43
+ days = []
44
+ length.times do |i|
45
+ days << day = NOAA::ForecastDay.new
46
+ day.starts_at = starts[i]
47
+ day.ends_at = ends[i]
48
+ day.high = maxima[i]
49
+ day.low = minima[i]
50
+ day.weather_summary = weather_summaries[i]
51
+ day.weather_type_code = weather_type_codes[i]
52
+ day.image_url = image_urls[i]
53
+ day.daytime_precipitation_probability = precipitation_probabilities[i*2]
54
+ day.evening_precipitation_probability = precipitation_probabilities[i*2+1]
55
+ end
56
+ days
57
+ end
58
+ end
59
+
60
+ def starts
61
+ @starts ||= @doc.find(%q{/dwml/data/time-layout[@summarization='24hourly'][1]/start-valid-time/text()}).map do |node|
62
+ Time.parse(node.to_s)
63
+ end
64
+ end
65
+
66
+ def ends
67
+ @ends ||= @doc.find(%q{/dwml/data/time-layout[@summarization='24hourly'][1]/end-valid-time/text()}).map do |node|
68
+ Time.parse(node.to_s)
69
+ end
70
+ end
71
+
72
+ def maxima
73
+ @maxima ||= @doc.find(%q{/dwml/data/parameters[1]/temperature[@type='maximum'][@units='Fahrenheit'][1]/value/text()}).map do |node|
74
+ node.to_s.to_i
75
+ end
76
+ end
77
+
78
+ def minima
79
+ @minima ||= @doc.find(%q{/dwml/data/parameters[1]/temperature[@type='minimum'][@units='Fahrenheit'][1]/value/text()}).map do |node|
80
+ node.to_s.to_i
81
+ end
82
+ end
83
+
84
+ def weather_summaries
85
+ @weather_summaries ||= @doc.find(%q{/dwml/data/parameters[1]/weather[1]/weather-conditions}).map do |node|
86
+ node['weather-summary'].to_s
87
+ end
88
+ end
89
+
90
+ def image_urls
91
+ @image_urls ||= @doc.find(%q{/dwml/data/parameters[1]/conditions-icon/icon-link/text()}).map do |node|
92
+ node.to_s
93
+ end
94
+ end
95
+
96
+ def weather_type_codes
97
+ @weather_type_codes ||= image_urls.map do |url|
98
+ url.match(/n?([a-z_]+)\d*\.jpg$/)[1].to_sym
99
+ end
100
+ end
101
+
102
+ def precipitation_probabilities
103
+ @precipitation_probabilities ||= @doc.find(%q{/dwml/data/parameters[1]/probability-of-precipitation[1]/value/text()}).map do |node|
104
+ node.to_s.to_i
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,38 @@
1
+ module Noaaer
2
+ #
3
+ # A ForecastDay contains forecast data for a single day. Each day should start at 6am and
4
+ # end at 6am the following day (assuming that is invariant on the part of the NOAA's data
5
+ # feed). ForecastDay objects are accessed using NOAA::Forecast#[]
6
+ class ForecastDay
7
+ # Time when this forecast's valid time span begins
8
+ attr_reader :starts_at
9
+
10
+ # Time when this forecast's valid time span ends
11
+ attr_reader :ends_at
12
+
13
+ # High temperature for the day in Fahrenheit
14
+ attr_reader :high
15
+
16
+ # Low temperature for the day in Fahrenheit
17
+ attr_reader :low
18
+
19
+ # String summary of weather (e.g., 'Fair')
20
+ attr_reader :weather_summary
21
+ alias_method :weather_description, :weather_summary
22
+
23
+ # Symbol representing NOAA weather type. See NOAA::CurrentConditions#weather_type_code
24
+ attr_reader :weather_type_code
25
+
26
+ # URL string for NOAA weather image
27
+ attr_reader :image_url
28
+
29
+ # Percentage probability of precipitation during the day, between 6am and 6pm, as an integer (0-100)
30
+ attr_reader :daytime_precipitation_probability
31
+
32
+ # Percentage probability of precipitation during the evening/night, between 6pm and 6am, as an integer (0-100)
33
+ attr_reader :evening_precipitation_probability
34
+
35
+ attr_writer :starts_at, :ends_at, :high, :low, :weather_summary, :weather_type_code, :image_url, #:nodoc:
36
+ :daytime_precipitation_probability, :evening_precipitation_probability #:nodoc:
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ # require 'libxml'
2
+
3
+ module Noaaer
4
+ class HttpService #:nodoc:
5
+ def initialize(http = Net::HTTP)
6
+ @HTTP = http
7
+ end
8
+
9
+ def get_current_conditions(station_id)
10
+ @HTTP.get(URI.parse("http://www.weather.gov/xml/current_obs/#{station_id}.xml"))
11
+ end
12
+
13
+ def get_forecast(num_days, lat, lng)
14
+ @HTTP.get(URI.parse("http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?lat=#{lat}&lon=#{lng}&format=24+hourly&numDays=#{num_days}"))
15
+ end
16
+
17
+ def get_station_list
18
+ @HTTP.get(URI.parse("http://www.weather.gov/xml/current_obs/index.xml"))
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,111 @@
1
+ module Noaaer
2
+ #
3
+ # Data about an NOAA observation station. When accessing current conditions, the NOAA XML API
4
+ # takes a station ID as input; thus, to find the current conditions for an arbitrary location, one
5
+ # must first determine the closest weather station to that location. The NOAA.current_conditions
6
+ # method performs this task implicitly; however, for applications that need to find conditions
7
+ # for the same location(s) repeatedly, it is far more efficient to find the closest weather station
8
+ # once, store that information, and then query directly against the weather station when updated
9
+ # conditions are needed.
10
+ #
11
+ # Station data is stored in a YAML file that is created using the <tt>noaa-update-stations</tt> executable.
12
+ # Be sure to run this command at least once when you first install the NOAA library, and any time
13
+ # thereafter that you would like to get the latest list of stations. I don't imagine the list
14
+ # changes very often but I don't really have any idea.
15
+ #
16
+ class Station
17
+ class <<self
18
+ attr_writer :stations_file #:nodoc:
19
+
20
+ #
21
+ # Retrieve information about a station given a station ID
22
+ #
23
+ # NOAA::Station.find('KNYC') #=> NOAA::Station object for the Central Park station
24
+ def find(id)
25
+ stations.find { |station| station.id == id }
26
+ end
27
+
28
+ #
29
+ # Find the station closest to a given location. Can accept arguments in any of the following
30
+ # three forms (all are equivalent):
31
+ #
32
+ # NOAA::Station.closest_to(37.989, -77.507)
33
+ # NOAA::Station.closest_to([37.989, -77.507])
34
+ # NOAA::Station.closest_to(GeoKit::LatLng.new(37.989, -77.507))
35
+ def closest_to(*args)
36
+ if args.length == 1
37
+ if args.first.respond_to?(:distance_to)
38
+ closest_to_coordinates(args.first)
39
+ elsif %w(first last).all? { |m| args.first.respond_to?(m) }
40
+ closest_to_lat_lng(args.first)
41
+ else
42
+ raise ArgumentError, "expected two-element Array or GeoKit::LatLng"
43
+ end
44
+ elsif args.length == 2
45
+ closest_to_lat_lng(args)
46
+ else
47
+ raise ArgumentError, "closest_to() will accept one Array argument, one GeoKit::LatLng argument, or two FixNum arguments"
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def closest_to_lat_lng(pair)
54
+ closest_to_coordinates(GeoKit::LatLng.new(pair.first, pair.last))
55
+ end
56
+
57
+ def closest_to_coordinates(coordinates)
58
+ stations.map do |station|
59
+ [coordinates.distance_to(station.coordinates), station]
60
+ end.min do |p1, p2|
61
+ p1.first <=> p2.first # compare distance
62
+ end[1]
63
+ end
64
+
65
+ def stations
66
+ File.open(stations_file) do |file|
67
+ yaml = YAML.load(file) || raise("Can't parse #{file.path} - be sure to run noaa-update-stations")
68
+ yaml.map { |station_hash| new(station_hash) }
69
+ end
70
+ end
71
+
72
+ def stations_file
73
+ @stations_file ||= File.join(File.dirname(__FILE__), '..', '..', 'data', 'stations.yml')
74
+ end
75
+ end
76
+
77
+ # GeoKit::LatLng containing the station's coordinates
78
+ attr_reader :coordinates
79
+
80
+ # Station ID (e.g., "KNYC")
81
+ attr_reader :id
82
+
83
+ # Station name (e.g., "New York City, Central Park")
84
+ attr_reader :name
85
+
86
+ # Two-digit abbreviation for state in which station resides (e.g., "NY")
87
+ attr_reader :state
88
+
89
+ attr_reader :xml_url #:nodoc:
90
+
91
+ def initialize(properties)
92
+ @id, @name, @state, @xml_url = %w(id name state xml_url).map do |p|
93
+ properties[p]
94
+ end
95
+ @coordinates = GeoKit::LatLng.new(properties['latitude'], properties['longitude'])
96
+ end
97
+
98
+ # Latitude of station
99
+ def latitude
100
+ @coordinates.lat
101
+ end
102
+ alias_method :lat, :latitude
103
+
104
+ # Longitude of station
105
+ def longitude
106
+ @coordinates.lng
107
+ end
108
+ alias_method :lng, :longitude
109
+ alias_method :lon, :longitude
110
+ end
111
+ end
@@ -0,0 +1,26 @@
1
+ module Noaeer
2
+ class StationWriter
3
+ def initialize(doc)
4
+ @doc = doc
5
+ end
6
+
7
+ def write(io)
8
+ YAML.dump(@doc.find('/wx_station_index/station').map { |node| node_to_hash(node) }, io)
9
+ end
10
+
11
+ private
12
+
13
+ def node_to_hash(node)
14
+ { 'latitude' => node_value(node, 'latitude').to_f,
15
+ 'longitude' => node_value(node, 'longitude').to_f,
16
+ 'id' => node_value(node, 'station_id'),
17
+ 'name' => node_value(node, 'station_name'),
18
+ 'state' => node_value(node, 'state'),
19
+ 'xml_url' => node_value(node, 'xml_url') }
20
+ end
21
+
22
+ def node_value(node, element)
23
+ node.find("./#{element}/text()").first.to_s
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Noaaer
2
+ VERSION = "0.0.4"
3
+ end
data/lib/noaaer.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'time'
2
+ require 'nokogiri'
3
+ require 'geokit'
4
+
5
+ %w(current_conditions forecast forecast_day http_service station station_writer).each { |file| require File.join(File.dirname(__FILE__), 'noaaer', file) }
6
+
7
+ #
8
+ # The NOAA singleton provides methods to conveniently access information from the NOAA weather feed.
9
+ # For the most part, NOAA.current_conditions and NOAA.forecast will be the only entry point into the
10
+ # NOAA API you will need; one exception is discussed below.
11
+ #
12
+ module Noaaer
13
+ autoload :VERSION, File.join(File.dirname(__FILE__), 'noaaer', 'version')
14
+
15
+ class << self
16
+ #
17
+ # Retrieve the current weather conditions for a given latitude and longitude. Returns an
18
+ # instance of NOAA::CurrentConditions.
19
+ #
20
+ # NOAA.current_conditions(37.989, -77.507) #=> NOAA::CurrentConditions encapsulating current conditions at this point
21
+ #
22
+ # <b>Note:</b> This method parses the stored list of all weather stations in the US and then finds the closest one to
23
+ # the given coordinates, as the NOAA XML API only takes a weather station ID as input. Clearly, this is an expensive
24
+ # operation; if your application needs to repeatedly request conditions for the same point, you will be much better off
25
+ # determining the current station once using NOAA::Station.closest_to, storing the station ID, and then passing it into
26
+ # NOAA.current_conditions_at_station when you need to get the latest conditions.
27
+ #
28
+ def current_conditions(lat, lng)
29
+ current_conditions_at_station(Station.closest_to(lat, lng).id)
30
+ end
31
+
32
+ #
33
+ # Retrieve the current weather conditions for a given weather station ID. Returns an
34
+ # instance of NOAA::CurrentConditions.
35
+ #
36
+ # NOAA.current_conditions_at_station('KNYC') #=> NOAA::CurrentConditions encapsulating current conditions in Central Park
37
+ #
38
+ # See discussion above regarding why this method is often preferable to simply calling #current_conditions.
39
+ #
40
+ def current_conditions_at_station(station_id)
41
+ CurrentConditions.from_xml(HttpService.new.get_current_conditions(station_id))
42
+ end
43
+
44
+ #
45
+ # Retrieve daily forecast information for a given latitude and longitude. Returns
46
+ # an instance of NOAA::Forecast.
47
+ #
48
+ # NOAA.forecast(4, 37.989, -77.507) #=> NOAA::Forecast containing next four days of forecast data for given coordinates
49
+ #
50
+ # <b>Note:</b> The NOAA updates this data no more than once an hour, and asks that users of the API not request the forecast
51
+ # for a given location more frequently than that. For more information, please see http://www.nws.noaa.gov/xml/#frequency
52
+ #
53
+ def forecast(num_days, lat, lng)
54
+ Forecast.from_xml(HttpService.new.get_forecast(num_days, lat, lng))
55
+ end
56
+ end
57
+ end
data/noaaer.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "noaaer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "noaaer"
7
+ s.version = Noaaer::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Cody Swann, Gunner Technology"]
10
+ s.email = ["developers@gunnertech.com"]
11
+ s.homepage = "http://gunnertech.com"
12
+ s.summary = %q{Wrapper for NOAA Weather Service API}
13
+ s.description = %q{This gem will help you utilize the NOAA API for weather data}
14
+
15
+ s.rubyforge_project = "noaaer"
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: noaaer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.4
6
+ platform: ruby
7
+ authors:
8
+ - Cody Swann, Gunner Technology
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-14 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: This gem will help you utilize the NOAA API for weather data
18
+ email:
19
+ - developers@gunnertech.com
20
+ executables:
21
+ - noaa-update-stations
22
+ extensions: []
23
+
24
+ extra_rdoc_files: []
25
+
26
+ files:
27
+ - .gitignore
28
+ - Gemfile
29
+ - Rakefile
30
+ - bin/noaa-update-stations
31
+ - lib/noaaer.rb
32
+ - lib/noaaer/current_conditions.rb
33
+ - lib/noaaer/forecast.rb
34
+ - lib/noaaer/forecast_day.rb
35
+ - lib/noaaer/http_service.rb
36
+ - lib/noaaer/station.rb
37
+ - lib/noaaer/station_writer.rb
38
+ - lib/noaaer/version.rb
39
+ - noaaer.gemspec
40
+ has_rdoc: true
41
+ homepage: http://gunnertech.com
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project: noaaer
64
+ rubygems_version: 1.6.0
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Wrapper for NOAA Weather Service API
68
+ test_files: []
69
+