-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget_wx_data.py
308 lines (308 loc) · 10.1 KB
/
get_wx_data.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# Python 3
# Get the data needed from the APIs
#
import requests, json, datetime, socket,time
from sys import platform as _platform
#
timeout = 2800
socket.setdefaulttimeout(timeout)
#
# Define the cities considered
#
cities = ['Sacramento,CA','San Francisco,CA','Portland,OR','San Jose,CA']
#
# Define the latitude and longitude of the cities considered
#
lats = ['38.58','37.77', '45.52','37.39']
longits = ['-121.49','-122.38','-122.67','-122.08']
#
# Define additional data needed for APIs to work
#
ymd = datetime.datetime.now()
dat = ymd.strftime("%Y")+ymd.strftime("%m")+ymd.strftime("%d")
#
# Define the 'base' of the four api requests used, will later add on to these strings
#
url_wx = 'https://api.weather.gov/points/'
url_aqi = 'http://www.airnowapi.org/aq/forecast/latLong/?format=application/json&'
url_light = 'http://api.openweathermap.org/data/2.5/weather?'
url_tide = 'https://tidesandcurrents.noaa.gov/api/datagetter?begin_date='+dat+'&range=48&station=9414290&product=predictions&datum=NAVD&time_zone=lst&interval=hilo&units=english&application=bikewxx&format=json'
#
# Functions to call individual APIs
#
#
# Function for basic weather data from the NWS
#
def get_wx(baseurl,lat,longit):
"This function calls the basic weather data from NWS"
url = baseurl + lat+','+longit+'/forecast/hourly'
r = requests.get(url)
status = r.status_code
print(status)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,1)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,2)
if status != 200:
print(status,3)
print('No data after 3 tries')
if status == 200:
json_data = r.json()
#
# The times given in the api are local times, and the utc offset is shown for information.
# 1994-11-05T08:15:30-05:00 corresponds to November 5, 1994, 8:15:30 am, US Eastern Standard Time.
# 1994-11-05T13:15:30Z corresponds to the same instant.
#
# Get the time of "period 1" (which is 0 on the list), then use that info to find which period to grab.
# For ride in you want 07:00 local, and for ride home you want 17:00 local.
# The chron job runs at 3:45 am and at 3:45 pm
#
startTime = json_data['properties']['periods'][0]['startTime']
print(startTime)
startTime = int(startTime[11:13])
if startTime < 12:
needPeriod = 8-startTime
else:
needPeriod = 15-startTime
print(startTime)
print(needPeriod)
#
ridein = json_data['properties']['periods'][needPeriod]['shortForecast'] + ', '\
+json.dumps(json_data['properties']['periods'][needPeriod]['temperature']) \
+json_data['properties']['periods'][needPeriod]['temperatureUnit'] \
+', Wind '\
+json_data['properties']['periods'][needPeriod]['windSpeed'] + ' from '\
+json_data['properties']['periods'][needPeriod]['windDirection']
#
needPeriod = needPeriod + 9
# +(u'\N{DEGREE SIGN}') \
#
ridehome = json_data['properties']['periods'][needPeriod]['shortForecast'] + ', '\
+json.dumps(json_data['properties']['periods'][needPeriod]['temperature']) \
+json_data['properties']['periods'][needPeriod]['temperatureUnit'] \
+', Wind '\
+json_data['properties']['periods'][needPeriod]['windSpeed'] + ' from '\
+json_data['properties']['periods'][needPeriod]['windDirection']
# +(u'\N{DEGREE SIGN}') \
else:
print(status)
ridein = 'No data'
ridehome = 'No data'
print(ridein)
print(ridehome)
f.write(ridein+'\n')
f.write(ridehome+'\n')
return
#
# Function for AQI from AirNow
#
def get_aqi(baseurl,lat,longit,ymd):
"This function calls the AQI from AirNow"
# Requires API Key so find it
if _platform == "linux" or _platform == "linux2":
e = open('/home/dougdroplet2/projects/BikeWxX/bikewxxkeys/AQIkey','r')
elif _platform == "darwin":
e = open('../bikewxxkeys/AQIkey','r')
elif _platform == "win32":
print('create dir and continue')
#
url = baseurl + 'latitude='+lat+'&longitude='+longit+'&date='+ymd.strftime("%Y")+'-'+ymd.strftime("%m")+'-'+ymd.strftime("%d")+'&distance=25&API_KEY='+e.read().rstrip()
print(url)
e.close
r = requests.get(url)
print(r)
status = r.status_code
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,1)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,2)
if status != 200:
print('No data after 3 tries')
print(status,3)
if status == 200:
print(status)
json_data = r.json()
#print(json_data)
# Always get the 0 data which is the AQI for this day, as there is only 1 forecast per day provided by the API
rideinAqi = "AQI: "+(json_data[0]['Category']['Name'])
ridehomeAqi = rideinAqi
# with the index number ridehomeAqi = "Air Quality Index "+json.dumps(json_data[0]['AQI'])+"-"+(json_data[0]['Category']['Name'])
# with the index number rideinAqi = "Air Quality Index "+json.dumps(json_data[0]['AQI'])+"-"+(json_data[0]['Category']['Name'])
else:
rideinAqi = 'No data'
ridehomeAqi = 'No data'
print(rideinAqi)
print(ridehomeAqi)
f.write(rideinAqi+'\n')
f.write(ridehomeAqi+'\n')
print()
return
#
# Function for twilight data from OpenWeather
# Define bike twilight as sunset and 24 minutes before sunrise
# 24 minutes is 1440 seconds
#
def get_light(baseurl,lat,longit):
"This function calls the twilight data from OpenWeather"
# Requires API Key so find it
if _platform == "linux" or _platform == "linux2":
g = open('/home/dougdroplet2/projects/BikeWxX/bikewxxkeys/OWMkey','r')
elif _platform == "darwin":
g = open('../bikewxxkeys/OWMkey','r')
elif _platform == "win32":
print('create dir and continue')
#url = baseurl + city
url = baseurl + 'lat='+lat+'&lon='+longit+'&APPID='+g.read().rstrip()
g.close
r = requests.get(url)
print(r.url)
status = r.status_code
print(status)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,1)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,2)
if status != 200:
print('No data after 3 tries')
print(status,3)
if status == 200:
print(status)
json_data = r.json()
print(json_data)
sunRise = json_data['sys']['sunrise']
sunRise = time.strftime("%I:%M %p", time.localtime(sunRise-1440))
print(sunRise)
sunSet = json_data['sys']['sunset']
sunSet = time.strftime("%I:%M %p", time.localtime(sunSet))
print(sunSet)
sunRise = "Bikelights: Before "+sunRise
sunSet = "Bikelights: After "+sunSet
else:
sunRise= "No data"
sunSet= "No data"
print(sunRise)
print(sunSet)
print()
# Note that sunrise sunset is now really my definition of Bike Twilight
f.write(sunRise+'\n')
f.write(sunSet+'\n')
return
#
# Function for tide data from NOAA
#
def get_tide(baseurl, city):
"This function calls the tide data from NOAA using the CO-OPS API"
# Warning, kluge ahead!
# This script assembles lines of text to be tweeted. Each line (now 4 lines) comes from each API call.
# The tide api call and it's corresponding line of text only apply to San Francisco
# So the kluge is to only run this tide api call on 'Frisco. The fourth line will always be a blank for other cities,
# but will be either the tide warning or a blank for 'Frisco.
if city == 'San Francisco,CA':
url = baseurl
r = requests.get(url)
status = r.status_code
print(url)
print(status)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,1)
if status != 200:
time.sleep(300)
r = requests.get(url)
status = r.status_code
print(status,2)
if status != 200:
print(status,3)
print('No data after 3 tries')
if status == 200:
json_data = r.json()
print (json_data['predictions'])
tidev = max(float(json_data['predictions'][0]['v']),float(json_data['predictions'][1]['v']),float(json_data['predictions'][2]['v']),float(json_data['predictions'][3]['v']))
if tidev > 6.40:
tidein = "Today's high tide of " + str(tidev)[:4] + ' could cause path flooding in low areas, see https://tidesandcurrents.noaa.gov/map/index.shtml?id=9414290'
tidehome = tidein
else:
# Assigning 'no data' here but really if it gets here then there is data, it is just data I don't want tweeted
tidein = 'No data'
tidehome = tidein
else:
print(status)
tidein = 'No data'
tidehome = tidein
# f.write(tidein+'\n')
# f.write(tidehome+'\n')
else:
tidein = 'No data'
tidehome = tidein
#
f.write(tidein+'\n')
f.write(tidehome+'\n')
return
#
# End of functions
#
# Open a txt file and write data to it sequentially, line by line, to be assembled into a tweet in another script
#
if _platform == "linux" or _platform == "linux2":
f = open('/home/dougdroplet2/projects/BikeWxX/BikeWxX/data/forecast.txt','w')
f.write(ymd.strftime("%c")+'\n')
elif _platform == "darwin":
f = open('data/forecast.txt','w')
f.write(ymd.strftime("%c")+'\n')
elif _platform == "win32":
print('if on win32, create a dir and continue')
#
# Call the functions which access the four APIs
#
# Basic weather from NWS
#
for city, lat, longit in zip(cities, lats, longits):
print()
print(city,lat,longit)
get_wx(url_wx, lat, longit)
print()
#
# AQI from AirNow
#
for city, lat, longit in zip(cities, lats, longits):
print()
print(city,lat,longit,ymd)
get_aqi(url_aqi, lat, longit, ymd)
print()
#
# Twilight from OpenWeather
#
for city, lat, longit in zip(cities, lats, longits):
print()
print(city,lat,longit)
get_light(url_light, lat, longit)
print()
#
# Tide from NOAA - this is just for 'frisco
#
for city in cities:
print()
get_tide(url_tide,city)
print()
#
f.close()