Class: Barometer::WeatherService::WeatherDotCom

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

Overview

Weather.com

www.weather.com

  • key required: YES (partnerid & licensekey)

  • registration required: YES

  • supported countries: US (by zipcode), International (by Weather Location ID)

performs geo coding

  • city: PARTIAL (just a name)

  • coordinates: YES

time info

  • sun rise/set: YES

  • provides timezone: NO, but provides a utc offset

  • requires TZInfo: NO

resources

  • API: ?

Possible queries:

where query can be:

  • zipcode (US) [5 digits only]

  • Weather Location ID (International)

Weather.com terms of use

???

notes

  • the Weather Location ID is a propreitary number (possibly shared with yahoo.com)

TODO

  • improve “forecasted_wet_by_icon?” to determine if day or night and use right code

  • improve “forecasted_sunny_by_icon?” to determine if day or night and use right code

  • improve “forcasted_wet_by_humidity?” to use forecasted values

  • improve “forcasted_windy?” to use forecasted values

Constant Summary collapse

@@partner_key =
nil
@@license_key =
nil

Class Method Summary collapse

Methods inherited from Barometer::WeatherService

_build_extra, _build_local_time, _build_station, _current_result, _forecast_result, _keys=, _links_result, _local_time, _location_result, _measure, _meets_requirements?, _parse_full_timezone, _station_result, _sun_result, _supports_country?, _time_result, _timezone, _timezone_result, measure, source

Class Method Details

._accepted_formatsObject



60
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 60

def self._accepted_formats; [:short_zipcode, :weather_id]; end

._build_current(data, metric = true) ⇒ Object

Raises:

  • (ArgumentError)


101
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
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 101

def self._build_current(data, metric=true)
  raise ArgumentError unless data.is_a?(Hash)
  current = Measurement::Current.new
  if data
    if data['cc']
      current.updated_at = Data::LocalDateTime.parse(data['cc']['lsup'])
      current.icon = data['cc']['icon']
      current.condition = data['cc']['t']
      current.humidity = data['cc']['hmid'].to_i
      current.temperature = Data::Temperature.new(metric)
      current.temperature << data['cc']['tmp']
      current.dew_point = Data::Temperature.new(metric)
      current.dew_point << data['cc']['dewp']
      current.wind_chill = Data::Temperature.new(metric)
      current.wind_chill << data['cc']['flik']
      current.visibility = Data::Distance.new(metric)
      current.visibility << data['cc']['vis']
      if data['cc']['wind']
        current.wind = Data::Speed.new(metric)
        current.wind << data['cc']['wind']['s']
        current.wind.degrees = data['cc']['wind']['d'].to_f
        current.wind.direction = data['cc']['wind']['t']
      end
      if data['cc']['bar']
        current.pressure = Data::Pressure.new(metric)
        current.pressure << data['cc']['bar']['r']
      end
    end
  end
  current
end

._build_forecast(data, metric = true) ⇒ Object

Raises:

  • (ArgumentError)


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 133

def self._build_forecast(data, metric=true)
  raise ArgumentError unless data.is_a?(Hash)
  forecasts = Measurement::ForecastArray.new

  if data && data['dayf'] && data['dayf']['day']
    local_date = data['dayf']['lsup']
    data['dayf']['day'].each do |forecast|
      forecast_measurement = Measurement::Forecast.new
      forecast_measurement.date = Date.parse(forecast['dt'])
      
      forecast_measurement.high = Data::Temperature.new(metric)
      forecast_measurement.high << forecast['hi']
      forecast_measurement.low = Data::Temperature.new(metric)
      forecast_measurement.low << forecast['low']
      
      # build sun
      rise_local_time = Data::LocalTime.parse(forecast['sunr'])
      set_local_time = Data::LocalTime.parse(forecast['suns'])
      sun = Data::Sun.new(rise_local_time, set_local_time)
      forecast_measurement.sun = sun
      
      if forecast['part']
        forecast['part'].each do |part|
          if part['p'] == 'd'
            # add this to the ForecastMeasurement
            forecast_measurement.condition = part['t']
            forecast_measurement.icon = part['icon']
            forecast_measurement.pop = part['ppcp'].to_i
            forecast_measurement.humidity = part['hmid'].to_i
            
            if part['wind']
              forecast_measurement.wind = Data::Speed.new(metric)
              forecast_measurement.wind << part['wind']['s']
              forecast_measurement.wind.degrees = part['wind']['d'].to_i
              forecast_measurement.wind.direction = part['wind']['t']
            end
            
          elsif part['p'] == 'n'  
            # add this to the NightMeasurement
            forecast_measurement.night = Measurement::ForecastNight.new
            forecast_measurement.night.condition = part['t']
            forecast_measurement.night.icon = part['icon']
            forecast_measurement.night.pop = part['ppcp'].to_i
            forecast_measurement.night.humidity = part['hmid'].to_i
            
            if part['wind']
              forecast_measurement.night.wind = Data::Speed.new(metric)
              forecast_measurement.night.wind << part['wind']['s']
              forecast_measurement.night.wind.degrees = part['wind']['d'].to_i
              forecast_measurement.night.wind.direction = part['wind']['t']
            end
            
          end
        end
      end
      forecasts << forecast_measurement
    end
  end
  forecasts
end


91
92
93
94
95
96
97
98
99
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 91

def self._build_links(data)
  links = {}
  if data && data['lnks'] && data['lnks']['link']
    data['lnks']['link'].each do |link_hash|
      links[link_hash['t']] = link_hash['l']
    end
  end
  links
end

._build_location(data, geo = nil) ⇒ Object

Raises:

  • (ArgumentError)


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

def self._build_location(data, geo=nil)
  raise ArgumentError unless data.is_a?(Hash)
  raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
  location = Data::Location.new
  # use the geocoded data if available, otherwise get data from result
  if geo
    location.city = geo.locality
    location.state_code = geo.region
    location.country = geo.country
    location.country_code = geo.country_code
    location.latitude = geo.latitude
    location.longitude = geo.longitude
  else
    if data && data['loc']
      location.name = data['loc']['dnam']
      location.latitude = data['loc']['lat']
      location.longitude = data['loc']['lon']
    end
  end
  location
end

._build_sun(data) ⇒ Object

Raises:

  • (ArgumentError)


216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 216

def self._build_sun(data)
  raise ArgumentError unless data.is_a?(Hash)
  sun = nil
  if data
    if data['loc']
      rise_local_time = Data::LocalTime.parse(data['loc']['sunr'])
      set_local_time = Data::LocalTime.parse(data['loc']['suns'])
    end  
    sun = Data::Sun.new(rise_local_time, set_local_time)
  end
  sun || Data::Sun.new
end

._build_timezone(data) ⇒ Object

first try to match the zone code, otherwise use the zone offset



76
77
78
79
80
81
82
83
84
85
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 76

def self._build_timezone(data)
  if data
    if data['cc'] && data['cc']['lsup'] &&
       (zone_match = data['cc']['lsup'].match(/ ([A-Z]{1,4})$/))
      Data::Zone.new(zone_match[1])
    elsif data['loc'] && data['loc']['zone']
      Data::Zone.new(data['loc']['zone'].to_f)
    end
  end
end

._fetch(query, metric = true) ⇒ Object

use HTTParty to get the current weather



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 231

def self._fetch(query, metric=true)
  return unless query
  puts "fetch weather.com: #{query.q}" if Barometer::debug?
  self.get(
    "http://xoap.weather.com/weather/local/#{query.q}",
    :query => { :par => @@partner_key, :key => @@license_key,
      :prod => "xoap", :link => "xoap", :cc => "*",
      :dayf => "5", :unit => (metric ? 'm' : 's')
    },
    :format => :xml,
    :timeout => Barometer.timeout
  )['weather']
end

._has_keys?Boolean

Returns:

  • (Boolean)


62
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 62

def self._has_keys?; !@@partner_key.nil? && !@@license_key.nil?; end

._parse_local_time(data) ⇒ Object



87
88
89
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 87

def self._parse_local_time(data)
  (data && data['loc']) ? Data::LocalTime.parse(data['loc']['tm']) : nil
end

._requires_keys?Boolean

Returns:

  • (Boolean)


63
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 63

def self._requires_keys?; true; end

._source_nameObject

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



59
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 59

def self._source_name; :weather_dot_com; end

._sunny_icon_codesObject



69
70
71
72
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 69

def self._sunny_icon_codes
  codes = [19, 22, 28, 30, 32, 34, 36]
  codes.collect {|c| c.to_s}
end

._wet_icon_codesObject



65
66
67
68
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 65

def self._wet_icon_codes
  codes = (0..18).to_a + [35] + (37..43).to_a + (45..47).to_a
  codes.collect {|c| c.to_s}
end

.keys=(keys) ⇒ Object

Raises:

  • (ArgumentError)


46
47
48
49
50
51
52
# File 'lib/barometer/weather_services/weather_dot_com.rb', line 46

def self.keys=(keys)
  raise ArgumentError unless keys.is_a?(Hash)
  keys.each do |key, value|
    @@partner_key = value.to_s if key.to_s.downcase == "partner"
    @@license_key = value.to_s if key.to_s.downcase == "license"
  end
end