Repository navigation
Strength workouts: optional per-step description and a time-based exercise step helper #458
Description
Summary
Two small gaps in the strength workout helpers that I currently work around by hand:
- There is no way to set a
descriptionon an individual workout step.BaseWorkout.description(add description to workouts #339) covers the whole workout; I use a per-step description for form cues. create_strength_exercise_stepis reps-only. Exercises like planks or carries are done for time, so I build that step myself.
Garmin accepted both when built by hand and returned the fields I checked on readback (details below), so this would need small model/helper changes.
What I tried (garminconnect 0.3.17, 11 Oct 2026, fenix 9 Pro)
A StrengthWorkout with one repeat group (2 rounds) containing:
- a time-based exercise step built by hand:
ExecutableStepwith anintervalstep type,endCondition{"conditionTypeId": 2, "conditionTypeKey": "time"},endConditionValue: 20.0, pluscategory: "WARM_UP"/exerciseName: "ARM_CIRCLES" - a reps step from
create_strength_exercise_step("LATERAL_RAISE", ..., exercise_name="DUMBBELL_LATERAL_RAISE") - a 20 s
create_strength_rest_step descriptionset by hand on both exercise steps (ExecutableStepallows extra fields)
Results:
upload_strength_workoutaccepted it.get_workout_by_idreadback: both exercise steps came back with a non-emptyexerciseName(including the time-based one) and adescription.schedule_workoutandpush_workout_to_devicesucceeded, and the workout appeared on the watch.
Not verified: I did not check end condition fields on readback, so I haven't confirmed the time end condition on the exercise step was stored as sent. I also haven't checked whether the watch shows the step description during the workout.
Proposal
- Add
description: str | None = NonetoExecutableStep, plus an optionaldescriptionparam oncreate_strength_exercise_stepandcreate_strength_set(applied to the exercise step). Sinceto_dict()usesexclude_none=True, existing payloads don't change. I only tested it on exercise steps, so I'd leave rest steps out unless you want it everywhere. - Add
create_strength_timed_stepfor time-based exercises, following thecreate_distance_interval_stepprecedent (Add distance-based workout interval helper #375) of a separate helper instead of a mode flag. Aduration_secondsoption oncreate_strength_setwould work for me too.
Sketch:
def create_strength_timed_step(
category: str,
step_order: int,
duration_seconds: float,
exercise_name: str = "",
weight_kg: float | None = None,
description: str | None = None,
) -> ExecutableStep:
# Same as create_strength_exercise_step, except:
# endCondition={"conditionTypeId": ConditionType.TIME, "conditionTypeKey": "time", ...}
# endConditionValue=float(duration_seconds)
...Tests would go in tests/test_strength_workout.py in the same style.
Happy to send a PR (one or two, whichever you prefer), run through pdm run format && pdm run lint and pdm run test. Before that I'll read back the end condition to confirm Garmin keeps it.
Related
- add description to workouts #339 (merged): workout-level
description - feat: add typed strength workouts with exercise catalog #380 (merged): strength workout helpers (reps-based)
- Add distance-based workout interval helper #375 (merged):
create_distance_interval_step - feat(workout): support skipping final repeat rest #452 (open):
skip_last_rest_stepon repeat groups
Activity