attack-barometer 0.5.0 → 0.6.0
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/README.rdoc +51 -9
- data/VERSION.yml +1 -1
- data/bin/barometer +57 -7
- data/lib/barometer/base.rb +3 -0
- data/lib/barometer/data/sun.rb +10 -0
- data/lib/barometer/data/zone.rb +79 -188
- data/lib/barometer/data.rb +11 -6
- data/lib/barometer/formats/coordinates.rb +4 -1
- data/lib/barometer/formats/geocode.rb +9 -7
- data/lib/barometer/formats/icao.rb +2 -2
- data/lib/barometer/formats/weather_id.rb +2 -2
- data/lib/barometer/measurements/common.rb +113 -0
- data/lib/barometer/{data → measurements}/current.rb +17 -42
- data/lib/barometer/measurements/forecast.rb +62 -0
- data/lib/barometer/measurements/forecast_array.rb +72 -0
- data/lib/barometer/{data → measurements}/measurement.rb +57 -45
- data/lib/barometer/measurements/night.rb +27 -0
- data/lib/barometer/query.rb +55 -5
- data/lib/barometer/services.rb +3 -1
- data/lib/barometer/translations/zone_codes.yml +360 -0
- data/lib/barometer/weather.rb +5 -4
- data/lib/barometer/weather_services/google.rb +19 -35
- data/lib/barometer/weather_services/service.rb +113 -255
- data/lib/barometer/weather_services/weather_bug.rb +291 -2
- data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
- data/lib/barometer/weather_services/wunderground.rb +83 -89
- data/lib/barometer/weather_services/yahoo.rb +44 -91
- data/lib/barometer/web_services/geocode.rb +1 -0
- data/lib/barometer/web_services/timezone.rb +40 -0
- data/lib/barometer/web_services/weather_id.rb +17 -2
- data/lib/barometer.rb +11 -0
- data/lib/demometer/demometer.rb +28 -0
- data/lib/demometer/public/css/master.css +259 -1
- data/lib/demometer/views/index.erb +2 -0
- data/lib/demometer/views/layout.erb +3 -2
- data/lib/demometer/views/measurement.erb +4 -1
- data/lib/demometer/views/readme.erb +116 -88
- data/spec/data/sun_spec.rb +53 -0
- data/spec/data/zone_spec.rb +330 -100
- data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
- data/spec/formats/weather_id_spec.rb +10 -5
- data/spec/measurements/common_spec.rb +352 -0
- data/spec/{data → measurements}/current_spec.rb +40 -103
- data/spec/measurements/forecast_array_spec.rb +165 -0
- data/spec/measurements/forecast_spec.rb +135 -0
- data/spec/{data → measurements}/measurement_spec.rb +86 -107
- data/spec/measurements/night_measurement_spec.rb +49 -0
- data/spec/query_spec.rb +12 -2
- data/spec/spec_helper.rb +28 -1
- data/spec/weather_services/google_spec.rb +27 -117
- data/spec/weather_services/services_spec.rb +49 -1024
- data/spec/weather_services/weather_bug_spec.rb +274 -0
- data/spec/weather_services/weather_dot_com_spec.rb +45 -125
- data/spec/weather_services/wunderground_spec.rb +42 -136
- data/spec/weather_services/yahoo_spec.rb +26 -116
- data/spec/weather_spec.rb +45 -45
- metadata +23 -11
- data/lib/barometer/data/forecast.rb +0 -84
- data/lib/barometer/data/night.rb +0 -69
- data/lib/barometer/extensions/graticule.rb +0 -51
- data/spec/data/forecast_spec.rb +0 -192
- data/spec/data/night_measurement_spec.rb +0 -136
@@ -1,6 +1,295 @@
|
|
1
1
|
module Barometer
|
2
|
-
|
2
|
+
#
|
3
|
+
# = WeatherBug
|
4
|
+
# www.weatherbug.com
|
5
|
+
#
|
6
|
+
# - key required: YES (api_code)
|
7
|
+
# - registration required: YES
|
8
|
+
# - supported countries: US (by zipcode), International (by coordinates)
|
9
|
+
#
|
10
|
+
# === performs geo coding
|
11
|
+
# - city: YES
|
12
|
+
# - coordinates: PARTIAL (just for weather station)
|
13
|
+
#
|
14
|
+
# === time info
|
15
|
+
# - sun rise/set: YES
|
16
|
+
# - provides timezone: NO, but provides a timezone short code and utc offset
|
17
|
+
# - requires TZInfo: NO
|
18
|
+
#
|
19
|
+
# == resources
|
20
|
+
# - API: http://weather.weatherbug.com/corporate/products/API/help.aspx
|
21
|
+
#
|
22
|
+
# === Possible queries:
|
23
|
+
# - http://[API_Code].api.wxbug.net:80/getLiveWeatherRSS.aspx?ACode=[API_Code]&OutputType=1&UnitType=1&zipCode=90210
|
24
|
+
#
|
25
|
+
# where query can be:
|
26
|
+
# - zipcode (US) [5 digits only]
|
27
|
+
# - coordinates (International)
|
28
|
+
#
|
29
|
+
# = WeatherBug.com terms of use
|
30
|
+
# ???
|
31
|
+
#
|
32
|
+
# == notes
|
33
|
+
# - WeatherBug also supports queries using "citycode" and "stationID", but these
|
34
|
+
# are specific to WeatherBug and un-supported by Barometer
|
35
|
+
#
|
3
36
|
class WeatherService::WeatherBug < WeatherService
|
37
|
+
|
38
|
+
@@api_code = nil
|
39
|
+
|
40
|
+
def self.keys=(keys)
|
41
|
+
raise ArgumentError unless keys.is_a?(Hash)
|
42
|
+
keys.each do |key, value|
|
43
|
+
@@api_code = value.to_s if key.to_s.downcase == "code"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#########################################################################
|
48
|
+
# PRIVATE
|
49
|
+
# If class methods could be private, the remaining methods would be.
|
50
|
+
#
|
51
|
+
|
52
|
+
def self._source_name; :weather_bug; end
|
53
|
+
def self._accepted_formats; [:short_zipcode, :coordinates]; end
|
54
|
+
|
55
|
+
def self._has_keys?; !@@api_code.nil?; end
|
56
|
+
def self._requires_keys?; true; end
|
57
|
+
|
58
|
+
def self._wet_icon_codes
|
59
|
+
codes = [5,6,8,9,11,12,14,15] + (18..22).to_a + [25] + (27..30).to_a +
|
60
|
+
[32,36] + (38..49).to_a + (52..63).to_a + (80..157).to_a +
|
61
|
+
(161..176).to_a
|
62
|
+
codes.collect {|c| c.to_s}
|
63
|
+
end
|
64
|
+
def self._sunny_icon_codes
|
65
|
+
codes = [0,2,3,4,7,26,31,64,65,75]
|
66
|
+
codes.collect {|c| c.to_s}
|
67
|
+
end
|
68
|
+
|
69
|
+
def self._build_extra(measurement, result, metric=true)
|
70
|
+
#raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
71
|
+
#raise ArgumentError unless query.is_a?(Barometer::Query)
|
72
|
+
|
73
|
+
# use todays sun data for all future days
|
74
|
+
if measurement.forecast && measurement.current.sun
|
75
|
+
measurement.forecast.each do |forecast|
|
76
|
+
forecast.sun = measurement.current.sun
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
measurement
|
81
|
+
end
|
82
|
+
|
83
|
+
def self._parse_local_time(data)
|
84
|
+
Data::LocalTime.new(
|
85
|
+
data["aws:ob_date"]["aws:hour"]["hour_24"].to_i,
|
86
|
+
data["aws:ob_date"]["aws:minute"]["number"].to_i,
|
87
|
+
data["aws:ob_date"]["aws:second"]["number"].to_i
|
88
|
+
) if data && data["aws:ob_date"]
|
89
|
+
end
|
90
|
+
|
91
|
+
def self._build_timezone(data)
|
92
|
+
if data && data["aws:ob_date"] && data["aws:ob_date"]["aws:time_zone"]
|
93
|
+
Data::Zone.new(data["aws:ob_date"]["aws:time_zone"]["abbrv"])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self._build_current(data, metric=true)
|
98
|
+
raise ArgumentError unless data.is_a?(Hash)
|
99
|
+
|
100
|
+
current = Measurement::Current.new
|
101
|
+
# current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
|
102
|
+
current.humidity = data['aws:humidity'].to_i
|
103
|
+
current.condition = data['aws:current_condition'] if data['aws:current_condition']
|
104
|
+
current.icon = data['aws:icon'].to_i.to_s if data['aws:icon']
|
105
|
+
|
106
|
+
current.temperature = Data::Temperature.new(metric)
|
107
|
+
current.temperature << data['aws:temp']
|
108
|
+
|
109
|
+
current.wind = Data::Speed.new(metric)
|
110
|
+
current.wind << data['aws:wind_speed'].to_f
|
111
|
+
current.wind.direction = data['aws:wind_direction']
|
112
|
+
|
113
|
+
current.pressure = Data::Pressure.new(metric)
|
114
|
+
current.pressure << data['aws:pressure']
|
115
|
+
|
116
|
+
current.dew_point = Data::Temperature.new(metric)
|
117
|
+
current.dew_point << data['aws:dew_point']
|
118
|
+
|
119
|
+
current.wind_chill = Data::Temperature.new(metric)
|
120
|
+
current.wind_chill << data['aws:feels_like']
|
121
|
+
|
122
|
+
current
|
123
|
+
end
|
124
|
+
|
125
|
+
def self._build_forecast(data, metric=true)
|
126
|
+
raise ArgumentError unless data.is_a?(Hash)
|
127
|
+
forecasts = Measurement::ForecastArray.new
|
128
|
+
# go through each forecast and create an instance
|
129
|
+
if data && data["aws:forecast"]
|
130
|
+
start_date = Date.parse(data['date'])
|
131
|
+
i = 0
|
132
|
+
data["aws:forecast"].each do |forecast|
|
133
|
+
forecast_measurement = Measurement::Forecast.new
|
134
|
+
icon_match = forecast['aws:image'].match(/cond(\d*)\.gif$/)
|
135
|
+
forecast_measurement.icon = icon_match[1].to_i.to_s if icon_match
|
136
|
+
forecast_measurement.date = start_date + i
|
137
|
+
forecast_measurement.condition = forecast['aws:short_prediction']
|
138
|
+
|
139
|
+
forecast_measurement.high = Data::Temperature.new(metric)
|
140
|
+
forecast_measurement.high << forecast['aws:high']
|
141
|
+
|
142
|
+
forecast_measurement.low = Data::Temperature.new(metric)
|
143
|
+
forecast_measurement.low << forecast['aws:low']
|
144
|
+
|
145
|
+
forecasts << forecast_measurement
|
146
|
+
i += 1
|
147
|
+
end
|
148
|
+
end
|
149
|
+
forecasts
|
150
|
+
end
|
151
|
+
|
152
|
+
def self._build_location(data, geo=nil)
|
153
|
+
raise ArgumentError unless data.is_a?(Hash)
|
154
|
+
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
155
|
+
location = Data::Location.new
|
156
|
+
# use the geocoded data if available, otherwise get data from result
|
157
|
+
if geo
|
158
|
+
location.city = geo.locality
|
159
|
+
location.state_code = geo.region
|
160
|
+
location.country = geo.country
|
161
|
+
location.country_code = geo.country_code
|
162
|
+
location.latitude = geo.latitude
|
163
|
+
location.longitude = geo.longitude
|
164
|
+
else
|
165
|
+
if data && data['aws:location']
|
166
|
+
location.city = data['aws:location']['aws:city']
|
167
|
+
location.state_code = data['aws:location']['aws:state']
|
168
|
+
location.zip_code = data['aws:location']['aws:zip']
|
169
|
+
end
|
170
|
+
end
|
171
|
+
location
|
172
|
+
end
|
173
|
+
|
174
|
+
def self._build_station(data)
|
175
|
+
raise ArgumentError unless data.is_a?(Hash)
|
176
|
+
station = Data::Location.new
|
177
|
+
station.id = data['aws:station_id']
|
178
|
+
station.name = data['aws:station']
|
179
|
+
station.city = data['aws:city_state'].split(',')[0].strip
|
180
|
+
station.state_code = data['aws:city_state'].split(',')[1].strip
|
181
|
+
station.country = data['aws:country']
|
182
|
+
station.zip_code = data['aws:station_zipcode']
|
183
|
+
station.latitude = data['aws:latitude']
|
184
|
+
station.longitude = data['aws:longitude']
|
185
|
+
station
|
186
|
+
end
|
187
|
+
|
188
|
+
def self._build_sun(data)
|
189
|
+
raise ArgumentError unless data.is_a?(Hash)
|
190
|
+
sun = nil
|
191
|
+
if data
|
192
|
+
if data['aws:sunrise']
|
193
|
+
rise = Data::LocalTime.new(
|
194
|
+
data['aws:sunrise']['aws:hour']['hour_24'].to_i,
|
195
|
+
data['aws:sunrise']['aws:minute']['number'].to_i,
|
196
|
+
data['aws:sunrise']['aws:second']['number'].to_i
|
197
|
+
)
|
198
|
+
end
|
199
|
+
if data['aws:sunset']
|
200
|
+
set = Data::LocalTime.new(
|
201
|
+
data['aws:sunset']['aws:hour']['hour_24'].to_i,
|
202
|
+
data['aws:sunset']['aws:minute']['number'].to_i,
|
203
|
+
data['aws:sunset']['aws:second']['number'].to_i
|
204
|
+
)
|
205
|
+
sun = Data::Sun.new(rise,set)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
sun || Data::Sun.new
|
209
|
+
end
|
210
|
+
|
211
|
+
# override default _fetch behavior
|
212
|
+
# this service requires TWO seperate http requests (one for current
|
213
|
+
# and one for forecasted weather) ... combine the results
|
214
|
+
#
|
215
|
+
def self._fetch(query, metric=true)
|
216
|
+
result = []
|
217
|
+
result << _fetch_current(query,metric)
|
218
|
+
result << _fetch_forecast(query,metric)
|
219
|
+
result
|
220
|
+
end
|
221
|
+
|
222
|
+
# use HTTParty to get the current weather
|
223
|
+
#
|
224
|
+
def self._fetch_current(query, metric=true)
|
225
|
+
puts "fetch weatherbug current: #{query.q}" if Barometer::debug?
|
226
|
+
|
227
|
+
q = ( query.format.to_sym == :short_zipcode ?
|
228
|
+
{ :zipCode => query.q } :
|
229
|
+
{ :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
|
230
|
+
|
231
|
+
# httparty and the xml builder it uses miss some information
|
232
|
+
# 1st - get the raw response
|
233
|
+
# 2nd - manually get the missing information
|
234
|
+
# 3rd - let httparty build xml as normal
|
235
|
+
#
|
236
|
+
response = self.get(
|
237
|
+
"http://#{@@api_code}.api.wxbug.net/getLiveWeatherRSS.aspx",
|
238
|
+
:query => { :ACode => @@api_code,
|
239
|
+
:OutputType => "1", :UnitType => (metric ? '1' : '0')
|
240
|
+
}.merge(q),
|
241
|
+
:format => :plain,
|
242
|
+
:timeout => Barometer.timeout
|
243
|
+
)
|
244
|
+
|
245
|
+
# get icon
|
246
|
+
icon_match = response.match(/cond(\d*)\.gif/)
|
247
|
+
icon = icon_match[1] if icon_match
|
248
|
+
|
249
|
+
# get station zipcode
|
250
|
+
zip_match = response.match(/zipcode=\"(\d*)\"/)
|
251
|
+
zipcode = zip_match[1] if zip_match
|
252
|
+
|
253
|
+
# build xml
|
254
|
+
output = Crack::XML.parse(response)
|
255
|
+
output = output["aws:weather"]["aws:ob"]
|
256
|
+
|
257
|
+
# add missing data
|
258
|
+
output["aws:icon"] = icon
|
259
|
+
output["aws:station_zipcode"] = zipcode
|
260
|
+
|
261
|
+
output
|
262
|
+
end
|
263
|
+
|
264
|
+
# use HTTParty to get the current weather
|
265
|
+
#
|
266
|
+
def self._fetch_forecast(query, metric=true)
|
267
|
+
puts "fetch weatherbug forecast: #{query.q}" if Barometer::debug?
|
268
|
+
|
269
|
+
q = ( query.format.to_sym == :short_zipcode ?
|
270
|
+
{ :zipCode => query.q } :
|
271
|
+
{ :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
|
272
|
+
|
273
|
+
self.get(
|
274
|
+
"http://#{@@api_code}.api.wxbug.net/getForecastRSS.aspx",
|
275
|
+
:query => { :ACode => @@api_code,
|
276
|
+
:OutputType => "1", :UnitType => (metric ? '1' : '0')
|
277
|
+
}.merge(q),
|
278
|
+
:format => :xml,
|
279
|
+
:timeout => Barometer.timeout
|
280
|
+
)["aws:weather"]["aws:forecasts"]
|
281
|
+
end
|
282
|
+
|
283
|
+
# since we have two sets of data, override these calls to choose the
|
284
|
+
# right set of data
|
285
|
+
#
|
286
|
+
def self._current_result(data); data[0]; end
|
287
|
+
def self._forecast_result(data=nil); data[1]; end
|
288
|
+
def self._location_result(data=nil); data[1]; end
|
289
|
+
def self._station_result(data=nil); data[0]; end
|
290
|
+
def self._sun_result(data=nil); data[0]; end
|
291
|
+
def self._timezone_result(data=nil); data[0]; end
|
292
|
+
def self._time_result(data=nil); data[0]; end
|
293
|
+
|
4
294
|
end
|
5
|
-
|
6
295
|
end
|
@@ -43,9 +43,6 @@ module Barometer
|
|
43
43
|
@@partner_key = nil
|
44
44
|
@@license_key = nil
|
45
45
|
|
46
|
-
def self.source_name; :weather_dot_com; end
|
47
|
-
def self.accepted_formats; [:short_zipcode, :weather_id]; end
|
48
|
-
|
49
46
|
def self.keys=(keys)
|
50
47
|
raise ArgumentError unless keys.is_a?(Hash)
|
51
48
|
keys.each do |key, value|
|
@@ -54,64 +51,56 @@ module Barometer
|
|
54
51
|
end
|
55
52
|
end
|
56
53
|
|
57
|
-
|
58
|
-
|
54
|
+
#########################################################################
|
55
|
+
# PRIVATE
|
56
|
+
# If class methods could be private, the remaining methods would be.
|
57
|
+
#
|
58
|
+
|
59
|
+
def self._source_name; :weather_dot_com; end
|
60
|
+
def self._accepted_formats; [:short_zipcode, :weather_id]; end
|
59
61
|
|
60
|
-
def self.
|
62
|
+
def self._has_keys?; !@@partner_key.nil? && !@@license_key.nil?; end
|
63
|
+
def self._requires_keys?; true; end
|
64
|
+
|
65
|
+
def self._wet_icon_codes
|
61
66
|
codes = (0..18).to_a + [35] + (37..43).to_a + (45..47).to_a
|
62
67
|
codes.collect {|c| c.to_s}
|
63
68
|
end
|
64
|
-
def self.
|
69
|
+
def self._sunny_icon_codes
|
65
70
|
codes = [19, 22, 28, 30, 32, 34, 36]
|
66
71
|
codes.collect {|c| c.to_s}
|
67
72
|
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
measurement.current = self.build_current(result, metric)
|
81
|
-
measurement.forecast = self.build_forecast(result, metric)
|
82
|
-
measurement.location = self.build_location(result, query.geo)
|
83
|
-
measurement.current.sun = self.build_sun(result)
|
84
|
-
|
85
|
-
# add links
|
86
|
-
if result && result['lnks'] && result['lnks']['link']
|
87
|
-
result['lnks']['link'].each do |link_hash|
|
88
|
-
measurement.links[link_hash['t']] = link_hash['l']
|
74
|
+
# first try to match the zone code, otherwise use the zone offset
|
75
|
+
#
|
76
|
+
def self._build_timezone(data)
|
77
|
+
if data
|
78
|
+
if data['cc'] && data['cc']['lsup'] &&
|
79
|
+
(zone_match = data['cc']['lsup'].match(/ ([A-Z]{1,4})$/))
|
80
|
+
Data::Zone.new(zone_match[1])
|
81
|
+
elsif data['loc'] && data['loc']['zone']
|
82
|
+
Data::Zone.new(data['loc']['zone'].to_f)
|
89
83
|
end
|
90
84
|
end
|
91
|
-
|
92
|
-
# set local time of measurement
|
93
|
-
local_time = self.build_local_time(result)
|
94
|
-
measurement.measured_at = local_time
|
95
|
-
measurement.current.current_at = local_time
|
96
|
-
|
97
|
-
measurement
|
98
85
|
end
|
99
86
|
|
100
|
-
|
101
|
-
# this is a best guess method. the data provided for time conversions
|
102
|
-
# leaves a lot to be desired. some time zones, offsets, local times are
|
103
|
-
# out to lunch. eg. Tahiti (all times seem to be 30 min off), but there
|
104
|
-
# is no way to determine this
|
105
|
-
#
|
106
|
-
# regardless of the above, this method will trust the data given to it
|
107
|
-
#
|
108
|
-
def self.build_local_time(data)
|
87
|
+
def self._parse_local_time(data)
|
109
88
|
(data && data['loc']) ? Data::LocalTime.parse(data['loc']['tm']) : nil
|
110
89
|
end
|
111
|
-
|
112
|
-
def self.
|
90
|
+
|
91
|
+
def self._build_links(data)
|
92
|
+
links = {}
|
93
|
+
if data && data['lnks'] && data['lnks']['link']
|
94
|
+
data['lnks']['link'].each do |link_hash|
|
95
|
+
links[link_hash['t']] = link_hash['l']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
links
|
99
|
+
end
|
100
|
+
|
101
|
+
def self._build_current(data, metric=true)
|
113
102
|
raise ArgumentError unless data.is_a?(Hash)
|
114
|
-
current =
|
103
|
+
current = Measurement::Current.new
|
115
104
|
if data
|
116
105
|
if data['cc']
|
117
106
|
current.updated_at = Data::LocalDateTime.parse(data['cc']['lsup'])
|
@@ -141,14 +130,14 @@ module Barometer
|
|
141
130
|
current
|
142
131
|
end
|
143
132
|
|
144
|
-
def self.
|
133
|
+
def self._build_forecast(data, metric=true)
|
145
134
|
raise ArgumentError unless data.is_a?(Hash)
|
146
|
-
forecasts =
|
135
|
+
forecasts = Measurement::ForecastArray.new
|
147
136
|
|
148
137
|
if data && data['dayf'] && data['dayf']['day']
|
149
138
|
local_date = data['dayf']['lsup']
|
150
139
|
data['dayf']['day'].each do |forecast|
|
151
|
-
forecast_measurement =
|
140
|
+
forecast_measurement = Measurement::Forecast.new
|
152
141
|
forecast_measurement.date = Date.parse(forecast['dt'])
|
153
142
|
|
154
143
|
forecast_measurement.high = Data::Temperature.new(metric)
|
@@ -180,7 +169,7 @@ module Barometer
|
|
180
169
|
|
181
170
|
elsif part['p'] == 'n'
|
182
171
|
# add this to the NightMeasurement
|
183
|
-
forecast_measurement.night =
|
172
|
+
forecast_measurement.night = Measurement::ForecastNight.new
|
184
173
|
forecast_measurement.night.condition = part['t']
|
185
174
|
forecast_measurement.night.icon = part['icon']
|
186
175
|
forecast_measurement.night.pop = part['ppcp'].to_i
|
@@ -202,7 +191,7 @@ module Barometer
|
|
202
191
|
forecasts
|
203
192
|
end
|
204
193
|
|
205
|
-
def self.
|
194
|
+
def self._build_location(data, geo=nil)
|
206
195
|
raise ArgumentError unless data.is_a?(Hash)
|
207
196
|
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
208
197
|
location = Data::Location.new
|
@@ -224,7 +213,7 @@ module Barometer
|
|
224
213
|
location
|
225
214
|
end
|
226
215
|
|
227
|
-
def self.
|
216
|
+
def self._build_sun(data)
|
228
217
|
raise ArgumentError unless data.is_a?(Hash)
|
229
218
|
sun = nil
|
230
219
|
if data
|
@@ -239,9 +228,11 @@ module Barometer
|
|
239
228
|
|
240
229
|
# use HTTParty to get the current weather
|
241
230
|
#
|
242
|
-
def self.
|
231
|
+
def self._fetch(query, metric=true)
|
232
|
+
return unless query
|
233
|
+
puts "fetch weather.com: #{query.q}" if Barometer::debug?
|
243
234
|
self.get(
|
244
|
-
"http://xoap.weather.com/weather/local/#{query}",
|
235
|
+
"http://xoap.weather.com/weather/local/#{query.q}",
|
245
236
|
:query => { :par => @@partner_key, :key => @@license_key,
|
246
237
|
:prod => "xoap", :link => "xoap", :cc => "*",
|
247
238
|
:dayf => "5", :unit => (metric ? 'm' : 's')
|