sporttracks, not fully tested
This commit is contained in:
@@ -71,7 +71,7 @@ class SyncIntegration(metaclass=ABCMeta):
|
||||
"scope": self.oauth_data['scope'],
|
||||
"state": state}
|
||||
|
||||
url = self.oauth_data['authorizaton_uri']+urllib.parse.urlencode(params)
|
||||
url = self.oauth_data['authorization_uri']+urllib.parse.urlencode(params)
|
||||
|
||||
return url
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from .integrations import SyncIntegration, NoTokenError
|
||||
from rowers.models import User, Rower, Workout, TombStone
|
||||
|
||||
from rowers.tasks import handle_sporttracks_sync
|
||||
from rowingdata import rowingdata
|
||||
|
||||
from rowers.tasks import handle_sporttracks_sync, handle_sporttracks_workout_from_data
|
||||
from rowers.rower_rules import is_workout_user
|
||||
import rowers.mytypes as mytypes
|
||||
from rowsandall_app.settings import (
|
||||
@@ -11,13 +13,38 @@ from rowsandall_app.settings import (
|
||||
|
||||
import re
|
||||
import numpy
|
||||
import pytz
|
||||
import json
|
||||
import requests
|
||||
import datetime
|
||||
import pandas as pd
|
||||
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
queuehigh = django_rq.get_queue('high')
|
||||
|
||||
from rowers.utils import myqueue, dologging
|
||||
from rowers.utils import myqueue, dologging, uniqify
|
||||
|
||||
def getidfromuri(uri): # pragma: no cover
|
||||
m = re.search('/(\w.*)\/(\d+)', uri)
|
||||
return m.group(2)
|
||||
|
||||
def getidfromresponse(response): # pragma: no cover
|
||||
t = response.json()
|
||||
uri = t['uris'][0]
|
||||
regex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities/(\d+)\.json$'
|
||||
m = re.compile(regex).match(uri).group(1)
|
||||
|
||||
id = int(m)
|
||||
|
||||
return int(id)
|
||||
|
||||
|
||||
def default(o): # pragma: no cover
|
||||
if isinstance(o, numpy.int64):
|
||||
return int(o)
|
||||
raise TypeError
|
||||
|
||||
class SportTracksIntegration(SyncIntegration):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -27,7 +54,7 @@ class SportTracksIntegration(SyncIntegration):
|
||||
'client_id': SPORTTRACKS_CLIENT_ID,
|
||||
'client_secret': SPORTTRACKS_CLIENT_SECRET,
|
||||
'redirect_uri': SPORTTRACKS_REDIRECT_URI,
|
||||
'autorization_uri': "https://api.sporttracks.mobi/oauth2/authorize",
|
||||
'authorization_uri': "https://api.sporttracks.mobi/oauth2/authorize",
|
||||
'content_type': 'application/json',
|
||||
'tokenname': 'sporttrackstoken',
|
||||
'refreshtokenname': 'sporttracksrefreshtoken',
|
||||
@@ -42,13 +69,178 @@ class SportTracksIntegration(SyncIntegration):
|
||||
return super(SportTracksIntegration, self).open(*args, **kwargs)
|
||||
|
||||
def createworkoutdata(self, w, *args, **kwargs):
|
||||
return None
|
||||
timezone = pytz.timezone(w.timezone)
|
||||
|
||||
filename = w.csvfilename
|
||||
try:
|
||||
row = rowingdata(csvfile=filename)
|
||||
except: # pragma: no cover
|
||||
return {}
|
||||
|
||||
try:
|
||||
averagehr = int(row.df[' HRCur (bpm)'].mean())
|
||||
maxhr = int(row.df[' HRCur (bpm)'].max())
|
||||
except KeyError: # pragma: no cover
|
||||
averagehr = 0
|
||||
maxhr = 0
|
||||
|
||||
try:
|
||||
duration = w.duration.hour*3600
|
||||
duration += w.duration.minute*60
|
||||
duration += w.duration.second
|
||||
duration += +1.0e-6*w.duration.microsecond
|
||||
except AttributeError: # pragma: no cover
|
||||
return {}
|
||||
|
||||
t = row.df.loc[:, 'TimeStamp (sec)'].values - \
|
||||
row.df.loc[:, 'TimeStamp (sec)'].iloc[0]
|
||||
try:
|
||||
t[0] = t[1]
|
||||
except IndexError: # pragma: no cover
|
||||
return {}
|
||||
|
||||
d = row.df.loc[:, 'cum_dist'].values
|
||||
d[0] = d[1]
|
||||
t = t.astype(int)
|
||||
d = d.astype(int)
|
||||
spm = row.df[' Cadence (stokes/min)'].astype(int).values
|
||||
spm[0] = spm[1]
|
||||
hr = row.df[' HRCur (bpm)'].astype(int).values
|
||||
|
||||
haslatlon = 1
|
||||
|
||||
try:
|
||||
lat = row.df[' latitude'].values
|
||||
lon = row.df[' longitude'].values
|
||||
if not lat.std() and not lon.std(): # pragma: no cover
|
||||
haslatlon = 0
|
||||
except KeyError:
|
||||
haslatlon = 0
|
||||
|
||||
haspower = 1
|
||||
try:
|
||||
power = row.df[' Power (watts)'].astype(int).values
|
||||
except KeyError: # pragma: no cover
|
||||
haspower = 0
|
||||
|
||||
locdata = []
|
||||
hrdata = []
|
||||
spmdata = []
|
||||
distancedata = []
|
||||
powerdata = []
|
||||
|
||||
t = t.tolist()
|
||||
hr = hr.tolist()
|
||||
d = d.tolist()
|
||||
spm = spm.tolist()
|
||||
if haslatlon:
|
||||
lat = lat.tolist()
|
||||
lon = lon.tolist()
|
||||
power = power.tolist()
|
||||
|
||||
for i in range(len(t)):
|
||||
hrdata.append(t[i])
|
||||
hrdata.append(hr[i])
|
||||
distancedata.append(t[i])
|
||||
distancedata.append(d[i])
|
||||
spmdata.append(t[i])
|
||||
spmdata.append(spm[i])
|
||||
if haslatlon:
|
||||
locdata.append(t[i])
|
||||
locdata.append([lat[i], lon[i]])
|
||||
if haspower:
|
||||
powerdata.append(t[i])
|
||||
powerdata.append(power[i])
|
||||
|
||||
try:
|
||||
w.notes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
|
||||
except TypeError:
|
||||
w.notes = 'from '+w.workoutsource+' via rowsandall.com'
|
||||
|
||||
st = w.startdatetime.astimezone(timezone)
|
||||
st = st.replace(microsecond=0)
|
||||
|
||||
data = {
|
||||
"type": "Rowing",
|
||||
"name": w.name,
|
||||
"start_time": st.isoformat(),
|
||||
"total_distance": int(w.distance),
|
||||
"duration": duration,
|
||||
"notes": w.notes,
|
||||
"avg_heartrate": averagehr,
|
||||
"max_heartrate": maxhr,
|
||||
"distance": distancedata,
|
||||
"cadence": spmdata,
|
||||
"heartrate": hrdata,
|
||||
}
|
||||
|
||||
if haslatlon:
|
||||
data = {
|
||||
"type": "Rowing",
|
||||
"name": w.name,
|
||||
"start_time": st.isoformat(),
|
||||
"total_distance": int(w.distance),
|
||||
"duration": duration,
|
||||
"notes": w.notes,
|
||||
"avg_heartrate": averagehr,
|
||||
"max_heartrate": maxhr,
|
||||
"location": locdata,
|
||||
"distance": distancedata,
|
||||
"cadence": spmdata,
|
||||
"heartrate": hrdata,
|
||||
}
|
||||
|
||||
|
||||
if haspower:
|
||||
data['power'] = powerdata
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def workout_export(self, workout, *args, **kwargs) -> str:
|
||||
pass
|
||||
thetoken = self.open()
|
||||
stid = "0"
|
||||
# ready to upload. Hurray
|
||||
|
||||
if not(is_workout_user(self.user, workout)):
|
||||
return "0"
|
||||
|
||||
authorizationstring = str('Bearer ' + thetoken)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
|
||||
data = self.createworkoutdata(workout)
|
||||
|
||||
if not data:
|
||||
return "0"
|
||||
|
||||
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
|
||||
_ = myqueue(
|
||||
queue,
|
||||
handle_sporttracks_sync,
|
||||
workout.id,
|
||||
url,
|
||||
headers,
|
||||
json.dumps(data, default=default))
|
||||
|
||||
return 1
|
||||
|
||||
def get_workouts(self, *args, **kwargs) -> int:
|
||||
pass
|
||||
r = self.rower
|
||||
workouts_json = self.get_workout_list_json(*args, **kwargs)
|
||||
|
||||
stids = [int(getidfromuri(item['uri']))
|
||||
for item in workouts_json['items']]
|
||||
|
||||
knownstids = uniqify([
|
||||
w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
|
||||
])
|
||||
newids = [stid for stid in stids if stid not in knownstids]
|
||||
for sporttracksid in newids:
|
||||
id = self.get_workout(sporttracksid)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
@@ -57,33 +249,19 @@ class SportTracksIntegration(SyncIntegration):
|
||||
|
||||
r = self.rower
|
||||
|
||||
authorizationstring = str('Bearer ' + r.sporttrackstoken)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities/" + \
|
||||
str(sporttracksid)
|
||||
s = requests.get(url, headers=headers)
|
||||
|
||||
data = s.json()
|
||||
|
||||
strokedata = pd.DataFrame.from_dict({
|
||||
key: pd.Series(value, dtype='object') for key, value in data.items()
|
||||
})
|
||||
|
||||
id = myqueue(
|
||||
job = myqueue(
|
||||
queue,
|
||||
handle_sporttracks_workout_from_data,
|
||||
self.user,
|
||||
sporttracksid, data,
|
||||
strokedata,
|
||||
id,
|
||||
'sporttracks',
|
||||
'sporttracks'
|
||||
)
|
||||
return id
|
||||
|
||||
return job.id
|
||||
|
||||
|
||||
def get_workout_list(self, *args, **kwargs) -> list:
|
||||
def get_workout_list_json(self, *args, **kwargs) -> dict:
|
||||
_ = self.open()
|
||||
r = self.rower
|
||||
|
||||
@@ -98,13 +276,18 @@ class SportTracksIntegration(SyncIntegration):
|
||||
s = "Token doesn't exist. Need to authorize"
|
||||
raise NoTokenError(s)
|
||||
|
||||
return res.json()
|
||||
|
||||
def get_workout_list(self, *args, **kwargs) -> list:
|
||||
r = self.rower
|
||||
workouts_json = self.get_workout_list_json(*args, **kwargs)
|
||||
|
||||
workouts = []
|
||||
|
||||
knownstids = uniqify([
|
||||
w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
|
||||
])
|
||||
for item in res.json()['items']:
|
||||
for item in workouts_json['items']:
|
||||
d = int(float(item['total_distance']))
|
||||
i = int(getidfromuri(item['uri']))
|
||||
if i in knownstids: # pragma: no cover
|
||||
@@ -127,7 +310,7 @@ class SportTracksIntegration(SyncIntegration):
|
||||
return super(SportTracksIntegration, self).make_authorization_url(*args, **kwargs)
|
||||
|
||||
def get_token(self, code, *args, **kwargs) -> (str, int, str):
|
||||
return ""
|
||||
return super(SportTracksIntegration, self).get_token(code, *args, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user