barometer 0.8.0 → 0.9.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.
Files changed (321) hide show
  1. data/.gitignore +2 -0
  2. data/.pelusa.yml +7 -0
  3. data/.travis.yml +6 -3
  4. data/Gemfile +11 -1
  5. data/README.md +89 -244
  6. data/Rakefile +1 -1
  7. data/barometer.gemspec +22 -24
  8. data/lib/barometer.rb +14 -65
  9. data/lib/barometer/base.rb +35 -65
  10. data/lib/barometer/data.rb +15 -20
  11. data/lib/barometer/data/attribute.rb +19 -0
  12. data/lib/barometer/data/attributes/distance.rb +11 -0
  13. data/lib/barometer/data/attributes/float.rb +11 -0
  14. data/lib/barometer/data/attributes/integer.rb +11 -0
  15. data/lib/barometer/data/attributes/location.rb +11 -0
  16. data/lib/barometer/data/attributes/pressure.rb +11 -0
  17. data/lib/barometer/data/attributes/sun.rb +15 -0
  18. data/lib/barometer/data/attributes/temperature.rb +11 -0
  19. data/lib/barometer/data/attributes/time.rb +11 -0
  20. data/lib/barometer/data/attributes/vector.rb +11 -0
  21. data/lib/barometer/data/attributes/zone.rb +11 -0
  22. data/lib/barometer/data/convertable_units.rb +145 -0
  23. data/lib/barometer/data/coordinates.rb +16 -0
  24. data/lib/barometer/data/distance.rb +14 -133
  25. data/lib/barometer/data/geo.rb +22 -59
  26. data/lib/barometer/data/location.rb +14 -20
  27. data/lib/barometer/data/pressure.rb +14 -135
  28. data/lib/barometer/data/sun.rb +24 -24
  29. data/lib/barometer/data/temperature.rb +14 -169
  30. data/lib/barometer/data/vector.rb +44 -0
  31. data/lib/barometer/data/zone.rb +109 -112
  32. data/lib/barometer/query.rb +23 -161
  33. data/lib/barometer/query/base.rb +88 -0
  34. data/lib/barometer/query/converter.rb +64 -0
  35. data/lib/barometer/query/converters/from_coordinates_to_noaa_station_id.rb +30 -0
  36. data/lib/barometer/query/converters/from_geocode_to_coordinates.rb +28 -0
  37. data/lib/barometer/query/converters/from_short_zipcode_to_zipcode.rb +28 -0
  38. data/lib/barometer/query/converters/from_weather_id_to_geocode.rb +30 -0
  39. data/lib/barometer/query/converters/from_woe_id_or_ipv4_to_geocode.rb +32 -0
  40. data/lib/barometer/query/converters/to_geocode.rb +30 -0
  41. data/lib/barometer/query/converters/to_weather_id.rb +30 -0
  42. data/lib/barometer/query/converters/to_woe_id.rb +30 -0
  43. data/lib/barometer/query/format.rb +59 -0
  44. data/lib/barometer/query/formats/base.rb +22 -0
  45. data/lib/barometer/query/formats/coordinates.rb +14 -0
  46. data/lib/barometer/query/formats/geocode.rb +15 -0
  47. data/lib/barometer/query/formats/icao.rb +35 -0
  48. data/lib/barometer/query/formats/ipv4_address.rb +19 -0
  49. data/lib/barometer/query/formats/noaa_station_id.rb +15 -0
  50. data/lib/barometer/query/formats/postalcode.rb +20 -0
  51. data/lib/barometer/query/formats/short_zipcode.rb +15 -0
  52. data/lib/barometer/{translations → query/formats/translations}/icao_country_codes.yml +0 -0
  53. data/lib/barometer/{translations → query/formats/translations}/weather_country_codes.yml +0 -0
  54. data/lib/barometer/query/formats/unknown.rb +14 -0
  55. data/lib/barometer/query/formats/weather_id.rb +33 -0
  56. data/lib/barometer/query/formats/woe_id.rb +28 -0
  57. data/lib/barometer/query/formats/zipcode.rb +15 -0
  58. data/lib/barometer/query/service.rb +13 -0
  59. data/lib/barometer/query/services/apis/geonames_timezone.rb +26 -0
  60. data/lib/barometer/query/services/apis/google_geocode.rb +35 -0
  61. data/lib/barometer/query/services/apis/noaa_station.rb +31 -0
  62. data/lib/barometer/query/services/apis/weather_id.rb +35 -0
  63. data/lib/barometer/query/services/apis/wunderground_timezone.rb +26 -0
  64. data/lib/barometer/query/services/apis/yahoo_placefinder.rb +35 -0
  65. data/lib/barometer/query/services/apis/yahoo_weather.rb +31 -0
  66. data/lib/barometer/query/services/from_weather_id.rb +64 -0
  67. data/lib/barometer/query/services/geonames_timezone.rb +18 -0
  68. data/lib/barometer/query/services/google_geocode.rb +106 -0
  69. data/lib/barometer/query/services/noaa_station_id.rb +28 -0
  70. data/lib/barometer/query/services/to_weather_id.rb +25 -0
  71. data/lib/barometer/query/services/to_woe_id.rb +29 -0
  72. data/lib/barometer/query/services/wunderground_timezone.rb +18 -0
  73. data/lib/barometer/query/services/yahoo_geocode.rb +69 -0
  74. data/lib/barometer/response.rb +12 -0
  75. data/lib/barometer/response/base.rb +57 -0
  76. data/lib/barometer/response/current.rb +27 -0
  77. data/lib/barometer/response/prediction.rb +41 -0
  78. data/lib/barometer/response/prediction_collection.rb +48 -0
  79. data/lib/barometer/utils.rb +17 -0
  80. data/lib/barometer/utils/address.rb +33 -0
  81. data/lib/barometer/utils/api.rb +30 -0
  82. data/lib/barometer/utils/config_reader.rb +40 -0
  83. data/lib/barometer/utils/get.rb +17 -0
  84. data/lib/barometer/utils/json_reader.rb +22 -0
  85. data/lib/barometer/utils/payload.rb +100 -0
  86. data/lib/barometer/utils/payload_request.rb +37 -0
  87. data/lib/barometer/utils/post.rb +24 -0
  88. data/lib/barometer/utils/time.rb +78 -0
  89. data/lib/barometer/{translations → utils/translations}/zone_codes.yml +0 -0
  90. data/lib/barometer/utils/versioned_registration.rb +70 -0
  91. data/lib/barometer/utils/xml_reader.rb +27 -0
  92. data/lib/barometer/utils/zone_code_lookup.rb +30 -0
  93. data/lib/barometer/version.rb +1 -1
  94. data/lib/barometer/weather.rb +44 -173
  95. data/lib/barometer/weather_service.rb +41 -0
  96. data/lib/barometer/weather_services/base.rb +50 -0
  97. data/lib/barometer/weather_services/forecast_io.rb +36 -0
  98. data/lib/barometer/weather_services/forecast_io/api.rb +22 -0
  99. data/lib/barometer/weather_services/forecast_io/query.rb +38 -0
  100. data/lib/barometer/weather_services/forecast_io/response.rb +31 -0
  101. data/lib/barometer/weather_services/forecast_io/response/current_weather.rb +78 -0
  102. data/lib/barometer/weather_services/forecast_io/response/forecasted_weather.rb +74 -0
  103. data/lib/barometer/weather_services/forecast_io/response/location.rb +19 -0
  104. data/lib/barometer/weather_services/forecast_io/response/timezone.rb +25 -0
  105. data/lib/barometer/weather_services/noaa.rb +21 -305
  106. data/lib/barometer/weather_services/noaa/current_api.rb +25 -0
  107. data/lib/barometer/weather_services/noaa/current_query.rb +30 -0
  108. data/lib/barometer/weather_services/noaa/current_response.rb +29 -0
  109. data/lib/barometer/weather_services/noaa/forecast_api.rb +25 -0
  110. data/lib/barometer/weather_services/noaa/forecast_query.rb +39 -0
  111. data/lib/barometer/weather_services/noaa/forecast_response.rb +28 -0
  112. data/lib/barometer/weather_services/noaa/response/current_location.rb +42 -0
  113. data/lib/barometer/weather_services/noaa/response/current_station.rb +46 -0
  114. data/lib/barometer/weather_services/noaa/response/current_weather.rb +82 -0
  115. data/lib/barometer/weather_services/noaa/response/forecasted_weather.rb +90 -0
  116. data/lib/barometer/weather_services/noaa/response/location.rb +19 -0
  117. data/lib/barometer/weather_services/noaa/response/timezone.rb +15 -0
  118. data/lib/barometer/weather_services/response.rb +9 -0
  119. data/lib/barometer/weather_services/response/location.rb +42 -0
  120. data/lib/barometer/weather_services/response/time_zone.rb +19 -0
  121. data/lib/barometer/weather_services/weather_bug.rb +24 -280
  122. data/lib/barometer/weather_services/weather_bug/current_api.rb +26 -0
  123. data/lib/barometer/weather_services/weather_bug/current_response.rb +33 -0
  124. data/lib/barometer/weather_services/weather_bug/forecast_api.rb +26 -0
  125. data/lib/barometer/weather_services/weather_bug/forecast_response.rb +29 -0
  126. data/lib/barometer/weather_services/weather_bug/query.rb +42 -0
  127. data/lib/barometer/weather_services/weather_bug/response/current_weather.rb +82 -0
  128. data/lib/barometer/weather_services/weather_bug/response/forecasted_weather.rb +67 -0
  129. data/lib/barometer/weather_services/weather_bug/response/location.rb +23 -0
  130. data/lib/barometer/weather_services/weather_bug/response/station.rb +43 -0
  131. data/lib/barometer/weather_services/weather_bug/response/sun.rb +32 -0
  132. data/lib/barometer/weather_services/weather_bug/response/time_helper.rb +52 -0
  133. data/lib/barometer/weather_services/weather_bug/response/timezone.rb +15 -0
  134. data/lib/barometer/weather_services/wunderground_v1.rb +32 -0
  135. data/lib/barometer/weather_services/wunderground_v1/current_api.rb +21 -0
  136. data/lib/barometer/weather_services/wunderground_v1/current_response.rb +31 -0
  137. data/lib/barometer/weather_services/wunderground_v1/forecast_api.rb +21 -0
  138. data/lib/barometer/weather_services/wunderground_v1/forecast_response.rb +33 -0
  139. data/lib/barometer/weather_services/wunderground_v1/query.rb +30 -0
  140. data/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb +92 -0
  141. data/lib/barometer/weather_services/wunderground_v1/response/forecasted_weather.rb +87 -0
  142. data/lib/barometer/weather_services/wunderground_v1/response/full_timezone.rb +22 -0
  143. data/lib/barometer/weather_services/wunderground_v1/response/location.rb +43 -0
  144. data/lib/barometer/weather_services/wunderground_v1/response/station.rb +39 -0
  145. data/lib/barometer/weather_services/wunderground_v1/response/sun.rb +53 -0
  146. data/lib/barometer/weather_services/wunderground_v1/response/timezone.rb +15 -0
  147. data/lib/barometer/weather_services/yahoo.rb +16 -198
  148. data/lib/barometer/weather_services/yahoo/api.rb +21 -0
  149. data/lib/barometer/weather_services/yahoo/query.rb +42 -0
  150. data/lib/barometer/weather_services/yahoo/response.rb +39 -0
  151. data/lib/barometer/weather_services/yahoo/response/current_weather.rb +86 -0
  152. data/lib/barometer/weather_services/yahoo/response/forecasted_weather.rb +71 -0
  153. data/lib/barometer/weather_services/yahoo/response/location.rb +47 -0
  154. data/lib/barometer/weather_services/yahoo/response/sun.rb +43 -0
  155. data/lib/barometer/weather_services/yahoo/response/timezone.rb +15 -0
  156. data/spec/barometer_spec.rb +18 -120
  157. data/spec/base_spec.rb +114 -0
  158. data/spec/cassettes/Converter_FromCoordinatesToNoaaStationId.json +1 -0
  159. data/spec/cassettes/Converter_FromWeatherIdToGeocode.json +1 -0
  160. data/spec/cassettes/Converter_FromWoeIdOrIpv4ToGeocode.json +1 -0
  161. data/spec/cassettes/Converter_ToGeocode.json +1 -0
  162. data/spec/cassettes/Converter_ToWeatherId.json +1 -0
  163. data/spec/cassettes/Converter_ToWoeId.json +1 -0
  164. data/spec/cassettes/Service_FromWeatherId.json +1 -0
  165. data/spec/cassettes/Service_GoogleGeocode.json +1 -0
  166. data/spec/cassettes/Service_NoaaStation.json +1 -0
  167. data/spec/cassettes/Service_ToWeatherId.json +1 -0
  168. data/spec/cassettes/Service_ToWoeId.json +1 -0
  169. data/spec/cassettes/Service_YahooGeocode.json +1 -0
  170. data/spec/cassettes/WeatherService_ForecastIo.json +1 -0
  171. data/spec/cassettes/WeatherService_Noaa.json +1 -1
  172. data/spec/cassettes/WeatherService_WeatherBug.json +1 -1
  173. data/spec/cassettes/WeatherService_WundergroundV1.json +1 -0
  174. data/spec/cassettes/WeatherService_Yahoo.json +1 -1
  175. data/spec/data/attributes/distance_spec.rb +60 -0
  176. data/spec/data/attributes/location_spec.rb +41 -0
  177. data/spec/data/attributes/pressure_spec.rb +60 -0
  178. data/spec/data/attributes/sun_spec.rb +33 -0
  179. data/spec/data/attributes/temperature_spec.rb +60 -0
  180. data/spec/data/attributes/time_spec.rb +58 -0
  181. data/spec/data/attributes/vector_spec.rb +43 -0
  182. data/spec/data/attributes/zone_spec.rb +34 -0
  183. data/spec/data/convertable_units_spec.rb +299 -0
  184. data/spec/data/coordinates_spec.rb +15 -0
  185. data/spec/data/distance_spec.rb +49 -333
  186. data/spec/data/geo_spec.rb +72 -71
  187. data/spec/data/location_spec.rb +70 -65
  188. data/spec/data/pressure_spec.rb +49 -333
  189. data/spec/data/sun_spec.rb +57 -81
  190. data/spec/data/temperature_spec.rb +49 -393
  191. data/spec/data/vector_spec.rb +100 -0
  192. data/spec/data/zone_spec.rb +199 -266
  193. data/spec/query/base_spec.rb +296 -0
  194. data/spec/query/converter_spec.rb +98 -0
  195. data/spec/query/converters/from_coordinates_to_noaa_station_id_spec.rb +35 -0
  196. data/spec/query/converters/from_geocode_to_coordinates_spec.rb +25 -0
  197. data/spec/query/converters/from_short_zipcode_to_zipcode_spec.rb +31 -0
  198. data/spec/query/converters/from_weather_id_to_geocode_spec.rb +40 -0
  199. data/spec/query/converters/from_woe_id_or_ipv4_to_geocode_spec.rb +51 -0
  200. data/spec/query/converters/to_geocode_spec.rb +99 -0
  201. data/spec/query/converters/to_weather_id_spec.rb +35 -0
  202. data/spec/query/converters/to_woe_id_spec.rb +74 -0
  203. data/spec/query/formats/base_spec.rb +15 -0
  204. data/spec/query/formats/coordinates_spec.rb +13 -0
  205. data/spec/query/formats/geocode_spec.rb +9 -0
  206. data/spec/query/formats/icao_spec.rb +20 -0
  207. data/spec/query/formats/ipv4_address_spec.rb +33 -0
  208. data/spec/query/formats/noaa_station_id_spec.rb +9 -0
  209. data/spec/query/formats/postalcode_spec.rb +18 -0
  210. data/spec/query/formats/short_zipcode_spec.rb +18 -0
  211. data/spec/query/formats/unknown_spec.rb +9 -0
  212. data/spec/query/formats/weather_id_spec.rb +31 -0
  213. data/spec/query/formats/woe_id_spec.rb +45 -0
  214. data/spec/query/formats/zipcode_spec.rb +18 -0
  215. data/spec/query/formats_spec.rb +55 -0
  216. data/spec/query/services/from_weather_id_spec.rb +54 -0
  217. data/spec/query/services/google_geocode_spec.rb +60 -0
  218. data/spec/query/services/noaa_station_id_spec.rb +23 -0
  219. data/spec/query/services/to_weather_id_spec.rb +23 -0
  220. data/spec/query/services/to_woe_id_spec.rb +51 -0
  221. data/spec/query/services/yahoo_geocode_spec.rb +72 -0
  222. data/spec/response/base_spec.rb +103 -0
  223. data/spec/response/current_spec.rb +33 -0
  224. data/spec/response/predicition_spec.rb +65 -0
  225. data/spec/response/prediction_collection_spec.rb +97 -0
  226. data/spec/spec_helper.rb +14 -12
  227. data/spec/support/key_file_parser.rb +22 -0
  228. data/spec/support/matchers/formats.rb +36 -0
  229. data/spec/support/matchers/have_data.rb +46 -0
  230. data/spec/support/matchers/have_field.rb +128 -0
  231. data/spec/support/matchers/have_forecast.rb +46 -0
  232. data/spec/support/matchers/path.rb +23 -0
  233. data/spec/support/query_factory.rb +20 -0
  234. data/spec/utils/address_spec.rb +67 -0
  235. data/spec/utils/config_reader_spec.rb +157 -0
  236. data/spec/utils/get_spec.rb +22 -0
  237. data/spec/utils/payload_request_spec.rb +69 -0
  238. data/spec/utils/payload_spec.rb +168 -0
  239. data/spec/utils/post_spec.rb +20 -0
  240. data/spec/utils/time_spec.rb +93 -0
  241. data/spec/utils/versioned_registration_spec.rb +105 -0
  242. data/spec/weather_services/base_spec.rb +116 -0
  243. data/spec/weather_services/forecast_io_spec.rb +71 -0
  244. data/spec/weather_services/noaa/current_response_spec.rb +22 -0
  245. data/spec/weather_services/noaa/forecast_response_spec.rb +33 -0
  246. data/spec/weather_services/noaa_spec.rb +68 -166
  247. data/spec/weather_services/weather_bug/current_response_spec.rb +64 -0
  248. data/spec/weather_services/weather_bug/forecast_response_spec.rb +23 -0
  249. data/spec/weather_services/weather_bug_spec.rb +62 -202
  250. data/spec/weather_services/wunderground_v1/current_response_spec.rb +19 -0
  251. data/spec/weather_services/wunderground_v1/forecast_response_spec.rb +62 -0
  252. data/spec/weather_services/wunderground_v1_spec.rb +78 -0
  253. data/spec/weather_services/yahoo/response_spec.rb +73 -0
  254. data/spec/weather_services/yahoo_spec.rb +52 -135
  255. data/spec/weather_services_spec.rb +103 -0
  256. data/spec/weather_spec.rb +167 -347
  257. metadata +342 -123
  258. data/.document +0 -5
  259. data/TODO +0 -60
  260. data/bin/barometer +0 -441
  261. data/lib/barometer/data/local_datetime.rb +0 -145
  262. data/lib/barometer/data/local_time.rb +0 -134
  263. data/lib/barometer/data/speed.rb +0 -158
  264. data/lib/barometer/data/units.rb +0 -49
  265. data/lib/barometer/formats.rb +0 -13
  266. data/lib/barometer/formats/coordinates.rb +0 -57
  267. data/lib/barometer/formats/format.rb +0 -64
  268. data/lib/barometer/formats/geocode.rb +0 -60
  269. data/lib/barometer/formats/icao.rb +0 -37
  270. data/lib/barometer/formats/postalcode.rb +0 -22
  271. data/lib/barometer/formats/short_zipcode.rb +0 -17
  272. data/lib/barometer/formats/weather_id.rb +0 -92
  273. data/lib/barometer/formats/woe_id.rb +0 -150
  274. data/lib/barometer/formats/zipcode.rb +0 -31
  275. data/lib/barometer/key_file_parser.rb +0 -20
  276. data/lib/barometer/measurements/measurement.rb +0 -202
  277. data/lib/barometer/measurements/result.rb +0 -207
  278. data/lib/barometer/measurements/result_array.rb +0 -75
  279. data/lib/barometer/services.rb +0 -19
  280. data/lib/barometer/weather_services/service.rb +0 -189
  281. data/lib/barometer/weather_services/wunderground.rb +0 -264
  282. data/lib/barometer/web_services/geocode.rb +0 -34
  283. data/lib/barometer/web_services/noaa_station_id.rb +0 -53
  284. data/lib/barometer/web_services/placemaker.rb +0 -95
  285. data/lib/barometer/web_services/timezone.rb +0 -38
  286. data/lib/barometer/web_services/weather_id.rb +0 -50
  287. data/lib/barometer/web_services/web_service.rb +0 -29
  288. data/spec/cassettes/Barometer.json +0 -1
  289. data/spec/cassettes/Query.json +0 -1
  290. data/spec/cassettes/Query_Format_Coordinates.json +0 -1
  291. data/spec/cassettes/Query_Format_Geocode.json +0 -1
  292. data/spec/cassettes/Query_Format_WeatherID.json +0 -1
  293. data/spec/cassettes/Query_Format_WoeID.json +0 -1
  294. data/spec/cassettes/WeatherService.json +0 -1
  295. data/spec/cassettes/WeatherService_Wunderground.json +0 -1
  296. data/spec/cassettes/WebService_Geocode.json +0 -1
  297. data/spec/cassettes/WebService_NoaaStation.json +0 -1
  298. data/spec/data/local_datetime_spec.rb +0 -274
  299. data/spec/data/local_time_spec.rb +0 -239
  300. data/spec/data/speed_spec.rb +0 -374
  301. data/spec/data/units_spec.rb +0 -101
  302. data/spec/formats/coordinates_spec.rb +0 -166
  303. data/spec/formats/format_spec.rb +0 -74
  304. data/spec/formats/geocode_spec.rb +0 -163
  305. data/spec/formats/icao_spec.rb +0 -55
  306. data/spec/formats/postalcode_spec.rb +0 -53
  307. data/spec/formats/short_zipcode_spec.rb +0 -47
  308. data/spec/formats/weather_id_spec.rb +0 -182
  309. data/spec/formats/woe_id_spec.rb +0 -211
  310. data/spec/formats/zipcode_spec.rb +0 -103
  311. data/spec/key_file_parser_spec.rb +0 -28
  312. data/spec/measurements/measurement_spec.rb +0 -381
  313. data/spec/measurements/result_array_spec.rb +0 -150
  314. data/spec/measurements/result_spec.rb +0 -632
  315. data/spec/query_spec.rb +0 -498
  316. data/spec/weather_services/services_spec.rb +0 -135
  317. data/spec/weather_services/wunderground_spec.rb +0 -179
  318. data/spec/web_services/geocode_spec.rb +0 -31
  319. data/spec/web_services/noaa_station_id_spec.rb +0 -33
  320. data/spec/web_services/placemaker_spec.rb +0 -41
  321. data/spec/web_services/web_services_spec.rb +0 -20
@@ -0,0 +1,19 @@
1
+ module Barometer
2
+ module WeatherService
3
+ class Noaa
4
+ class Response
5
+ class Location < WeatherService::Response::Location
6
+ private
7
+
8
+ def latitude
9
+ payload.fetch('location', 'point', '@latitude')
10
+ end
11
+
12
+ def longitude
13
+ payload.fetch('location', 'point', '@longitude')
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module Barometer
2
+ module WeatherService
3
+ class Noaa
4
+ class Response
5
+ class TimeZone < WeatherService::Response::TimeZone
6
+ private
7
+
8
+ def time_zone
9
+ payload.using(/ ([A-Z]*)$/).fetch('observation_time')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Barometer
2
+ module WeatherService
3
+ module Response
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative 'response/location'
9
+ require_relative 'response/time_zone'
@@ -0,0 +1,42 @@
1
+ module Barometer
2
+ module WeatherService
3
+ module Response
4
+ class Location
5
+ def initialize(payload)
6
+ @payload = payload
7
+ end
8
+
9
+ def parse
10
+ Data::Location.new(
11
+ id: id,
12
+ name: name,
13
+ city: city,
14
+ state_name: state_name,
15
+ state_code: state_code,
16
+ country: country,
17
+ country_code: country_code,
18
+ zip_code: zip_code,
19
+ latitude: latitude,
20
+ longitude: longitude
21
+ )
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :payload
27
+
28
+ def id; end
29
+ def name; end
30
+ def city; end
31
+ def state_name; end
32
+ def state_code; end
33
+ def country; end
34
+ def country_code; end
35
+ def zip_code; end
36
+ def zip_code; end
37
+ def latitude; end
38
+ def longitude; end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ module Barometer
2
+ module WeatherService
3
+ module Response
4
+ class TimeZone
5
+ def initialize(payload)
6
+ @payload = payload
7
+ end
8
+
9
+ def parse
10
+ Data::Zone.new(time_zone)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :payload
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,297 +1,41 @@
1
- require 'crack'
1
+ require_relative 'weather_bug/current_api'
2
+ require_relative 'weather_bug/current_response'
3
+ require_relative 'weather_bug/forecast_api'
4
+ require_relative 'weather_bug/forecast_response'
2
5
 
3
6
  module Barometer
4
- #
5
- # = WeatherBug
6
- # www.weatherbug.com
7
- #
8
- # - key required: YES (api_code)
9
- # - registration required: YES
10
- # - supported countries: US (by zipcode), International (by coordinates)
11
- #
12
- # === performs geo coding
13
- # - city: YES
14
- # - coordinates: PARTIAL (just for weather station)
15
- #
16
- # === time info
17
- # - sun rise/set: YES
18
- # - provides timezone: NO, but provides a timezone short code and utc offset
19
- # - requires TZInfo: NO
20
- #
21
- # == resources
22
- # - API: http://weather.weatherbug.com/corporate/products/API/help.aspx
23
- #
24
- # === Possible queries:
25
- # - http://[API_Code].api.wxbug.net:80/getLiveWeatherRSS.aspx?ACode=[API_Code]&OutputType=1&UnitType=1&zipCode=90210
26
- #
27
- # where query can be:
28
- # - zipcode (US) [5 digits only]
29
- # - coordinates (International)
30
- #
31
- # = WeatherBug.com terms of use
32
- # ???
33
- #
34
- # == notes
35
- # - WeatherBug also supports queries using "citycode" and "stationID", but these
36
- # are specific to WeatherBug and un-supported by Barometer
37
- #
38
- class WeatherService::WeatherBug < WeatherService
39
-
40
- @@api_code = nil
41
-
42
- def self.keys=(keys)
43
- raise ArgumentError unless keys.is_a?(Hash)
44
- keys.each do |key, value|
45
- @@api_code = value.to_s if key.to_s.downcase == "code"
7
+ module WeatherService
8
+ class WeatherBug
9
+ def self.call(query, config={})
10
+ WeatherBug.new(query, config).measure!
46
11
  end
47
- end
48
-
49
- #########################################################################
50
- # PRIVATE
51
- # If class methods could be private, the remaining methods would be.
52
- #
53
-
54
- def self._source_name; :weather_bug; end
55
- def self._accepted_formats; [:short_zipcode, :coordinates]; end
56
-
57
- def self._has_keys?; !@@api_code.nil?; end
58
- def self._requires_keys?; true; end
59
-
60
- def self._wet_icon_codes
61
- codes = [5,6,8,9,11,12,14,15] + (18..22).to_a + [25] + (27..30).to_a +
62
- [32,36] + (38..49).to_a + (52..63).to_a + (80..157).to_a +
63
- (161..176).to_a
64
- codes.collect {|c| c.to_s}
65
- end
66
- def self._sunny_icon_codes
67
- codes = [0,2,3,4,7,26,31,64,65,75]
68
- codes.collect {|c| c.to_s}
69
- end
70
12
 
71
- def self._build_extra(measurement, result, metric=true)
72
- #raise ArgumentError unless measurement.is_a?(Data::Measurement)
73
- #raise ArgumentError unless query.is_a?(Barometer::Query)
74
-
75
- # use todays sun data for all future days
76
- if measurement.forecast && measurement.current.sun
77
- measurement.forecast.each do |forecast|
78
- forecast.sun = measurement.current.sun
79
- end
13
+ def initialize(query, config={})
14
+ @query = query
15
+ @api_code = config[:keys][:code] if config[:keys]
80
16
  end
81
17
 
82
- measurement
83
- end
18
+ def measure!
19
+ validate_key!
84
20
 
85
- def self._parse_local_time(data)
86
- Data::LocalTime.new(
87
- data["aws:ob_date"]["aws:hour"]["hour_24"].to_i,
88
- data["aws:ob_date"]["aws:minute"]["number"].to_i,
89
- data["aws:ob_date"]["aws:second"]["number"].to_i
90
- ) if data && data["aws:ob_date"]
91
- end
21
+ current_weather_api = CurrentApi.new(query, api_code)
22
+ response = CurrentResponse.new.parse(current_weather_api.get)
92
23
 
93
- def self._build_timezone(data)
94
- if data && data["aws:ob_date"] && data["aws:ob_date"]["aws:time_zone"]
95
- Data::Zone.new(data["aws:ob_date"]["aws:time_zone"]["abbrv"])
24
+ forecast_weather_api = ForecastApi.new(current_weather_api.query, api_code)
25
+ ForecastResponse.new(response).parse(forecast_weather_api.get)
96
26
  end
97
- end
98
27
 
99
- def self._build_current(data, metric=true)
100
- raise ArgumentError unless data.is_a?(Hash)
28
+ private
101
29
 
102
- current = Measurement::Result.new
103
- # current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
104
- current.humidity = data['aws:humidity'].to_i
105
- current.condition = data['aws:current_condition'] if data['aws:current_condition']
106
- current.icon = data['aws:icon'].to_i.to_s if data['aws:icon']
30
+ attr_reader :query, :api_code
107
31
 
108
- current.temperature = Data::Temperature.new(metric)
109
- current.temperature << data['aws:temp']
110
-
111
- current.wind = Data::Speed.new(metric)
112
- current.wind << data['aws:wind_speed'].to_f
113
- current.wind.direction = data['aws:wind_direction']
114
-
115
- current.pressure = Data::Pressure.new(metric)
116
- current.pressure << data['aws:pressure']
117
-
118
- current.dew_point = Data::Temperature.new(metric)
119
- current.dew_point << data['aws:dew_point']
120
-
121
- current.wind_chill = Data::Temperature.new(metric)
122
- current.wind_chill << data['aws:feels_like']
123
-
124
- current
125
- end
126
-
127
- def self._build_forecast(data, metric=true)
128
- raise ArgumentError unless data.is_a?(Hash)
129
- forecasts = Measurement::ResultArray.new
130
- # go through each forecast and create an instance
131
- if data && data["forecast"]
132
- start_date = Date.strptime(data['date'], "%m/%d/%Y %H:%M:%S %p")
133
- i = 0
134
- data["forecast"].each do |forecast|
135
- forecast_measurement = Measurement::Result.new
136
- icon_match = forecast['image']['icon'].match(/cond(\d*)\.gif$/)
137
- forecast_measurement.icon = icon_match[1].to_i.to_s if icon_match
138
- forecast_measurement.date = start_date + i
139
- forecast_measurement.condition = forecast['short_prediction']
140
-
141
- forecast_measurement.high = Data::Temperature.new(metric)
142
- forecast_measurement.high << forecast['high']['__content__']
143
-
144
- forecast_measurement.low = Data::Temperature.new(metric)
145
- forecast_measurement.low << forecast['low']['__content__']
146
-
147
- forecasts << forecast_measurement
148
- i += 1
32
+ def validate_key!
33
+ unless api_code && !api_code.empty?
34
+ raise KeyRequired
149
35
  end
150
36
  end
151
- forecasts
152
37
  end
153
-
154
- def self._build_location(data, geo=nil)
155
- raise ArgumentError unless data.is_a?(Hash)
156
- raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
157
- location = Data::Location.new
158
- # use the geocoded data if available, otherwise get data from result
159
- if geo
160
- location.city = geo.locality
161
- location.state_code = geo.region
162
- location.country = geo.country
163
- location.country_code = geo.country_code
164
- location.latitude = geo.latitude
165
- location.longitude = geo.longitude
166
- else
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']
171
- end
172
- end
173
- location
174
- end
175
-
176
- def self._build_station(data)
177
- raise ArgumentError unless data.is_a?(Hash)
178
- station = Data::Location.new
179
- station.id = data['aws:station_id']
180
- station.name = data['aws:station']
181
- station.city = data['aws:city_state'].split(',')[0].strip
182
- station.state_code = data['aws:city_state'].split(',')[1].strip
183
- station.country = data['aws:country']
184
- station.zip_code = data['aws:station_zipcode']
185
- station.latitude = data['aws:latitude']
186
- station.longitude = data['aws:longitude']
187
- station
188
- end
189
-
190
- def self._build_sun(data)
191
- raise ArgumentError unless data.is_a?(Hash)
192
- sun = nil
193
- if data
194
- if data['aws:sunrise']
195
- rise = Data::LocalTime.new(
196
- data['aws:sunrise']['aws:hour']['hour_24'].to_i,
197
- data['aws:sunrise']['aws:minute']['number'].to_i,
198
- data['aws:sunrise']['aws:second']['number'].to_i
199
- )
200
- end
201
- if data['aws:sunset']
202
- set = Data::LocalTime.new(
203
- data['aws:sunset']['aws:hour']['hour_24'].to_i,
204
- data['aws:sunset']['aws:minute']['number'].to_i,
205
- data['aws:sunset']['aws:second']['number'].to_i
206
- )
207
- sun = Data::Sun.new(rise,set)
208
- end
209
- end
210
- sun || Data::Sun.new
211
- end
212
-
213
- # override default _fetch behavior
214
- # this service requires TWO seperate http requests (one for current
215
- # and one for forecasted weather) ... combine the results
216
- #
217
- def self._fetch(query, metric=true)
218
- result = []
219
- result << _fetch_current(query,metric)
220
- result << _fetch_forecast(query,metric)
221
- result
222
- end
223
-
224
- # use HTTParty to get the current weather
225
- #
226
- def self._fetch_current(query, metric=true)
227
- puts "fetch weatherbug current: #{query.q}" if Barometer::debug?
228
-
229
- q = ( query.format.to_sym == :short_zipcode ?
230
- { :zipCode => query.q } :
231
- { :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
232
-
233
- # httparty and the xml builder it uses miss some information
234
- # 1st - get the raw response
235
- # 2nd - manually get the missing information
236
- # 3rd - let httparty build xml as normal
237
- #
238
- response = self.get(
239
- "http://#{@@api_code}.api.wxbug.net/getLiveWeatherRSS.aspx",
240
- :query => { :ACode => @@api_code,
241
- :OutputType => "1", :UnitType => (metric ? '1' : '0')
242
- }.merge(q),
243
- :format => :plain,
244
- :timeout => Barometer.timeout
245
- )
246
-
247
- # get icon
248
- icon_match = response.match(/cond(\d*)\.gif/)
249
- icon = icon_match[1] if icon_match
250
-
251
- # get station zipcode
252
- zip_match = response.match(/zipcode=\"(\d*)\"/)
253
- zipcode = zip_match[1] if zip_match
254
-
255
- # build xml
256
- output = ::Crack::XML.parse(response)
257
- output = output["aws:weather"]["aws:ob"]
258
-
259
- # add missing data
260
- output["aws:icon"] = icon
261
- output["aws:station_zipcode"] = zipcode
262
-
263
- output
264
- end
265
-
266
- # use HTTParty to get the current weather
267
- #
268
- def self._fetch_forecast(query, metric=true)
269
- puts "fetch weatherbug forecast: #{query.q}" if Barometer::debug?
270
-
271
- q = ( query.format.to_sym == :short_zipcode ?
272
- { :zipCode => query.q } :
273
- { :lat => query.q.split(',')[0], :long => query.q.split(',')[1] })
274
-
275
- self.get(
276
- "http://#{@@api_code}.api.wxbug.net/getForecastRSS.aspx",
277
- :query => { :ACode => @@api_code,
278
- :OutputType => "1", :UnitType => (metric ? '1' : '0')
279
- }.merge(q),
280
- :format => :xml,
281
- :timeout => Barometer.timeout
282
- )["weather"]["forecasts"]
283
- end
284
-
285
- # since we have two sets of data, override these calls to choose the
286
- # right set of data
287
- #
288
- def self._current_result(data); data[0]; end
289
- def self._forecast_result(data=nil); data[1]; end
290
- def self._location_result(data=nil); data[1]; end
291
- def self._station_result(data=nil); data[0]; end
292
- def self._sun_result(data=nil); data[0]; end
293
- def self._timezone_result(data=nil); data[0]; end
294
- def self._time_result(data=nil); data[0]; end
295
-
296
38
  end
297
39
  end
40
+
41
+ Barometer::WeatherService.register(:weather_bug, Barometer::WeatherService::WeatherBug)
@@ -0,0 +1,26 @@
1
+ require_relative 'query'
2
+
3
+ module Barometer
4
+ module WeatherService
5
+ class WeatherBug
6
+ class CurrentApi < Utils::Api
7
+ def initialize(query, api_code)
8
+ @query = WeatherBug::Query.new(query)
9
+ @api_code = api_code
10
+ end
11
+
12
+ def url
13
+ "http://#{@api_code}.api.wxbug.net/getLiveWeatherRSS.aspx"
14
+ end
15
+
16
+ def params
17
+ {ACode: @api_code, OutputType: '1'}.merge(@query.to_param)
18
+ end
19
+
20
+ def unwrap_nodes
21
+ ['weather', 'ob']
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end