Skip to content

Strength workouts: optional per-step description and a time-based exercise step helper #458

Open

Description

@mukhtadir-syed

Summary

Two small gaps in the strength workout helpers that I currently work around by hand:

  1. There is no way to set a description on an individual workout step. BaseWorkout.description (add description to workouts #339) covers the whole workout; I use a per-step description for form cues.
  2. create_strength_exercise_step is 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: ExecutableStep with an interval step type, endCondition {"conditionTypeId": 2, "conditionTypeKey": "time"}, endConditionValue: 20.0, plus category: "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
  • description set by hand on both exercise steps (ExecutableStep allows extra fields)

Results:

  1. upload_strength_workout accepted it.
  2. get_workout_by_id readback: both exercise steps came back with a non-empty exerciseName (including the time-based one) and a description.
  3. schedule_workout and push_workout_to_device succeeded, 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

  1. Add description: str | None = None to ExecutableStep, plus an optional description param on create_strength_exercise_step and create_strength_set (applied to the exercise step). Since to_dict() uses exclude_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.
  2. Add create_strength_timed_step for time-based exercises, following the create_distance_interval_step precedent (Add distance-based workout interval helper #375) of a separate helper instead of a mode flag. A duration_seconds option on create_strength_set would 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions