barometer 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +7 -0
- data/LICENSE +1 -1
- data/{README.rdoc → README.md} +124 -110
- data/Rakefile +1 -21
- data/TODO +8 -9
- data/barometer.gemspec +20 -19
- data/bin/barometer +36 -83
- data/lib/barometer.rb +13 -11
- data/lib/barometer/base.rb +10 -10
- data/lib/barometer/data.rb +1 -1
- data/lib/barometer/data/distance.rb +25 -25
- data/lib/barometer/data/geo.rb +9 -9
- data/lib/barometer/data/local_datetime.rb +24 -20
- data/lib/barometer/data/local_time.rb +13 -13
- data/lib/barometer/data/location.rb +6 -6
- data/lib/barometer/data/pressure.rb +24 -24
- data/lib/barometer/data/speed.rb +28 -28
- data/lib/barometer/data/sun.rb +7 -7
- data/lib/barometer/data/temperature.rb +29 -29
- data/lib/barometer/data/units.rb +9 -9
- data/lib/barometer/data/zone.rb +19 -19
- data/lib/barometer/formats.rb +1 -1
- data/lib/barometer/formats/coordinates.rb +7 -7
- data/lib/barometer/formats/format.rb +6 -6
- data/lib/barometer/formats/geocode.rb +5 -5
- data/lib/barometer/formats/icao.rb +6 -6
- data/lib/barometer/formats/postalcode.rb +3 -3
- data/lib/barometer/formats/short_zipcode.rb +2 -2
- data/lib/barometer/formats/weather_id.rb +10 -10
- data/lib/barometer/formats/woe_id.rb +20 -20
- data/lib/barometer/formats/zipcode.rb +3 -3
- data/lib/barometer/key_file_parser.rb +20 -0
- data/lib/barometer/measurements/measurement.rb +32 -32
- data/lib/barometer/measurements/result.rb +39 -39
- data/lib/barometer/measurements/result_array.rb +12 -12
- data/lib/barometer/query.rb +15 -15
- data/lib/barometer/services.rb +3 -3
- data/lib/barometer/translations/icao_country_codes.yml +20 -20
- data/lib/barometer/translations/weather_country_codes.yml +1 -1
- data/lib/barometer/translations/zone_codes.yml +2 -2
- data/lib/barometer/version.rb +3 -0
- data/lib/barometer/weather.rb +27 -27
- data/lib/barometer/weather_services/noaa.rb +314 -3
- data/lib/barometer/weather_services/service.rb +32 -30
- data/lib/barometer/weather_services/weather_bug.rb +35 -33
- data/lib/barometer/weather_services/wunderground.rb +31 -29
- data/lib/barometer/weather_services/yahoo.rb +36 -35
- data/lib/barometer/web_services/geocode.rb +5 -7
- data/lib/barometer/web_services/noaa_station_id.rb +53 -0
- data/lib/barometer/web_services/placemaker.rb +11 -13
- data/lib/barometer/web_services/timezone.rb +5 -7
- data/lib/barometer/web_services/weather_id.rb +4 -6
- data/lib/barometer/web_services/web_service.rb +4 -4
- data/spec/barometer_spec.rb +25 -27
- data/spec/cassettes/Barometer.json +1 -0
- data/spec/cassettes/Query.json +1 -0
- data/spec/cassettes/Query_Format_Coordinates.json +1 -0
- data/spec/cassettes/Query_Format_Geocode.json +1 -0
- data/spec/cassettes/Query_Format_WeatherID.json +1 -0
- data/spec/cassettes/Query_Format_WoeID.json +1 -0
- data/spec/cassettes/WeatherService.json +1 -0
- data/spec/cassettes/WeatherService_Noaa.json +1 -0
- data/spec/cassettes/WeatherService_WeatherBug.json +1 -0
- data/spec/cassettes/WeatherService_Wunderground.json +1 -0
- data/spec/cassettes/WeatherService_Yahoo.json +1 -0
- data/spec/cassettes/WebService_Geocode.json +1 -0
- data/spec/cassettes/WebService_NoaaStation.json +1 -0
- data/spec/data/distance_spec.rb +60 -60
- data/spec/data/geo_spec.rb +23 -23
- data/spec/data/local_datetime_spec.rb +44 -44
- data/spec/data/local_time_spec.rb +47 -47
- data/spec/data/location_spec.rb +16 -16
- data/spec/data/pressure_spec.rb +61 -61
- data/spec/data/speed_spec.rb +69 -69
- data/spec/data/sun_spec.rb +25 -25
- data/spec/data/temperature_spec.rb +68 -68
- data/spec/data/units_spec.rb +21 -21
- data/spec/data/zone_spec.rb +35 -35
- data/spec/formats/coordinates_spec.rb +27 -27
- data/spec/formats/format_spec.rb +17 -25
- data/spec/formats/geocode_spec.rb +23 -31
- data/spec/formats/icao_spec.rb +26 -32
- data/spec/formats/postalcode_spec.rb +22 -28
- data/spec/formats/short_zipcode_spec.rb +20 -26
- data/spec/formats/weather_id_spec.rb +57 -67
- data/spec/formats/woe_id_spec.rb +59 -59
- data/spec/formats/zipcode_spec.rb +39 -47
- data/spec/key_file_parser_spec.rb +28 -0
- data/spec/measurements/measurement_spec.rb +79 -133
- data/spec/measurements/result_array_spec.rb +23 -38
- data/spec/measurements/result_spec.rb +100 -128
- data/spec/query_spec.rb +83 -100
- data/spec/spec_helper.rb +24 -6
- data/spec/weather_services/noaa_spec.rb +179 -0
- data/spec/weather_services/services_spec.rb +28 -36
- data/spec/weather_services/weather_bug_spec.rb +57 -77
- data/spec/weather_services/wunderground_spec.rb +36 -65
- data/spec/weather_services/yahoo_spec.rb +38 -60
- data/spec/weather_spec.rb +79 -79
- data/spec/web_services/geocode_spec.rb +7 -11
- data/spec/web_services/noaa_station_id_spec.rb +33 -0
- data/spec/web_services/placemaker_spec.rb +7 -12
- data/spec/web_services/web_services_spec.rb +3 -9
- metadata +214 -163
- data/VERSION.yml +0 -5
- data/lib/barometer/weather_services/google.rb +0 -142
- data/lib/barometer/weather_services/weather_dot_com.rb +0 -279
- data/spec/fakeweb_helper.rb +0 -179
- data/spec/fixtures/formats/weather_id/90210.xml +0 -7
- data/spec/fixtures/formats/weather_id/from_USGA0028.xml +0 -3
- data/spec/fixtures/formats/weather_id/ksfo.xml +0 -1
- data/spec/fixtures/formats/weather_id/manhattan.xml +0 -7
- data/spec/fixtures/formats/weather_id/new_york.xml +0 -1
- data/spec/fixtures/formats/weather_id/the_hills.xml +0 -1
- data/spec/fixtures/geocode/40_73_v3.json +0 -497
- data/spec/fixtures/geocode/90210_v3.json +0 -63
- data/spec/fixtures/geocode/T5B4M9_v3.json +0 -68
- data/spec/fixtures/geocode/atlanta_v3.json +0 -58
- data/spec/fixtures/geocode/calgary_ab_v3.json +0 -58
- data/spec/fixtures/geocode/ksfo_v3.json +0 -73
- data/spec/fixtures/geocode/newyork_ny_v3.json +0 -58
- data/spec/fixtures/services/google/calgary_ab.xml +0 -1
- data/spec/fixtures/services/placemaker/T5B4M9.xml +0 -65
- data/spec/fixtures/services/placemaker/atlanta.xml +0 -65
- data/spec/fixtures/services/placemaker/coords.xml +0 -65
- data/spec/fixtures/services/placemaker/ksfo.xml +0 -65
- data/spec/fixtures/services/placemaker/new_york.xml +0 -65
- data/spec/fixtures/services/placemaker/the_hills.xml +0 -65
- data/spec/fixtures/services/placemaker/w615702.xml +0 -47
- data/spec/fixtures/services/weather_bug/90210_current.xml +0 -93
- data/spec/fixtures/services/weather_bug/90210_forecast.xml +0 -76
- data/spec/fixtures/services/weather_dot_com/90210.xml +0 -1
- data/spec/fixtures/services/wunderground/current_calgary_ab.xml +0 -9
- data/spec/fixtures/services/wunderground/forecast_calgary_ab.xml +0 -13
- data/spec/fixtures/services/yahoo/90210.xml +0 -3
- data/spec/weather_services/google_spec.rb +0 -181
- data/spec/weather_services/weather_dot_com_spec.rb +0 -224
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'crack'
|
2
|
+
|
1
3
|
module Barometer
|
2
4
|
#
|
3
5
|
# = WeatherBug
|
@@ -34,7 +36,7 @@ module Barometer
|
|
34
36
|
# are specific to WeatherBug and un-supported by Barometer
|
35
37
|
#
|
36
38
|
class WeatherService::WeatherBug < WeatherService
|
37
|
-
|
39
|
+
|
38
40
|
@@api_code = nil
|
39
41
|
|
40
42
|
def self.keys=(keys)
|
@@ -65,7 +67,7 @@ module Barometer
|
|
65
67
|
codes = [0,2,3,4,7,26,31,64,65,75]
|
66
68
|
codes.collect {|c| c.to_s}
|
67
69
|
end
|
68
|
-
|
70
|
+
|
69
71
|
def self._build_extra(measurement, result, metric=true)
|
70
72
|
#raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
71
73
|
#raise ArgumentError unless query.is_a?(Barometer::Query)
|
@@ -76,7 +78,7 @@ module Barometer
|
|
76
78
|
forecast.sun = measurement.current.sun
|
77
79
|
end
|
78
80
|
end
|
79
|
-
|
81
|
+
|
80
82
|
measurement
|
81
83
|
end
|
82
84
|
|
@@ -121,26 +123,26 @@ module Barometer
|
|
121
123
|
|
122
124
|
current
|
123
125
|
end
|
124
|
-
|
126
|
+
|
125
127
|
def self._build_forecast(data, metric=true)
|
126
128
|
raise ArgumentError unless data.is_a?(Hash)
|
127
129
|
forecasts = Measurement::ResultArray.new
|
128
130
|
# go through each forecast and create an instance
|
129
|
-
if data && data["
|
131
|
+
if data && data["forecast"]
|
130
132
|
start_date = Date.strptime(data['date'], "%m/%d/%Y %H:%M:%S %p")
|
131
133
|
i = 0
|
132
|
-
data["
|
134
|
+
data["forecast"].each do |forecast|
|
133
135
|
forecast_measurement = Measurement::Result.new
|
134
|
-
icon_match = forecast['
|
136
|
+
icon_match = forecast['image']['icon'].match(/cond(\d*)\.gif$/)
|
135
137
|
forecast_measurement.icon = icon_match[1].to_i.to_s if icon_match
|
136
138
|
forecast_measurement.date = start_date + i
|
137
|
-
forecast_measurement.condition = forecast['
|
139
|
+
forecast_measurement.condition = forecast['short_prediction']
|
138
140
|
|
139
141
|
forecast_measurement.high = Data::Temperature.new(metric)
|
140
|
-
forecast_measurement.high << forecast['
|
142
|
+
forecast_measurement.high << forecast['high']['__content__']
|
141
143
|
|
142
144
|
forecast_measurement.low = Data::Temperature.new(metric)
|
143
|
-
forecast_measurement.low << forecast['
|
145
|
+
forecast_measurement.low << forecast['low']['__content__']
|
144
146
|
|
145
147
|
forecasts << forecast_measurement
|
146
148
|
i += 1
|
@@ -148,7 +150,7 @@ module Barometer
|
|
148
150
|
end
|
149
151
|
forecasts
|
150
152
|
end
|
151
|
-
|
153
|
+
|
152
154
|
def self._build_location(data, geo=nil)
|
153
155
|
raise ArgumentError unless data.is_a?(Hash)
|
154
156
|
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
@@ -162,15 +164,15 @@ module Barometer
|
|
162
164
|
location.latitude = geo.latitude
|
163
165
|
location.longitude = geo.longitude
|
164
166
|
else
|
165
|
-
if data && data['
|
166
|
-
location.city = data['
|
167
|
-
location.state_code = data['
|
168
|
-
location.zip_code = data['
|
167
|
+
if data && data['location']
|
168
|
+
location.city = data['location']['city']
|
169
|
+
location.state_code = data['location']['state']
|
170
|
+
location.zip_code = data['location']['zip']
|
169
171
|
end
|
170
172
|
end
|
171
173
|
location
|
172
174
|
end
|
173
|
-
|
175
|
+
|
174
176
|
def self._build_station(data)
|
175
177
|
raise ArgumentError unless data.is_a?(Hash)
|
176
178
|
station = Data::Location.new
|
@@ -184,7 +186,7 @@ module Barometer
|
|
184
186
|
station.longitude = data['aws:longitude']
|
185
187
|
station
|
186
188
|
end
|
187
|
-
|
189
|
+
|
188
190
|
def self._build_sun(data)
|
189
191
|
raise ArgumentError unless data.is_a?(Hash)
|
190
192
|
sun = nil
|
@@ -218,16 +220,16 @@ module Barometer
|
|
218
220
|
result << _fetch_forecast(query,metric)
|
219
221
|
result
|
220
222
|
end
|
221
|
-
|
223
|
+
|
222
224
|
# use HTTParty to get the current weather
|
223
225
|
#
|
224
226
|
def self._fetch_current(query, metric=true)
|
225
227
|
puts "fetch weatherbug current: #{query.q}" if Barometer::debug?
|
226
|
-
|
228
|
+
|
227
229
|
q = ( query.format.to_sym == :short_zipcode ?
|
228
230
|
{ :zipCode => query.q } :
|
229
231
|
{ :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
|
230
|
-
|
232
|
+
|
231
233
|
# httparty and the xml builder it uses miss some information
|
232
234
|
# 1st - get the raw response
|
233
235
|
# 2nd - manually get the missing information
|
@@ -240,36 +242,36 @@ module Barometer
|
|
240
242
|
}.merge(q),
|
241
243
|
:format => :plain,
|
242
244
|
:timeout => Barometer.timeout
|
243
|
-
)
|
244
|
-
|
245
|
+
)
|
246
|
+
|
245
247
|
# get icon
|
246
248
|
icon_match = response.match(/cond(\d*)\.gif/)
|
247
249
|
icon = icon_match[1] if icon_match
|
248
|
-
|
250
|
+
|
249
251
|
# get station zipcode
|
250
252
|
zip_match = response.match(/zipcode=\"(\d*)\"/)
|
251
253
|
zipcode = zip_match[1] if zip_match
|
252
|
-
|
254
|
+
|
253
255
|
# build xml
|
254
|
-
output = Crack::XML.parse(response)
|
256
|
+
output = ::Crack::XML.parse(response)
|
255
257
|
output = output["aws:weather"]["aws:ob"]
|
256
|
-
|
258
|
+
|
257
259
|
# add missing data
|
258
260
|
output["aws:icon"] = icon
|
259
261
|
output["aws:station_zipcode"] = zipcode
|
260
|
-
|
262
|
+
|
261
263
|
output
|
262
264
|
end
|
263
|
-
|
265
|
+
|
264
266
|
# use HTTParty to get the current weather
|
265
267
|
#
|
266
268
|
def self._fetch_forecast(query, metric=true)
|
267
269
|
puts "fetch weatherbug forecast: #{query.q}" if Barometer::debug?
|
268
|
-
|
270
|
+
|
269
271
|
q = ( query.format.to_sym == :short_zipcode ?
|
270
272
|
{ :zipCode => query.q } :
|
271
273
|
{ :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
|
272
|
-
|
274
|
+
|
273
275
|
self.get(
|
274
276
|
"http://#{@@api_code}.api.wxbug.net/getForecastRSS.aspx",
|
275
277
|
:query => { :ACode => @@api_code,
|
@@ -277,9 +279,9 @@ module Barometer
|
|
277
279
|
}.merge(q),
|
278
280
|
:format => :xml,
|
279
281
|
:timeout => Barometer.timeout
|
280
|
-
)["
|
282
|
+
)["weather"]["forecasts"]
|
281
283
|
end
|
282
|
-
|
284
|
+
|
283
285
|
# since we have two sets of data, override these calls to choose the
|
284
286
|
# right set of data
|
285
287
|
#
|
@@ -292,4 +294,4 @@ module Barometer
|
|
292
294
|
def self._time_result(data=nil); data[0]; end
|
293
295
|
|
294
296
|
end
|
295
|
-
end
|
297
|
+
end
|
@@ -45,17 +45,17 @@ module Barometer
|
|
45
45
|
# Unable to locate.
|
46
46
|
#
|
47
47
|
class WeatherService::Wunderground < WeatherService
|
48
|
-
|
48
|
+
|
49
49
|
#########################################################################
|
50
50
|
# PRIVATE
|
51
51
|
# If class methods could be private, the remaining methods would be.
|
52
52
|
#
|
53
|
-
|
53
|
+
|
54
54
|
def self._source_name; :wunderground; end
|
55
55
|
def self._accepted_formats
|
56
56
|
[:zipcode, :postalcode, :icao, :coordinates, :geocode]
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
# these are the icon codes that indicate "wet", used by wet? function
|
60
60
|
def self._wet_icon_codes
|
61
61
|
%w(flurries rain sleet snow tstorms nt_flurries nt_rain nt_sleet nt_snow nt_tstorms chancerain chancetstorms)
|
@@ -75,7 +75,7 @@ module Barometer
|
|
75
75
|
forecast.sun = measurement.current.sun
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
measurement
|
80
80
|
end
|
81
81
|
|
@@ -90,7 +90,7 @@ module Barometer
|
|
90
90
|
)
|
91
91
|
end
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
def self._build_links(data)
|
95
95
|
links = {}
|
96
96
|
if data["credit"] && data["credit_URL"]
|
@@ -101,63 +101,65 @@ module Barometer
|
|
101
101
|
|
102
102
|
def self._build_current(data, metric=true)
|
103
103
|
raise ArgumentError unless data.is_a?(Hash)
|
104
|
-
|
104
|
+
|
105
105
|
current = Measurement::Result.new
|
106
|
-
|
106
|
+
if data['observation_time'] && data['observation_time'].match(/\d/)
|
107
|
+
current.updated_at = Data::LocalDateTime.parse(data['observation_time'])
|
108
|
+
end
|
107
109
|
current.humidity = data['relative_humidity'].to_i
|
108
110
|
current.icon = data['icon'] if data['icon']
|
109
|
-
|
111
|
+
|
110
112
|
current.temperature = Data::Temperature.new(metric)
|
111
113
|
current.temperature << [data['temp_c'], data['temp_f']]
|
112
|
-
|
114
|
+
|
113
115
|
current.wind = Data::Speed.new(metric)
|
114
116
|
current.wind.mph = data['wind_mph'].to_f
|
115
117
|
current.wind.degrees = data['wind_degrees'].to_i
|
116
118
|
current.wind.direction = data['wind_dir']
|
117
|
-
|
119
|
+
|
118
120
|
current.pressure = Data::Pressure.new(metric)
|
119
121
|
current.pressure << [data['pressure_mb'], data['pressure_in']]
|
120
|
-
|
122
|
+
|
121
123
|
current.dew_point = Data::Temperature.new(metric)
|
122
124
|
current.dew_point << [data['dewpoint_c'], data['dewpoint_f']]
|
123
|
-
|
125
|
+
|
124
126
|
current.heat_index = Data::Temperature.new(metric)
|
125
127
|
current.heat_index << [data['heat_index_c'], data['heat_index_f']]
|
126
|
-
|
128
|
+
|
127
129
|
current.wind_chill = Data::Temperature.new(metric)
|
128
130
|
current.wind_chill << [data['windchill_c'], data['windchill_f']]
|
129
|
-
|
131
|
+
|
130
132
|
current.visibility = Data::Distance.new(metric)
|
131
133
|
current.visibility << [data['visibility_km'], data['visibility_mi']]
|
132
|
-
|
134
|
+
|
133
135
|
current
|
134
136
|
end
|
135
|
-
|
137
|
+
|
136
138
|
def self._build_forecast(data, metric=true)
|
137
139
|
raise ArgumentError unless data.is_a?(Hash)
|
138
140
|
forecasts = Measurement::ResultArray.new
|
139
141
|
# go through each forecast and create an instance
|
140
142
|
if data && data['simpleforecast'] &&
|
141
143
|
data['simpleforecast']['forecastday']
|
142
|
-
|
144
|
+
|
143
145
|
data['simpleforecast']['forecastday'].each do |forecast|
|
144
146
|
forecast_measurement = Measurement::Result.new
|
145
147
|
forecast_measurement.icon = forecast['icon']
|
146
148
|
forecast_measurement.date = Date.parse(forecast['date']['pretty'])
|
147
149
|
forecast_measurement.pop = forecast['pop'].to_i
|
148
|
-
|
150
|
+
|
149
151
|
forecast_measurement.high = Data::Temperature.new(metric)
|
150
152
|
forecast_measurement.high << [forecast['high']['celsius'],forecast['high']['fahrenheit']]
|
151
|
-
|
153
|
+
|
152
154
|
forecast_measurement.low = Data::Temperature.new(metric)
|
153
155
|
forecast_measurement.low << [forecast['low']['celsius'],forecast['low']['fahrenheit']]
|
154
|
-
|
156
|
+
|
155
157
|
forecasts << forecast_measurement
|
156
158
|
end
|
157
159
|
end
|
158
160
|
forecasts
|
159
161
|
end
|
160
|
-
|
162
|
+
|
161
163
|
def self._build_location(data, geo=nil)
|
162
164
|
raise ArgumentError unless data.is_a?(Hash)
|
163
165
|
location = Data::Location.new
|
@@ -173,7 +175,7 @@ module Barometer
|
|
173
175
|
end
|
174
176
|
location
|
175
177
|
end
|
176
|
-
|
178
|
+
|
177
179
|
def self._build_station(data)
|
178
180
|
raise ArgumentError unless data.is_a?(Hash)
|
179
181
|
station = Data::Location.new
|
@@ -190,7 +192,7 @@ module Barometer
|
|
190
192
|
end
|
191
193
|
station
|
192
194
|
end
|
193
|
-
|
195
|
+
|
194
196
|
def self._build_sun(data)
|
195
197
|
raise ArgumentError unless data.is_a?(Hash)
|
196
198
|
sun = nil
|
@@ -209,7 +211,7 @@ module Barometer
|
|
209
211
|
end
|
210
212
|
sun || Data::Sun.new
|
211
213
|
end
|
212
|
-
|
214
|
+
|
213
215
|
# override default _fetch behavior
|
214
216
|
# this service requires TWO seperate http requests (one for current
|
215
217
|
# and one for forecasted weather) ... combine the results
|
@@ -220,7 +222,7 @@ module Barometer
|
|
220
222
|
result << _fetch_forecast(query)
|
221
223
|
result
|
222
224
|
end
|
223
|
-
|
225
|
+
|
224
226
|
# use HTTParty to get the current weather
|
225
227
|
#
|
226
228
|
def self._fetch_current(query)
|
@@ -233,7 +235,7 @@ module Barometer
|
|
233
235
|
:timeout => Barometer.timeout
|
234
236
|
)['current_observation']
|
235
237
|
end
|
236
|
-
|
238
|
+
|
237
239
|
# use HTTParty to get the forecasted weather
|
238
240
|
#
|
239
241
|
def self._fetch_forecast(query)
|
@@ -246,7 +248,7 @@ module Barometer
|
|
246
248
|
:timeout => Barometer.timeout
|
247
249
|
)['forecast']
|
248
250
|
end
|
249
|
-
|
251
|
+
|
250
252
|
# since we have two sets of data, override these calls to choose the
|
251
253
|
# right set of data
|
252
254
|
#
|
@@ -257,6 +259,6 @@ module Barometer
|
|
257
259
|
def self._links_result(data=nil); data[0]; end
|
258
260
|
def self._sun_result(data=nil); data[1]; end
|
259
261
|
def self._timezone_result(data=nil); data[1]; end
|
260
|
-
|
262
|
+
|
261
263
|
end
|
262
|
-
end
|
264
|
+
end
|
@@ -46,16 +46,16 @@ module Barometer
|
|
46
46
|
# - the Yahoo! WOEID is only used by Yahoo!, and is a 32-bit number. Unfortunately
|
47
47
|
# this number confilcts with US Zipcodes (ie the zipcode=90210 and the
|
48
48
|
# WOEID=90210 cannot be destinguished and do not mean the same thing). To
|
49
|
-
# solve this, any 5 digit number will be dtected as a ZIPCODE. To have a
|
49
|
+
# solve this, any 5 digit number will be dtected as a ZIPCODE. To have a
|
50
50
|
# 5 digit query be detected as a WOEID, prepend it with a 'w' (ie: w90210).
|
51
51
|
#
|
52
52
|
class WeatherService::Yahoo < WeatherService
|
53
|
-
|
53
|
+
|
54
54
|
#########################################################################
|
55
55
|
# PRIVATE
|
56
56
|
# If class methods could be private, the remaining methods would be.
|
57
57
|
#
|
58
|
-
|
58
|
+
|
59
59
|
def self._source_name; :yahoo; end
|
60
60
|
def self._accepted_formats; [:zipcode, :weather_id, :woe_id]; end
|
61
61
|
|
@@ -67,11 +67,11 @@ module Barometer
|
|
67
67
|
codes = (29..34).to_a + [36]
|
68
68
|
codes.collect {|c| c.to_s}
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def self._build_extra(measurement, result, metric=true)
|
72
72
|
#raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
73
73
|
#raise ArgumentError unless query.is_a?(Barometer::Query)
|
74
|
-
|
74
|
+
|
75
75
|
# use todays sun data for all future days
|
76
76
|
if measurement.forecast && measurement.current.sun
|
77
77
|
measurement.forecast.each do |forecast|
|
@@ -80,14 +80,14 @@ module Barometer
|
|
80
80
|
end
|
81
81
|
measurement
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def self._build_timezone(data)
|
85
85
|
if data && data['item'] && data['item']['pubDate']
|
86
86
|
zone_match = data['item']['pubDate'].match(/ ([A-Z]*)$/)
|
87
87
|
Data::Zone.new(zone_match[1]) if zone_match
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def self._build_links(data)
|
92
92
|
links = {}
|
93
93
|
if data["title"] && data["link"]
|
@@ -95,29 +95,29 @@ module Barometer
|
|
95
95
|
end
|
96
96
|
links
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
def self._build_current(data, metric=true)
|
100
100
|
raise ArgumentError unless data.is_a?(Hash)
|
101
101
|
current = Measurement::Result.new(metric)
|
102
102
|
if data
|
103
|
-
if data['item'] && data['item']['
|
104
|
-
condition_result = data['item']['
|
103
|
+
if data['item'] && data['item']['condition']
|
104
|
+
condition_result = data['item']['condition']
|
105
105
|
current.updated_at = Data::LocalDateTime.parse(condition_result['date'])
|
106
106
|
current.icon = condition_result['code']
|
107
107
|
current.condition = condition_result['text']
|
108
108
|
current.temperature = Data::Temperature.new(metric)
|
109
109
|
current.temperature << condition_result['temp']
|
110
110
|
end
|
111
|
-
if data['
|
112
|
-
atmosphere_result = data['
|
111
|
+
if data['atmosphere']
|
112
|
+
atmosphere_result = data['atmosphere']
|
113
113
|
current.humidity = atmosphere_result['humidity'].to_i
|
114
114
|
current.pressure = Data::Pressure.new(metric)
|
115
115
|
current.pressure << atmosphere_result['pressure']
|
116
116
|
current.visibility = Data::Distance.new(metric)
|
117
117
|
current.visibility << atmosphere_result['visibility']
|
118
118
|
end
|
119
|
-
if data['
|
120
|
-
wind_result = data['
|
119
|
+
if data['wind']
|
120
|
+
wind_result = data['wind']
|
121
121
|
current.wind = Data::Speed.new(metric)
|
122
122
|
current.wind << wind_result['speed']
|
123
123
|
current.wind.degrees = wind_result['degrees'].to_f
|
@@ -127,14 +127,14 @@ module Barometer
|
|
127
127
|
end
|
128
128
|
current
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
def self._build_forecast(data, metric=true)
|
132
132
|
raise ArgumentError unless data.is_a?(Hash)
|
133
133
|
forecasts = Measurement::ResultArray.new
|
134
|
-
|
135
|
-
if data && data['item'] && data['item']['
|
136
|
-
forecast_result = data['item']['
|
137
|
-
|
134
|
+
|
135
|
+
if data && data['item'] && data['item']['forecast']
|
136
|
+
forecast_result = data['item']['forecast']
|
137
|
+
|
138
138
|
forecast_result.each do |forecast|
|
139
139
|
forecast_measurement = Measurement::Result.new
|
140
140
|
forecast_measurement.icon = forecast['code']
|
@@ -149,7 +149,7 @@ module Barometer
|
|
149
149
|
end
|
150
150
|
forecasts
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
def self._build_location(data, geo=nil)
|
154
154
|
raise ArgumentError unless data.is_a?(Hash)
|
155
155
|
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
@@ -163,30 +163,30 @@ module Barometer
|
|
163
163
|
location.latitude = geo.latitude
|
164
164
|
location.longitude = geo.longitude
|
165
165
|
else
|
166
|
-
if data && data['
|
167
|
-
location.city = data['
|
168
|
-
location.state_code = data['
|
169
|
-
location.country_code = data['
|
166
|
+
if data && data['location']
|
167
|
+
location.city = data['location']['city']
|
168
|
+
location.state_code = data['location']['region']
|
169
|
+
location.country_code = data['location']['country']
|
170
170
|
if data['item']
|
171
|
-
location.latitude = data['item']['
|
172
|
-
location.longitude = data['item']['
|
171
|
+
location.latitude = data['item']['lat']
|
172
|
+
location.longitude = data['item']['long']
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
176
176
|
location
|
177
177
|
end
|
178
|
-
|
178
|
+
|
179
179
|
def self._build_sun(data)
|
180
180
|
raise ArgumentError unless data.is_a?(Hash)
|
181
181
|
sun = nil
|
182
|
-
if data && data['
|
183
|
-
local_rise = Data::LocalTime.parse(data['
|
184
|
-
local_set = Data::LocalTime.parse(data['
|
182
|
+
if data && data['astronomy'] && data['item']
|
183
|
+
local_rise = Data::LocalTime.parse(data['astronomy']['sunrise'])
|
184
|
+
local_set = Data::LocalTime.parse(data['astronomy']['sunset'])
|
185
185
|
sun = Data::Sun.new(local_rise, local_set)
|
186
186
|
end
|
187
187
|
sun || Data::Sun.new
|
188
188
|
end
|
189
|
-
|
189
|
+
|
190
190
|
# use HTTParty to get the current weather
|
191
191
|
def self._fetch(query, metric=true)
|
192
192
|
return unless query
|
@@ -196,13 +196,14 @@ module Barometer
|
|
196
196
|
:w => query.format == :woe_id ? query.q : nil,
|
197
197
|
:u => (metric ? 'c' : 'f')
|
198
198
|
}.delete_if {|k,v| v.nil? }
|
199
|
-
self.get(
|
199
|
+
r = self.get(
|
200
200
|
"http://weather.yahooapis.com/forecastrss",
|
201
201
|
:query => options,
|
202
202
|
:format => :xml,
|
203
203
|
:timeout => Barometer.timeout
|
204
|
-
)
|
204
|
+
)
|
205
|
+
r['rss']['channel']
|
205
206
|
end
|
206
|
-
|
207
|
+
|
207
208
|
end
|
208
|
-
end
|
209
|
+
end
|