Private
Public Access
1
0

works except for target cadence

This commit is contained in:
Sander Roosendaal
2021-05-16 07:30:56 +02:00
parent acc4c6f305
commit 54190ed383
3 changed files with 225 additions and 66 deletions

View File

@@ -28,23 +28,24 @@ payload = {
'workoutSourceId': 'Rowsandall.com', 'workoutSourceId': 'Rowsandall.com',
'steps': [ 'steps': [
{ {
'type': 'WorkoutStep', 'stepOrder': 0, 'type': 'WorkoutStep',
'stepOrder': 0,
#'repeatType': 'Step', #'repeatType': 'Step',
'repeatValue': 1, #'repeatValue': 1,
'intensity': 'ACTIVE', 'intensity': 'ACTIVE',
'description': '0', 'description': 'At 220W',
'durationType': 'TIME', 'durationType': 'TIME',
'durationValue': 1800, 'durationValue': 1800,
'durationValueType': 'METER', 'durationValueType': None,
'targetType': 'POWER', 'targetType': 'POWER',
'targetValue': 1226, 'targetValue': 226,
'targetValueLow': None, 'targetValueLow': None,
'targetValueHigh': None, 'targetValueHigh': None,
} }
] ]
} }
payload = { payload2 = {
"workoutName": "Test", "workoutName": "Test",
"description": "Test", "description": "Test",
"sport": "CYCLING", "sport": "CYCLING",
@@ -55,16 +56,93 @@ payload = {
"intensity": "INTERVAL", "intensity": "INTERVAL",
"description": "Free Ride", "description": "Free Ride",
"durationType": "TIME", "durationType": "TIME",
"durationValue": 300, "durationValue": 1800,
"durationValueType": None, "durationValueType": None,
"targetType": "POWER", "targetType": "POWER",
"targetValue": None, "targetValue": 226,
"targetValueLow": 0, "targetValueLow": None,
"targetValueHigh": 0.7, "targetValueHigh": None,
"targetValueType": "PERCENT", "targetValueType": None,
"exerciseCategory": None "exerciseCategory": None
}]} }]}
payload = {'workoutName': '4x1000m',
'sport': 'GENERIC',
'description': 'Uploaded from Rowsandall.com',
'estimatedDurationInSecs': 2700,
'estimatedDistanceInMeters': 8768,
'workoutProvider': 'Rowsandall.com',
'workoutSourceId': 'Rowsandall.com',
'steps': [{'type': 'WorkoutStep',
'stepOrder': 0,
'repeatType': None,
'repeatValue': 1,
'intensity': 'INTERVAL',
'description': '0',
'durationType': 'DISTANCE',
'durationValue': 2000,
'durationValueType': 'METER',
'targetType': None,
'targetValue': None,
'targetValueLow': None,
'targetValueHigh': None},
{'type': 'WorkoutRepeatStep',
'stepOrder': 1,
'repeatType': 'REPEAT_UNTIL_STEPS_CMPLT',
'repeatValue': 4,
'intensity': 'INTERVAL',
'description': '3',
'durationType': 'REPS',
'durationValue': None,
'durationValueType': None,
'targetType': None,
'targetValue': None,
'targetValueLow': None,
'targetValueHigh': None,
'steps': [{'type': 'WorkoutStep',
'stepOrder': 2,
'repeatType': None,
'repeatValue': 1,
'intensity': 'INTERVAL',
'description': '1',
'durationType': 'DISTANCE',
'durationValue': 1000,
'durationValueType': 'METER',
#'targetType': 'CADENCE',
#'targetValue': 25,
#'targetValueLow': None,
#'targetValueHigh': None
},
{'type': 'WorkoutStep',
'stepOrder': 3,
'repeatType': None,
'repeatValue': 1,
'intensity': 'REST',
'description': '2',
'durationType': 'TIME',
'durationValue': 60,
'durationValueType': None,
'targetType': None,
'targetValue': None,
'targetValueLow': None,
'targetValueHigh': None}]},
{'type': 'WorkoutStep',
'stepOrder': 4,
'repeatType': None,
'repeatValue': 1,
'intensity': 'INTERVAL',
'description': '4',
'durationType': 'DISTANCE',
'durationValue': 2000,
'durationValueType': 'METER',
'targetType': None,
'targetValue': None,
'targetValueLow': None,
'targetValueHigh': None}]}
print(json.dumps(payload)) print(json.dumps(payload))
@@ -95,4 +173,17 @@ response = requests.post(url,auth=authheaders,json=payload)
# build base_string # build base_string
print(response.status_code) print(response.status_code)
print(response.text)
print(response.json())
garmin_workout_id = response.json()['workoutId']
url = 'http://apis.garmin.com/training-api/schedule'
payload = {
'workoutId': garmin_workout_id,
'date': '2021-05-16'
}
response = requests.post(url,auth=authheaders,json=payload)
print(response.status_code)
print(response.json())

View File

@@ -27,13 +27,6 @@ from rowsandall_app.settings import (
from pytz import timezone as tz, utc from pytz import timezone as tz, utc
#try:
# import http.client as http_client
#except ImportError:
# Python 2
# import httplib as http_client
#http_client.HTTPConnection.debuglevel = 1
# You must initialize logging, otherwise you'll not see debug output. # You must initialize logging, otherwise you'll not see debug output.
#logging.basicConfig() #logging.basicConfig()
#logging.getLogger().setLevel(logging.DEBUG) #logging.getLogger().setLevel(logging.DEBUG)
@@ -82,6 +75,36 @@ columns = {
'bikeCadenceInRPM':' Cadence (stokes/min)', 'bikeCadenceInRPM':' Cadence (stokes/min)',
} }
targettypes = {
"Speed": "SPEED",
"HeartRate": "HEART_RATE",
"Open": "OPEN",
"Cadence": "CADENCE",
"Power": "POWER",
"Grade": "GRADE",
"Resistance": "RESISTANCE",
"Power3s": "POWER_3S",
"Power10s": "POWER_10S",
"Power30s": "POWER_30S",
"PowerLap": "POWER_LAP",
"SwimStroke": "SWIM_STROKE",
"SpeedLap": "SPEED_LAP",
"HeartRateLap": "HEART_RATE_LAP"
}
repeattypes = {
"RepeatUntilStepsCmplt": "REPEAT_UNTIL_STEPS_CMPLT",
"RepeatUntilTime": "REPEAT_UNTIL_TIME",
"RepeatUntilDistance": "REPEAT_UNTIL_TIME",
"RepeatUntilCalories": "REPEAT_UNTIL_CALORIES" ,
"RepeatUntilHrLessThan": "REPEAT_UNTIL_HR_LESS_THAN" ,
"RepeatUntilHrGreaterThan": "REPEAT_UNTIL_HR_GREATER_THAN",
"RepeatUntilPowerLessThan": "REPEAT_UNTIL_POWER_LESS_THAN",
"RepeatUntilPowerGreaterThan": "REPEAT_UNTIL_POWER_GREATER_THAN",
"RepeatUntilPowerLapLessThan": "REPEAT_UNTIL_POWER_LAP_LESS_THAN",
"RepeatUntilPowerLapGreaterThan": "REPEAT_UNTIL_POWER_LAP_GREATER_THAN",
}
def garmin_authorize(): # pragma: no cover def garmin_authorize(): # pragma: no cover
redirect_uri = oauth_data['redirect_uri'] redirect_uri = oauth_data['redirect_uri']
client_secret = oauth_data['client_secret'] client_secret = oauth_data['client_secret']
@@ -179,9 +202,11 @@ from rowers import utils
def step_to_garmin(step,order=0): def step_to_garmin(step,order=0):
durationtype = step['dict']['durationType'] durationtype = step['dict']['durationType']
durationvalue = step['dict']['durationValue'] durationvalue = step['dict']['durationValue']
durationvaluetype = '' durationvaluetype = None
try: try:
intensity = step['dict']['intensity'] intensity = step['dict']['intensity'].upper()
if intensity.lower() == 'active':
intensity = 'INTERVAL'
except KeyError: except KeyError:
intensity = None intensity = None
#durationvaluetype = '' #durationvaluetype = ''
@@ -197,56 +222,87 @@ def step_to_garmin(step,order=0):
if durationvalue <= 100: if durationvalue <= 100:
durationvaluetype = 'PERCENT' durationvaluetype = 'PERCENT'
else: else:
durationvaluetype = '' durationvaluetype = None
durationvalue -= 100 durationvalue -= 100
elif durationtype == 'HrGreaterThan': # pragma: no cover elif durationtype == 'HrGreaterThan': # pragma: no cover
durationtype = 'HR_GREATER_THAN' durationtype = 'HR_GREATER_THAN'
if durationvalue <= 100: if durationvalue <= 100:
durationvaluetype = 'PERCENT' durationvaluetype = 'PERCENT'
else: else:
durationvaluetype = '' durationvaluetype = None
durationvalue -= 100 durationvalue -= 100
elif durationtype == 'PowerLessThan': # pragma: no cover elif durationtype == 'PowerLessThan': # pragma: no cover
durationtype = 'POWER_LESS_THAN' durationtype = 'POWER_LESS_THAN'
if durationvalue <= 1000: if durationvalue <= 1000:
durationvaluetype = 'PERCENT' durationvaluetype = 'PERCENT'
else: else:
durationvaluetype = '' durationvaluetype = None
durationvalue -= 1000 durationvalue -= 1000
elif durationtype == 'PowerGreaterThan': # pragma: no cover elif durationtype == 'PowerGreaterThan': # pragma: no cover
durationtype = 'POWER_GREATER_THAN' durationtype = 'POWER_GREATER_THAN'
if durationvalue <= 1000: if durationvalue <= 1000:
durationvaluetype = 'PERCENT' durationvaluetype = 'PERCENT'
else: else:
durationvaluetype = '' durationvaluetype = None
durationvalue -= 1000 durationvalue -= 1000
elif durationtype == 'Reps': # pragma: no cover elif durationtype == 'Reps': # pragma: no cover
durationtype = 'REPS' durationtype = 'REPS'
try: try:
targetType = step['dict']['targetType'] targetType = step['dict']['targetType']
targetType = targettypes[targetType]
except KeyError: except KeyError:
targetType = None targetType = None
try: try:
targetValue = step['dict']['targetValue'] targetValue = step['dict']['targetValue']
if targetValue == 0:
targetValue = None
except KeyError: except KeyError:
targetValue = None targetValue = None
try: try:
targetValueLow = step['dict']['targetValueLow'] targetValueLow = step['dict']['targetValueLow']
if targetValueLow == 0:
targetValueLow = None
except KeyError: except KeyError:
targetValueLow = None targetValueLow = None
try: try:
targetValueHigh = step['dict']['targetValueHigh'], targetValueHigh = step['dict']['targetValueHigh']
if targetValueHigh == 0:
targetValueHigh = None
except KeyError: except KeyError:
targetValueHigh = None targetValueHigh = None
if targetType.lower() == "power":
targetType = 'POWER'
if targetValue is not None and targetValue > 1000:
targetValue -= 1000
if targetValueHigh is not None and targetValueHigh > 1000:
targetValueHigh -= 1000
if targetValueLow is not None and targetValueLow > 1000:
targetValueLow -= 1000
if targetValue is None and targetValueLow is None and targetValueHigh is None:
targetType = None
steptype = 'WorkoutRepeatStep'
if step['type'].lower() == 'step':
steptype = 'WorkoutStep'
repeattype = None
if steptype == 'WorkoutRepeatStep':
repeattype = repeattypes[step['dict']['durationType']]
durationtype = 'REPS'
durationvalue = None
durationvaluetype = None
targetType = None
targetValue = None
out = { out = {
'type': step['type'], 'type': steptype,
'stepOrder':order, 'stepOrder':order,
'repeatType':step['type'], 'repeatType':repeattype,
'repeatValue':step['repeatValue'], 'repeatValue':step['repeatValue'],
'intensity':intensity, 'intensity':intensity,
'description':step['dict']['wkt_step_name'], 'description':step['dict']['wkt_step_name'],
@@ -303,30 +359,10 @@ def ps_to_garmin(ps,r):
lijst.append(gstep) lijst.append(gstep)
payload['steps'] = lijst payload['steps'] = lijst
url = 'https://apis.garmin.com/training-api/workout/'
garmin = OAuth1Session(oauth_data['client_id'], return payload
client_secret=oauth_data['client_secret'],
resource_owner_key=r.garmintoken,
resource_owner_secret=r.garminrefreshtoken,
signature_method='HMAC-SHA1',
encoding='base64'
)
response = garmin.post(url,data=payload)
#POST /training-api/workout?undefined HTTP/1.1
#Authorization: OAuth oauth_nonce="3347376452", oauth_signature="jM8%2BCsflDfmB6SGYFIEFa%2BKRBOU%3D", oauth_token="673806b7-aa7b-4064-8290-2dd1b0236ae6", oauth_consumer_key="ca29ba5e-6868-4468-987d-4ee60a1f04bf", oauth_timestamp="1616050850", oauth_signature_method="HMAC-SHA1", oauth_version="1.0"
#Host: apis.garmin.com
#Accept: */*
#curl -v --header 'Authorization: OAuth oauth_nonce="3347376452", oauth_signature="jM8%2BCsflDfmB6SGYFIEFa%2BKRBOU%3D", oauth_token="673806b7-aa7b-4064-8290-2dd1b0236ae6", oauth_consumer_key="ca29ba5e-6868-4468-987d-4ee60a1f04bf", oauth_timestamp="1616050850", oauth_signature_method="HMAC-SHA1", oauth_version="1.0"' 'https://apis.garmin.com/training-api/workout'
#Authorization: OAuth oauth_nonce="3347376452", oauth_signature="jM8%2BCsflDfmB6SGYFIEFa%2BKRBOU%3D", oauth_token="673806b7-aa7b-4064-8290-2dd1b0236ae6", oauth_consumer_key="ca29ba5e-6868-4468-987d-4ee60a1f04bf", oauth_timestamp="1616050850", oauth_signature_method="HMAC-SHA1", oauth_version="1.0"
return response
def get_garmin_permissions(user): # pragma: no cover def get_garmin_permissions(user): # pragma: no cover
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
@@ -334,15 +370,18 @@ def get_garmin_permissions(user): # pragma: no cover
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
garmin = OAuth1Session(oauth_data['client_id'], garminheaders = OAuth1(
client_secret=oauth_data['client_secret'], client_key = oauth_data['client_id'],
resource_owner_key=r.garmintoken, client_secret=oauth_data['client_secret'],
resource_owner_secret=r.garminrefreshtoken, resource_owner_key=r.garmintoken,
) resource_owner_secret=r.garminrefreshtoken,
signature_method='HMAC-SHA1',
)
url = 'https://apis.garmin.com/userPermissions/'
result = garmin.get(url) url = 'https://apis.garmin.com/userPermissions'
result = requests.get(url,auth=garminheaders)
if result.status_code == 200: if result.status_code == 200:
return result.json() return result.json()
@@ -351,31 +390,58 @@ def get_garmin_permissions(user): # pragma: no cover
def garmin_session_create(ps,user): # pragma: no cover def garmin_session_create(ps,user): # pragma: no cover
if not ps.steps: if not ps.steps:
print('aap')
return 0 return 0
if not garmin_can_export_session(user): if not garmin_can_export_session(user):
print('noot')
return 0 return 0
garmindict = ps_to_garmin(ps)
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.garmintoken == '') or (r.garmintoken is None): if (r.garmintoken == '') or (r.garmintoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
garmin = OAuth1Session(oauth_data['client_id'], payload = ps_to_garmin(ps,r)
client_secret=oauth_data['client_secret'],
resource_owner_key=r.garmintoken,
resource_owner_secret=r.garminrefreshtoken,
)
url = 'http://apis.garmin.com/training-api/schedule/' url = 'https://apis.garmin.com/training-api/workout'
garminheaders = OAuth1(
client_key = oauth_data['client_id'],
client_secret=oauth_data['client_secret'],
resource_owner_key=r.garmintoken,
resource_owner_secret=r.garminrefreshtoken,
signature_method='HMAC-SHA1',
)
response = requests.post(url,auth=garminheaders,json=payload)
print(response.status_code,response.text)
response = garmin.post(url,data=garmindict)
if response.status_code != 200: if response.status_code != 200:
return 0 return 0
return response.json()['workoutId'] garmin_workout_id = response.json()['workoutId']
url = 'http://apis.garmin.com/training-api/schedule'
payload = {
'workoutId': garmin_workout_id,
'date': ps.preferreddate.strftime('%Y-%m-%d')
}
response = requests.post(url,auth=garminheaders,json=payload)
print(response.status_code,response.text)
if response.status_code != 200:
return 0
ps.garmin_schedule_id = response.json()
ps.garmin_workout_id = garmin_workout_id
ps.save()
return garmin_workout_id
def garmin_getworkout(garminid,r,activity): def garmin_getworkout(garminid,r,activity):
starttime = activity['startTimeInSeconds'] starttime = activity['startTimeInSeconds']

View File

@@ -2399,6 +2399,8 @@ class PlannedSession(models.Model):
steps = PlannedSessionStepField(default={},null=True) steps = PlannedSessionStepField(default={},null=True)
interval_string = models.TextField(max_length=1000,default=None,blank=True,null=True, interval_string = models.TextField(max_length=1000,default=None,blank=True,null=True,
verbose_name='Interval String (optional)') verbose_name='Interval String (optional)')
garmin_workout_id = models.BigIntegerField(default=0)
garmin_schedule_id = models.BigIntegerField(default=0)
tags = TaggableManager(blank=True) tags = TaggableManager(blank=True)