cyberjunky / python-garminconnect

Python 3 API wrapper for Garmin Connect to get activity statistics
MIT License
908 stars 142 forks source link

Uploading Workouts #185

Open euanChalmers02 opened 8 months ago

euanChalmers02 commented 8 months ago

Could anyone advise on if I have made any mistakes in creating an example for creating a workout using the API as part of a package fork? current works to list all workout but not creating new?


       garmin_workouts = (
            "/workout-service"
        )
        url = f"{garmin_workouts}/workout"

        expected_workout_payload = {
            'workoutId': "random_id",
            'ownerId': "random",
            'workoutName': 'Any workout name',
            'description': 'FTP 200, TSS 1, NP 114, IF 0.57',
            'sportType': {'sportTypeId': 2, 'sportTypeKey': 'cycling'},
            'workoutSegments': [
                {
                    'segmentOrder': 1,
                    'sportType': {'sportTypeId': 2, 'sportTypeKey': 'cycling'},
                    'workoutSteps': [
                        {'type': 'ExecutableStepDTO', 'stepOrder': 1,
                         'stepType': {'stepTypeId': 3, 'stepTypeKey': 'interval'}, 'childStepId': None,
                         'endCondition': {'conditionTypeId': 2, 'conditionTypeKey': 'time'}, 'endConditionValue': 60,
                         'targetType': {'workoutTargetTypeId': 2, 'workoutTargetTypeKey': 'power.zone'},
                         'targetValueOne': 95, 'targetValueTwo': 105},
                        {'type': 'ExecutableStepDTO', 'stepOrder': 2,
                         'stepType': {'stepTypeId': 3, 'stepTypeKey': 'interval'}, 'childStepId': None,
                         'endCondition': {'conditionTypeId': 2, 'conditionTypeKey': 'time'}, 'endConditionValue': 120,
                         'targetType': {'workoutTargetTypeId': 2, 'workoutTargetTypeKey': 'power.zone'},
                         'targetValueOne': 114, 'targetValueTwo': 126}
                    ]
                }
            ]
        }

        response = self.garth.post("save", url, json=expected_workout_payload)
        print("Response: "+str(response))
        return response
matin commented 8 months ago

What response are you receiving?

At first glance, you're missing api=True in self.garth.post(). Without that flag, it won't pass the auth tokens in the request.

euanChalmers02 commented 8 months ago

The following extra methods should work for other commands (within init) : ` def get_workouts(self):

only gets first 100

    url = f"{self.garmin_workouts}/workouts"
    logger.debug("Requesting user summary")
    params = {
        "start": 0,
        "limit": 100
    }
    response = self.connectapi(url, params=params)
    return response

def get_workout_by_id(self,workoutID):
    url = f"{self.garmin_workouts}/workout/"+workoutID
    response = self.connectapi(url)
    return response

def download_workout_by_id(self, workoutID):
    url = f"{self.garmin_workouts}/workout/FIT/" + workoutID
    response = self.connectapi(url)

    with open("Download_Workout"+workoutID, "wb") as f:
        f.write(response.content)

    return response
    `
cyberjunky commented 8 months ago

I added the calls to the new version (to be released tomorrow) I renamed

def download_workout_by_id(self, workoutID):

to:

def download_workout(self, workoutID):

So it named the same as the other download methods

cyberjunky commented 8 months ago

Oh wait I didn't include upload_workout(), need to look at that.

cyberjunky commented 8 months ago

@euanChalmers02 Did you get the upload working, if so how? ;-)

cyberjunky commented 8 months ago

I added the get and download methods to version 0.2.13, didn't get het upload function to work yet though.

euanChalmers02 commented 8 months ago

Thanks alot very helpful, and no I did some trial and error but no luck and have reverted to copying files directly from PC due to this being deprecated by garmin I think?

OscarSalgado commented 8 months ago

Workout upload works fine via workout-service, you just need the correct payload (workout json structure). May be a bit tricky depending on sport, duration, intensity, etc.

euanChalmers02 commented 8 months ago

Great, Would you happen to have an example payload I can use to develop some tests /examples for different sports?

OscarSalgado commented 8 months ago

Feel free to check https://github.com/OscarSalgado/garmin-workouts

It is not as documented as it should be but I hope you can follow the rationale behind. I tried to simplify workout definition as much as possible.

Intensively tested for running workouts, although I made some tests for the rest of sports. Happy to help