@@ -1,107 +0,0 @@ |
||
| 1 |
-require 'forecast_io' |
|
| 2 |
-require 'date' |
|
| 3 |
- |
|
| 4 |
-module Agents |
|
| 5 |
- class ForecastAgent < Agent |
|
| 6 |
- cannot_receive_events! |
|
| 7 |
- |
|
| 8 |
- description <<-MD |
|
| 9 |
- The ForecastAgent creates an event for the following day's weather at a given `latitude` and `longitude`. |
|
| 10 |
- |
|
| 11 |
- You also must select which `day` you would like to get the weather for where the number 0 is for today and 1 is for tomorrow and so on. Weather is only returned for 1 week at a time. |
|
| 12 |
- |
|
| 13 |
- You must setup an [API key for Forecast](https://developer.forecast.io/) in order to use this Agent. |
|
| 14 |
- MD |
|
| 15 |
- |
|
| 16 |
- event_description <<-MD |
|
| 17 |
- Events look like this: |
|
| 18 |
- |
|
| 19 |
- {
|
|
| 20 |
- "time" : 1391320800, |
|
| 21 |
- "summary" : "Rain throughout the day.", |
|
| 22 |
- "icon" : "rain", |
|
| 23 |
- "sunriseTime" : "06:48", |
|
| 24 |
- "sunsetTime" : "17:16", |
|
| 25 |
- "moonPhase" : 0.11, |
|
| 26 |
- "precipIntensity" : 0.0582, |
|
| 27 |
- "precipIntensityMax" : 0.1705, |
|
| 28 |
- "precipIntensityMaxTime" : "21:00", |
|
| 29 |
- "precipProbability" : 1, |
|
| 30 |
- "precipType" : "rain", |
|
| 31 |
- "temperatureMin" : 35.67, |
|
| 32 |
- "temperatureMinTime" : "23:00", |
|
| 33 |
- "temperatureMax" : 50.82, |
|
| 34 |
- "temperatureMaxTime" : "02:00", |
|
| 35 |
- "apparentTemperatureMin" : 26.11, |
|
| 36 |
- "apparentTemperatureMinTime" : "23:00", |
|
| 37 |
- "apparentTemperatureMax" : 50.82, |
|
| 38 |
- "apparentTemperatureMaxTime" : "02:00", |
|
| 39 |
- "dewPoint" : 41, |
|
| 40 |
- "humidity" : 0.92, |
|
| 41 |
- "windSpeed" : 4.59, |
|
| 42 |
- "windBearing" : 358, |
|
| 43 |
- "visibility" : 5.92, |
|
| 44 |
- "cloudCover" : 0.99, |
|
| 45 |
- "pressure" : 1017.66, |
|
| 46 |
- "ozone" : 278.6 |
|
| 47 |
- } |
|
| 48 |
- |
|
| 49 |
- MD |
|
| 50 |
- |
|
| 51 |
- default_schedule "8pm" |
|
| 52 |
- |
|
| 53 |
- def working? |
|
| 54 |
- event_created_within?(2) && !recent_error_logs? |
|
| 55 |
- end |
|
| 56 |
- |
|
| 57 |
- def key_setup? |
|
| 58 |
- options['api_key'] && options['api_key'] != "your-key" |
|
| 59 |
- end |
|
| 60 |
- |
|
| 61 |
- def default_options |
|
| 62 |
- {
|
|
| 63 |
- 'api_key' => "your-key", |
|
| 64 |
- 'latitude' => "36.166667", |
|
| 65 |
- 'longitude' => "-86.783333", |
|
| 66 |
- 'day' => "0" |
|
| 67 |
- } |
|
| 68 |
- end |
|
| 69 |
- |
|
| 70 |
- def validate_options |
|
| 71 |
- errors.add(:base, "latitude is required") unless options['latitude'].present? |
|
| 72 |
- errors.add(:base, "longitude is required") unless options['longitude'].present? |
|
| 73 |
- errors.add(:base, "api_key is required") unless options['api_key'].present? |
|
| 74 |
- errors.add(:base, "day selection is required") unless options['day'].present? |
|
| 75 |
- end |
|
| 76 |
- |
|
| 77 |
- def check |
|
| 78 |
- if key_setup? |
|
| 79 |
- ForecastIO.api_key = options['api_key'] |
|
| 80 |
- ForecastIO.forecast(options['latitude'],options['longitude']).daily.each do |key, value| |
|
| 81 |
- if key == "data" |
|
| 82 |
- value.each do |day| |
|
| 83 |
- if day_diff(day.time) == options['day'].tp_i |
|
| 84 |
- day.sunriseTime = Time.at(day.sunriseTime).strftime("%H:%M")
|
|
| 85 |
- day.sunsetTime = Time.at(day.sunsetTime).strftime("%H:%M")
|
|
| 86 |
- day.precipIntensityMaxTime = Time.at(day.precipIntensityMaxTime).strftime("%H:%M")
|
|
| 87 |
- day.temperatureMinTime = Time.at(day.temperatureMinTime).strftime("%H:%M")
|
|
| 88 |
- day.temperatureMaxTime = Time.at(day.temperatureMaxTime).strftime("%H:%M")
|
|
| 89 |
- day.apparentTemperatureMinTime = Time.at(day.apparentTemperatureMinTime).strftime("%H:%M")
|
|
| 90 |
- day.apparentTemperatureMaxTime = Time.at(day.apparentTemperatureMaxTime).strftime("%H:%M")
|
|
| 91 |
- create_event :payload => day |
|
| 92 |
- end |
|
| 93 |
- end |
|
| 94 |
- end |
|
| 95 |
- end |
|
| 96 |
- end |
|
| 97 |
- end |
|
| 98 |
- |
|
| 99 |
- def day_diff(day) |
|
| 100 |
- a=Time.at(day).to_date |
|
| 101 |
- b=Time.now.to_date |
|
| 102 |
- days=(a-b).to_i |
|
| 103 |
- return days |
|
| 104 |
- end |
|
| 105 |
- |
|
| 106 |
- end |
|
| 107 |
-end |
@@ -6,11 +6,19 @@ module Agents |
||
| 6 | 6 |
cannot_receive_events! |
| 7 | 7 |
|
| 8 | 8 |
description <<-MD |
| 9 |
- The WeatherAgent creates an event for the following day's weather at a given `location`. |
|
| 9 |
+ The WeatherAgent creates an event for the day's weather at a given `location`. |
|
| 10 | 10 |
|
| 11 |
- The `location` can be a US zipcode, or any location that Wunderground supports. To find one, search [wunderground.com](http://wunderground.com) and copy the location part of the URL. For example, a result for San Francisco gives `http://www.wunderground.com/US/CA/San_Francisco.html` and London, England gives `http://www.wunderground.com/q/zmw:00000.1.03772`. The locations in each are `US/CA/San_Francisco` and `zmw:00000.1.03772`, respectively. |
|
| 11 |
+ You also must select `which_day` you would like to get the weather for where the number 0 is for today and 1 is for tomorrow and so on. Weather is only returned for 1 week at a time. |
|
| 12 | 12 |
|
| 13 |
- You must setup an [API key for Wunderground](http://www.wunderground.com/weather/api/) in order to use this Agent. |
|
| 13 |
+ The weather can be provided by either Wunderground or ForecastIO. To choose which `service` to use, enter either `forecastio` or `wunderground`. |
|
| 14 |
+ |
|
| 15 |
+ The `location` can be a US zipcode, or any location that Wunderground supports. To find one, search [wunderground.com](http://wunderground.com) and copy the location part of the URL. For example, a result for San Francisco gives `http://www.wunderground.com/US/CA/San_Francisco.html` and London, England gives `http://www.wunderground.com/q/zmw:00000.1.03772`. The locations in each are `US/CA/San_Francisco` and `zmw:00000.1.03772`, respectively. |
|
| 16 |
+ |
|
| 17 |
+ If you plan on using ForecastIO, the `location` must be a set of GPS coordinates. |
|
| 18 |
+ |
|
| 19 |
+ You must setup an [API key for Wunderground](http://www.wunderground.com/weather/api/) in order to use this Agent with Wunderground. |
|
| 20 |
+ |
|
| 21 |
+ You must setup an [API key for Forecast](https://developer.forecast.io/) in order to use this Agent with ForecastIO. |
|
| 14 | 22 |
MD |
| 15 | 23 |
|
| 16 | 24 |
event_description <<-MD |
@@ -44,38 +52,120 @@ module Agents |
||
| 44 | 52 |
event_created_within?(2) && !recent_error_logs? |
| 45 | 53 |
end |
| 46 | 54 |
|
| 47 |
- def wunderground |
|
| 48 |
- Wunderground.new(options['api_key']) if key_setup? |
|
| 49 |
- end |
|
| 50 |
- |
|
| 51 | 55 |
def key_setup? |
| 52 | 56 |
options['api_key'] && options['api_key'] != "your-key" |
| 53 | 57 |
end |
| 54 | 58 |
|
| 55 | 59 |
def default_options |
| 56 | 60 |
{
|
| 57 |
- 'api_key' => "your-key", |
|
| 58 |
- 'location' => "94103" |
|
| 61 |
+ 'service' => 'wunderground', |
|
| 62 |
+ 'api_key' => 'your-key', |
|
| 63 |
+ 'location' => '94103', |
|
| 64 |
+ 'which_day' => '0' |
|
| 59 | 65 |
} |
| 60 | 66 |
end |
| 61 | 67 |
|
| 62 | 68 |
def validate_options |
| 63 |
- errors.add(:base, "location is required") unless options['location'].present? || options['zipcode'].present? |
|
| 69 |
+ errors.add(:base, "service is required") unless options['service'].present? |
|
| 70 |
+ errors.add(:base, "service must be set to 'forecastio' or 'wunderground'") unless ["forecastio", "wunderground"].include?(options['service']) |
|
| 71 |
+ errors.add(:base, "location is required") unless options['location'].present? |
|
| 64 | 72 |
errors.add(:base, "api_key is required") unless options['api_key'].present? |
| 73 |
+ errors.add(:base, "which_day selection is required") unless options['which_day'].present? |
|
| 74 |
+ end |
|
| 75 |
+ |
|
| 76 |
+ def wunderground |
|
| 77 |
+ data = Wunderground.new(options['api_key']).forecast_for(options['location'])['forecast']['simpleforecast']['forecastday'] if key_setup? |
|
| 78 |
+ return data |
|
| 79 |
+ end |
|
| 80 |
+ |
|
| 81 |
+ def forecastio |
|
| 82 |
+ ForecastIO.api_key = options['api_key'] if key_setup? |
|
| 83 |
+ data = ForecastIO.forecast(options['location'].split(',')[0],options['location'].split(',')[1])['daily']['data']
|
|
| 84 |
+ return data |
|
| 85 |
+ end |
|
| 86 |
+ |
|
| 87 |
+ def model(data,service,which_day) |
|
| 88 |
+ day = Hash.new |
|
| 89 |
+ if service == "wunderground" |
|
| 90 |
+ day = data[which_day.to_i] |
|
| 91 |
+ elsif service == "forecastio" |
|
| 92 |
+ data.each do |value| |
|
| 93 |
+ timestamp = Time.at(value.time) |
|
| 94 |
+ if (timestamp.to_date - Time.now.to_date).to_i == which_day.to_i |
|
| 95 |
+ day = {
|
|
| 96 |
+ 'date' => {
|
|
| 97 |
+ 'epoch' => value.time.to_s, |
|
| 98 |
+ 'pretty' => timestamp.strftime("%l:%M %p %Z on %B %d, %Y"),
|
|
| 99 |
+ 'day' => timestamp.day, |
|
| 100 |
+ 'month' => timestamp.month, |
|
| 101 |
+ 'year' => timestamp.year, |
|
| 102 |
+ 'yday' => timestamp.yday, |
|
| 103 |
+ 'hour' => timestamp.hour, |
|
| 104 |
+ 'min' => timestamp.strftime("%M"),
|
|
| 105 |
+ 'sec' => timestamp.sec, |
|
| 106 |
+ 'isdst' => timestamp.isdst ? 1 : 0 , |
|
| 107 |
+ 'monthname' => timestamp.strftime("%B"),
|
|
| 108 |
+ 'monthname_short' => timestamp.strftime("%b"),
|
|
| 109 |
+ 'weekday_short' => timestamp.strftime("%a"),
|
|
| 110 |
+ 'weekday' => timestamp.strftime("%A"),
|
|
| 111 |
+ 'ampm' => timestamp.strftime("%p"),
|
|
| 112 |
+ 'tz_short' => timestamp.zone |
|
| 113 |
+ }, |
|
| 114 |
+ 'period' => which_day.to_i, |
|
| 115 |
+ 'high' => {
|
|
| 116 |
+ 'fahrenheit' => value.temperatureMax.round().to_s, |
|
| 117 |
+ 'epoch' => value.temperatureMaxTime.to_s, |
|
| 118 |
+ 'fahrenheit_apparent' => value.apparentTemperatureMax.round().to_s, |
|
| 119 |
+ 'epoch_apparent' => value.apparentTemperatureMaxTime.to_s, |
|
| 120 |
+ 'celsius' => ((5*(Float(value.temperatureMax) - 32))/9).round().to_s |
|
| 121 |
+ }, |
|
| 122 |
+ 'low' => {
|
|
| 123 |
+ 'fahrenheit' => value.temperatureMin.round().to_s, |
|
| 124 |
+ 'epoch' => value.temperatureMinTime.to_s, |
|
| 125 |
+ 'fahrenheit_apparent' => value.apparentTemperatureMin.round().to_s, |
|
| 126 |
+ 'epoch_apparent' => value.apparentTemperatureMinTime.to_s, |
|
| 127 |
+ 'celsius' => ((5*(Float(value.temperatureMin) - 32))/9).round().to_s |
|
| 128 |
+ }, |
|
| 129 |
+ 'conditions' => value.summary, |
|
| 130 |
+ 'icon' => value.icon, |
|
| 131 |
+ 'avehumidity' => (value.humidity * 100).to_i, |
|
| 132 |
+ 'sunriseTime' => value.sunriseTime.to_s, |
|
| 133 |
+ 'sunsetTime' => value.sunsetTime.to_s, |
|
| 134 |
+ 'moonPhase' => value.moonPhase.to_s, |
|
| 135 |
+ 'precip' => {
|
|
| 136 |
+ 'intensity' => value.precipIntensity.to_s, |
|
| 137 |
+ 'intensity_max' => value.precipIntensityMax.to_s, |
|
| 138 |
+ 'intensity_max_epoch' => value.precipIntensityMaxTime.to_s, |
|
| 139 |
+ 'probability' => value.precipProbability.to_s, |
|
| 140 |
+ 'type' => value.precipType |
|
| 141 |
+ }, |
|
| 142 |
+ 'dewPoint' => value.dewPoint.to_s, |
|
| 143 |
+ 'avewind' => {
|
|
| 144 |
+ 'mph' => value.windSpeed.round().to_s, |
|
| 145 |
+ 'kph' => (Float(value.windSpeed) * 1.609344).round().to_s, |
|
| 146 |
+ 'degrees' => value.windBearing.to_s |
|
| 147 |
+ }, |
|
| 148 |
+ 'visibility' => value.visibility.to_s, |
|
| 149 |
+ 'cloudCover' => value.cloudCover.to_s, |
|
| 150 |
+ 'pressure' => value.pressure.to_s, |
|
| 151 |
+ 'ozone' => value.ozone.to_s |
|
| 152 |
+ } |
|
| 153 |
+ end |
|
| 154 |
+ end |
|
| 155 |
+ end |
|
| 156 |
+ return day.merge('location' => options['location'])
|
|
| 65 | 157 |
end |
| 66 | 158 |
|
| 67 | 159 |
def check |
| 68 | 160 |
if key_setup? |
| 69 |
- wunderground.forecast_for(options['location'] || options['zipcode'])["forecast"]["simpleforecast"]["forecastday"].each do |day| |
|
| 70 |
- if is_tomorrow?(day) |
|
| 71 |
- create_event :payload => day.merge('location' => options['location'] || options['zipcode'])
|
|
| 72 |
- end |
|
| 161 |
+ if options['service'] == 'forecastio' |
|
| 162 |
+ weather = model(forecastio,options['service'],options['which_day']) |
|
| 163 |
+ elsif options['service'] == 'wunderground' |
|
| 164 |
+ weather = model(wunderground,options['service'],options['which_day']) |
|
| 73 | 165 |
end |
| 166 |
+ create_event :payload => weather |
|
| 74 | 167 |
end |
| 75 | 168 |
end |
| 76 | 169 |
|
| 77 |
- def is_tomorrow?(day) |
|
| 78 |
- Time.zone.at(day["date"]["epoch"].to_i).to_date == Time.zone.now.tomorrow.to_date |
|
| 79 |
- end |
|
| 80 | 170 |
end |
| 81 | 171 |
end |