Merged ForecastIO into existing WeatherAgent

Joseph Scavone лет %!s(int64=11): %!d(string=назад)
Родитель
Сommit
67d3a638c0
2 измененных файлов с 107 добавлено и 124 удалено
  1. 0 107
      app/models/agents/forecast_agent.rb
  2. 107 17
      app/models/agents/weather_agent.rb

+ 0 - 107
app/models/agents/forecast_agent.rb

@@ -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

+ 107 - 17
app/models/agents/weather_agent.rb

@@ -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