Private
Public Access
1
0

Merge branch 'release/metar'

This commit is contained in:
Sander Roosendaal
2017-02-20 21:27:29 +01:00
5 changed files with 6845 additions and 5 deletions
File diff suppressed because it is too large Load Diff
+4
View File
@@ -52,6 +52,10 @@
</div> </div>
<div class="grid_2 omega"> <div class="grid_2 omega">
<p>Closest Airport Weather: {{ airport }}
({{ airportdistance | floatformat:-1 }} km)
<a class="button green small" href="/rowers/workout/{{ workout.id }}/metar/{{ airport }}">Airport Data</a></p>
<p>
<a class="button green small" href="/rowers/workout/{{ workout.id }}/darkskywind">Dark Sky Data</a> <a class="button green small" href="/rowers/workout/{{ workout.id }}/darkskywind">Dark Sky Data</a>
<p> <p>
Download wind speed and bearing from <a href="http://forecast.io/">The Dark Sky</a> Download wind speed and bearing from <a href="http://forecast.io/">The Dark Sky</a>
+1
View File
@@ -178,6 +178,7 @@ urlpatterns = [
url(r'^workout/(?P<id>\d+)/wind/c/(?P<message>\w+.*)$',views.workout_wind_view), url(r'^workout/(?P<id>\d+)/wind/c/(?P<message>\w+.*)$',views.workout_wind_view),
url(r'^workout/(?P<id>\d+)/wind/s/(?P<successmessage>\w+.*)$',views.workout_wind_view), url(r'^workout/(?P<id>\d+)/wind/s/(?P<successmessage>\w+.*)$',views.workout_wind_view),
url(r'^workout/(?P<id>\d+)/darkskywind$',views.workout_downloadwind_view), url(r'^workout/(?P<id>\d+)/darkskywind$',views.workout_downloadwind_view),
url(r'^workout/(?P<id>\d+)/metar/(?P<airportcode>\w+)$',views.workout_downloadmetar_view),
url(r'^workout/(\d+)/stream$',views.workout_stream_view), url(r'^workout/(\d+)/stream$',views.workout_stream_view),
url(r'^workout/(?P<id>\d+)/stream/c/(?P<message>\w+.*)$',views.workout_stream_view), url(r'^workout/(?P<id>\d+)/stream/c/(?P<message>\w+.*)$',views.workout_stream_view),
url(r'^workout/(\d+)/crewnerdsummary$',views.workout_crewnerd_summary_view), url(r'^workout/(\d+)/crewnerdsummary$',views.workout_crewnerd_summary_view),
+80 -2
View File
@@ -82,7 +82,7 @@ import mpld3
from mpld3 import plugins from mpld3 import plugins
import stravalib import stravalib
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
from weather import get_wind_data from weather import get_wind_data,get_airport_code,get_metar_data
from oauth2_provider.models import Application,Grant,AccessToken from oauth2_provider.models import Application,Grant,AccessToken
@@ -2435,7 +2435,9 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
'id':row.id}) 'id':row.id})
# Get weather for given location and date/time # Get weather for given location and date/time
@user_passes_test(ispromember,login_url="/",redirect_field_name=None) @user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_downloadwind_view(request,id=0,
airportcode=None,
message="",successmessage=""): message="",successmessage=""):
try: try:
row = Workout.objects.get(id=id) row = Workout.objects.get(id=id)
@@ -2494,6 +2496,71 @@ def workout_downloadwind_view(request,id=0,message="",successmessage=""):
return response return response
# Get weather for given location and date/time
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_downloadmetar_view(request,id=0,
airportcode=None,
message="",successmessage=""):
try:
row = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
f1 = row.csvfilename
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
url = reverse(workouts_view,args=[str(message)])
return HttpResponseRedirect(url)
# create bearing
rowdata = rdata(f1)
if rowdata == 0:
return HttpResponse("Error: CSV Data File Not Found")
try:
bearing = rowdata.df.ix[:,'bearing'].values
except KeyError:
rowdata.add_bearing()
rowdata.write_csv(f1,gzip=True)
# get wind
try:
avglat = rowdata.df[' latitude'].mean()
avglon = rowdata.df[' longitude'].mean()
airportcode = get_airport_code(avglat,avglon)[0]
avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.ix[0,'TimeStamp (sec)'])
startdatetime = dateutil.parser.parse("{}, {}".format(row.date,
row.starttime))
starttimeunix = int(mktime(startdatetime.timetuple()))
avgtime = starttimeunix+avgtime
winddata = get_metar_data(airportcode,avgtime)
windspeed = winddata[0]
windbearing = winddata[1]
message = winddata[2]
row.notes += "\n"+message
row.save()
rowdata.add_wind(windspeed,windbearing)
rowdata.write_csv(f1,gzip=True)
kwargs = {'successmessage':str(message),
'id':str(id)}
url = reverse(workout_wind_view,kwargs=kwargs)
response = HttpResponseRedirect(url)
except KeyError:
message = "No latitude/longitude data"
kwargs = {'message':str(message),
'id':str(id)}
url = reverse(workout_wind_view,kwargs=kwargs)
response = HttpResponseRedirect(url)
return response
# Show form to update wind data # Show form to update wind data
@user_passes_test(ispromember,login_url="/",redirect_field_name=None) @user_passes_test(ispromember,login_url="/",redirect_field_name=None)
@@ -2536,6 +2603,15 @@ def workout_wind_view(request,id=0,message="",successmessage=""):
rowdata.add_bearing() rowdata.add_bearing()
rowdata.write_csv(f1,gzip=True) rowdata.write_csv(f1,gzip=True)
if hascoordinates:
avglat = rowdata.df[' latitude'].mean()
avglon = rowdata.df[' longitude'].mean()
airportcode,newlat,newlon,airportdistance = get_airport_code(avglat,avglon)
airportcode = airportcode.upper()
airportdistance = airportdistance[0]
else:
airportcode = 'UNKNOWN'
airportdistance = 0 airportdistance = 0
@@ -2593,6 +2669,8 @@ def workout_wind_view(request,id=0,message="",successmessage=""):
'message': message, 'message': message,
'successmessage': successmessage, 'successmessage': successmessage,
'interactiveplot':script, 'interactiveplot':script,
'form':form,
'airport':airportcode,
'airportdistance':airportdistance, 'airportdistance':airportdistance,
'the_div':div, 'the_div':div,
'gmap':gmscript, 'gmap':gmscript,
+65 -1
View File
@@ -1,13 +1,26 @@
import requests import requests
import json import json
from lxml import objectify,etree
import xml.etree.ElementTree as ET
import time import time
from datetime import datetime from datetime import datetime
from rowingdata import rowingdata from rowingdata import rowingdata,geo_distance
import pandas as pd import pandas as pd
from rowers.models import Rower, Workout from rowers.models import Rower, Workout
from rowsandall_app.settings import FORECAST_IO_KEY from rowsandall_app.settings import FORECAST_IO_KEY
# Find closest airport
def get_airport_code(lat,lon):
metardata = pd.read_csv('rowers/data/metarlatlon.csv')
deltasq = (lat-metardata.lat)**2+(lon-metardata.lon)**2
a = metardata[deltasq == deltasq.min()]
airport_code = a.iloc[0]['icao']
newlat = a.iloc[0]['lat']
newlon = a.iloc[0]['lon']
distance = geo_distance(lat,lon,newlat,newlon)
return airport_code,newlat,newlon,distance
# Get weather data from the DarkSky API # Get weather data from the DarkSky API
def get_weather_data(long,lat,unixtime): def get_weather_data(long,lat,unixtime):
url = "https://api.darksky.net/forecast/"+FORECAST_IO_KEY+"/" url = "https://api.darksky.net/forecast/"+FORECAST_IO_KEY+"/"
@@ -20,6 +33,57 @@ def get_weather_data(long,lat,unixtime):
else: else:
return 0 return 0
# Get Metar data
def get_metar_data(airportcode,unixtime):
timestamp = datetime.utcfromtimestamp(unixtime).isoformat()+'Z'
url = "https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&startTime="
url += str(unixtime-3600)
url += "&endTime="
url += str(unixtime+3600)
url += "&stationString="+airportcode
s = requests.get(url)
if s.ok:
doc = etree.fromstring(s.content)
try:
id = doc.xpath('data/METAR/station_id')[0].text
temp_c = doc.xpath('data/METAR/temp_c')[0].text
wind_dir = doc.xpath('data/METAR/wind_dir_degrees')[0].text
wind_speed = doc.xpath('data/METAR/wind_speed_kt')[0].text
timestamp = doc.xpath('data/METAR/observation_time')[0].text
rawtext = doc.xpath('data/METAR/raw_text')[0].text
except IndexError:
message = 'Failed to download METAR data'
return [0,0,message,'',timestamp]
print temp_c,wind_dir,wind_speed
windbearing = float(wind_dir)
wind_knots = float(wind_speed)
wind_ms = 0.514444*wind_knots
wind_ms = int(10*wind_ms)/10.
temperaturec = float(temp_c)
temp_f = 32.+(9./5.)*temperaturec
temp_f = str(int(10*temp_f)/10.)
message = 'Summary for your location at '+timestamp+': '
message += 'Temperature '+temp_c+'C/'+temp_f+'F'
message += '. Wind: '+str(wind_ms)+' m/s ('+str(wind_knots)+' kt)'
message +='. Wind Bearing: '+str(windbearing)+' degrees'
# message +='\n'+rawtext
return [wind_ms,windbearing,message,rawtext,timestamp]
message = 'Failed to download METAR data'
return [0,0,message,'',timestamp]
# Get wind data (and translate from knots to m/s) # Get wind data (and translate from knots to m/s)
def get_wind_data(lat,long,unixtime): def get_wind_data(lat,long,unixtime):
data = get_weather_data(lat,long,unixtime) data = get_weather_data(lat,long,unixtime)