Class: Barometer::WeatherService::Wunderground

Inherits:
Barometer::WeatherService show all
Defined in:
lib/barometer/weather_services/wunderground.rb

Overview

DEFAULT PROVIDER

Weather Underground

www.wunderground.com

  • key required: NO

  • registration required: NO

  • supported countries: ALL

performs geo coding

  • city: YES

  • coordinates: YES

NOTE: provides geo data for location and weather station

time info

  • sun rise/set: YES (today only)

  • provides timezone: YES

  • requires TZInfo: YES

*NOTE: If accuarcy of times and converting, this service is the top choice.

They provide the full timezone name that is needed for the most
accurate time conversions.

resources

Possible queries:

where query can be:

  • zipcode (US or Canadian)

  • city state; city, state

  • city

  • state

  • country

  • airport code (3-letter or 4-letter)

  • lat,lon

Wunderground terms of use

Unable to locate.

Class Method Summary collapse

Methods inherited from Barometer::WeatherService

_build_local_time, _build_timezone, _has_keys?, _keys=, _local_time, _measure, _meets_requirements?, _parse_local_time, _requires_keys?, _supports_country?, _time_result, _timezone, measure, source

Class Method Details

._accepted_formatsObject



55
56
57
# File 'lib/barometer/weather_services/wunderground.rb', line 55

def self._accepted_formats
  [:zipcode, :postalcode, :icao, :coordinates, :geocode]
end

._build_current(data, metric = true) ⇒ Object

Raises:

  • (ArgumentError)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/barometer/weather_services/wunderground.rb', line 102

def self._build_current(data, metric=true)
  raise ArgumentError unless data.is_a?(Hash)
  
  current = Measurement::Result.new
  current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
  current.humidity = data['relative_humidity'].to_i
  current.icon = data['icon'] if data['icon']
  
  current.temperature = Data::Temperature.new(metric)
  current.temperature << [data['temp_c'], data['temp_f']]
  
  current.wind = Data::Speed.new(metric)
  current.wind.mph = data['wind_mph'].to_f
  current.wind.degrees = data['wind_degrees'].to_i
  current.wind.direction = data['wind_dir']
  
  current.pressure = Data::Pressure.new(metric)
  current.pressure << [data['pressure_mb'], data['pressure_in']]
  
  current.dew_point = Data::Temperature.new(metric)
  current.dew_point << [data['dewpoint_c'], data['dewpoint_f']]
  
  current.heat_index = Data::Temperature.new(metric)
  current.heat_index << [data['heat_index_c'], data['heat_index_f']]
  
  current.wind_chill = Data::Temperature.new(metric)
  current.wind_chill << [data['windchill_c'], data['windchill_f']]
  
  current.visibility = Data::Distance.new(metric)
  current.visibility << [data['visibility_km'], data['visibility_mi']]
  
  current
end

._build_extra(measurement, result, metric = true) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/barometer/weather_services/wunderground.rb', line 68

def self._build_extra(measurement, result, metric=true)
  #raise ArgumentError unless measurement.is_a?(Data::Measurement)
  #raise ArgumentError unless query.is_a?(Barometer::Query)

  # use todays sun data for all future days
  if measurement.forecast && measurement.current.sun
    measurement.forecast.each do |forecast|
      forecast.sun = measurement.current.sun
    end
  end
  
  measurement
end

._build_forecast(data, metric = true) ⇒ Object

Raises:

  • (ArgumentError)


136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/barometer/weather_services/wunderground.rb', line 136

def self._build_forecast(data, metric=true)
  raise ArgumentError unless data.is_a?(Hash)
  forecasts = Measurement::ResultArray.new
  # go through each forecast and create an instance
  if data && data['simpleforecast'] &&
     data['simpleforecast']['forecastday']
     
    data['simpleforecast']['forecastday'].each do |forecast|
      forecast_measurement = Measurement::Result.new
      forecast_measurement.icon = forecast['icon']
      forecast_measurement.date = Date.parse(forecast['date']['pretty'])
      forecast_measurement.pop = forecast['pop'].to_i
      
      forecast_measurement.high = Data::Temperature.new(metric)
      forecast_measurement.high << [forecast['high']['celsius'],forecast['high']['fahrenheit']]
      
      forecast_measurement.low = Data::Temperature.new(metric)
      forecast_measurement.low << [forecast['low']['celsius'],forecast['low']['fahrenheit']]
      
      forecasts << forecast_measurement
    end
  end
  forecasts
end


94
95
96
97
98
99
100
# File 'lib/barometer/weather_services/wunderground.rb', line 94

def self._build_links(data)
  links = {}
  if data["credit"] && data["credit_URL"]
    links[data["credit"]] = data["credit_URL"]
  end
  links
end

._build_location(data, geo = nil) ⇒ Object

Raises:

  • (ArgumentError)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/barometer/weather_services/wunderground.rb', line 161

def self._build_location(data, geo=nil)
  raise ArgumentError unless data.is_a?(Hash)
  location = Data::Location.new
  if data['display_location']
    location.name = data['display_location']['full']
    location.city = data['display_location']['city']
    location.state_name = data['display_location']['state_name']
    location.state_code = data['display_location']['state']
    location.country_code = data['display_location']['country']
    location.zip_code = data['display_location']['zip']
    location.latitude = data['display_location']['latitude']
    location.longitude = data['display_location']['longitude']
  end
  location
end

._build_station(data) ⇒ Object

Raises:

  • (ArgumentError)


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/barometer/weather_services/wunderground.rb', line 177

def self._build_station(data)
  raise ArgumentError unless data.is_a?(Hash)
  station = Data::Location.new
  station.id = data['station_id']
  if data['observation_location']
    station.name = data['observation_location']['full']
    station.city = data['observation_location']['city']
    station.state_name = data['observation_location']['state_name']
    station.state_code = data['observation_location']['state']
    station.country_code = data['observation_location']['country']
    station.zip_code = data['observation_location']['zip']
    station.latitude = data['observation_location']['latitude']
    station.longitude = data['observation_location']['longitude']
  end
  station
end

._build_sun(data) ⇒ Object

Raises:

  • (ArgumentError)


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/barometer/weather_services/wunderground.rb', line 194

def self._build_sun(data)
  raise ArgumentError unless data.is_a?(Hash)
  sun = nil
  if data
    if data['moon_phase']
      rise = Data::LocalTime.new(
        data['moon_phase']['sunrise']['hour'].to_i,
        data['moon_phase']['sunrise']['minute'].to_i
      ) if data['moon_phase']['sunrise']
      set = Data::LocalTime.new(
        data['moon_phase']['sunset']['hour'].to_i,
        data['moon_phase']['sunset']['minute'].to_i
      ) if data['moon_phase']['sunset']
      sun = Data::Sun.new(rise,set)
    end
  end
  sun || Data::Sun.new
end

._current_result(data) ⇒ Object

since we have two sets of data, override these calls to choose the right set of data



253
# File 'lib/barometer/weather_services/wunderground.rb', line 253

def self._current_result(data); data[0]; end

._fetch(query, metric = true) ⇒ Object

override default _fetch behavior this service requires TWO seperate http requests (one for current and one for forecasted weather) … combine the results



217
218
219
220
221
222
# File 'lib/barometer/weather_services/wunderground.rb', line 217

def self._fetch(query, metric=true)
  result = []
  result << _fetch_current(query)
  result << _fetch_forecast(query)
  result
end

._fetch_current(query) ⇒ Object

use HTTParty to get the current weather



226
227
228
229
230
231
232
233
234
235
# File 'lib/barometer/weather_services/wunderground.rb', line 226

def self._fetch_current(query)
  return unless query
  puts "fetch wunderground current: #{query.q}" if Barometer::debug?
  self.get(
   "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml",
   :query => {:query => query.q},
   :format => :xml,
   :timeout => Barometer.timeout
   )['current_observation']
end

._fetch_forecast(query) ⇒ Object

use HTTParty to get the forecasted weather



239
240
241
242
243
244
245
246
247
248
# File 'lib/barometer/weather_services/wunderground.rb', line 239

def self._fetch_forecast(query)
  return unless query
  puts "fetch wunderground forecast: #{query.q}" if Barometer::debug?
  self.get(
    "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml",
    :query => {:query => query.q},
    :format => :xml,
    :timeout => Barometer.timeout
  )['forecast']
end

._forecast_result(data = nil) ⇒ Object



254
# File 'lib/barometer/weather_services/wunderground.rb', line 254

def self._forecast_result(data=nil); data[1]; end


257
# File 'lib/barometer/weather_services/wunderground.rb', line 257

def self._links_result(data=nil); data[0]; end

._location_result(data = nil) ⇒ Object



255
# File 'lib/barometer/weather_services/wunderground.rb', line 255

def self._location_result(data=nil); data[0]; end

._parse_full_timezone(data) ⇒ Object

Raises:

  • (ArgumentError)


82
83
84
85
86
87
88
89
90
91
92
# File 'lib/barometer/weather_services/wunderground.rb', line 82

def self._parse_full_timezone(data)
  raise ArgumentError unless data.is_a?(Hash)
  if data && data['simpleforecast'] &&
     data['simpleforecast']['forecastday'] &&
     data['simpleforecast']['forecastday'].first &&
     data['simpleforecast']['forecastday'].first['date']
    Data::Zone.new(
      data['simpleforecast']['forecastday'].first['date']['tz_long']
    )
  end
end

._source_nameObject

PRIVATE If class methods could be private, the remaining methods would be.



54
# File 'lib/barometer/weather_services/wunderground.rb', line 54

def self._source_name; :wunderground; end

._station_result(data = nil) ⇒ Object



256
# File 'lib/barometer/weather_services/wunderground.rb', line 256

def self._station_result(data=nil); data[0]; end

._sun_result(data = nil) ⇒ Object



258
# File 'lib/barometer/weather_services/wunderground.rb', line 258

def self._sun_result(data=nil); data[1]; end

._sunny_icon_codesObject

these are the icon codes that indicate “sun”, used by sunny? function



64
65
66
# File 'lib/barometer/weather_services/wunderground.rb', line 64

def self._sunny_icon_codes
  %w(clear mostlysunny partlysunny sunny partlycloudy)
end

._timezone_result(data = nil) ⇒ Object



259
# File 'lib/barometer/weather_services/wunderground.rb', line 259

def self._timezone_result(data=nil); data[1]; end

._wet_icon_codesObject

these are the icon codes that indicate “wet”, used by wet? function



60
61
62
# File 'lib/barometer/weather_services/wunderground.rb', line 60

def self._wet_icon_codes
  %w(flurries rain sleet snow tstorms nt_flurries nt_rain nt_sleet nt_snow nt_tstorms chancerain chancetstorms)
end