Skip to content

Commit eb5015f

Browse files
committed
fix: correct ConditionType IDs and update all workout enums (issue #370)
ConditionType was wrong: DISTANCE=1 (should be 3), HEART_RATE=3 (should be 6), POWER=6 (should be 5), and CADENCE=5 (not a valid end condition). Authoritative values sourced from /workout-service/workout/types endpoint. - ConditionType: LAP_BUTTON=1, TIME=2, DISTANCE=3, CALORIES=4, POWER=5, HEART_RATE=6, ITERATIONS=7 + add FIXED_REST=8, FIXED_REPETITION=9, REPS=10 - SportType: fix SWIMMING=4, OTHER=3, MULTI_SPORT=10; add STRENGTH_TRAINING, CARDIO_TRAINING, YOGA, PILATES, HIIT, MOBILITY; remove incorrect aliases - TargetType: rename to POWER_ZONE, HEART_RATE_ZONE, SPEED_ZONE, PACE_ZONE; add GRADE=7, HEART_RATE_LAP=8, POWER_LAP=9, RESISTANCE=15 - StepType: add OTHER=7, MAIN=8 - Update test_workout_constants.py to pin the corrected values
1 parent 6e8f81b commit eb5015f

2 files changed

Lines changed: 72 additions & 50 deletions

File tree

garminconnect/workout.py

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,67 @@ def Field(*_args: Any, **_kwargs: Any) -> Any: # type: ignore[misc]
2525
return None
2626

2727

28-
# Sport Type IDs (common values)
28+
# Sport Type IDs — from /workout-service/workout/types
2929
class SportType:
30-
"""Common Garmin sport type IDs."""
30+
"""Garmin workout sport type IDs."""
3131

3232
RUNNING = 1
3333
CYCLING = 2
34-
SWIMMING = 3
35-
WALKING = 4
36-
MULTI_SPORT = 5
37-
FITNESS_EQUIPMENT = 6
38-
HIKING = 7
39-
OTHER = 8
40-
41-
42-
# Step Type IDs
34+
OTHER = 3
35+
SWIMMING = 4
36+
STRENGTH_TRAINING = 5
37+
CARDIO_TRAINING = 6
38+
YOGA = 7
39+
PILATES = 8
40+
HIIT = 9
41+
MULTI_SPORT = 10
42+
MOBILITY = 11
43+
44+
45+
# Step Type IDs — from /workout-service/workout/types
4346
class StepType:
44-
"""Common Garmin workout step type IDs."""
47+
"""Garmin workout step type IDs."""
4548

4649
WARMUP = 1
4750
COOLDOWN = 2
4851
INTERVAL = 3
4952
RECOVERY = 4
5053
REST = 5
5154
REPEAT = 6
55+
OTHER = 7
56+
MAIN = 8
5257

5358

54-
# Condition Type IDs
59+
# Condition Type IDs — from /workout-service/workout/types
5560
class ConditionType:
56-
"""Common Garmin end condition type IDs."""
61+
"""Garmin end condition type IDs."""
5762

58-
DISTANCE = 1
63+
LAP_BUTTON = 1
5964
TIME = 2
60-
HEART_RATE = 3
65+
DISTANCE = 3
6166
CALORIES = 4
62-
CADENCE = 5
63-
POWER = 6
67+
POWER = 5
68+
HEART_RATE = 6
6469
ITERATIONS = 7
70+
FIXED_REST = 8
71+
FIXED_REPETITION = 9
72+
REPS = 10
6573

6674

67-
# Target Type IDs
75+
# Target Type IDs — from /workout-service/workout/types
6876
class TargetType:
69-
"""Common Garmin workout target type IDs."""
77+
"""Garmin workout target type IDs."""
7078

7179
NO_TARGET = 1
72-
POWER = 2 # power.zone
73-
CADENCE = 3 # cadence
74-
HEART_RATE = 4 # heart.rate.zone
75-
SPEED = 5 # speed.zone
76-
OPEN = 6 # open
80+
POWER_ZONE = 2
81+
CADENCE = 3
82+
HEART_RATE_ZONE = 4
83+
SPEED_ZONE = 5
84+
PACE_ZONE = 6
85+
GRADE = 7
86+
HEART_RATE_LAP = 8
87+
POWER_LAP = 9
88+
RESISTANCE = 15
7789

7890

7991
class SportTypeModel(BaseModel):
@@ -208,9 +220,7 @@ class SwimmingWorkout(BaseWorkout):
208220

209221
sportType: dict[str, Any] = Field(
210222
default_factory=lambda: {
211-
# Garmin workout-service expects swimming sportTypeId=4.
212-
# Using 3 gets normalized to sportTypeKey="other" on upload.
213-
"sportTypeId": 4,
223+
"sportTypeId": SportType.SWIMMING,
214224
"sportTypeKey": "swimming",
215225
"displayOrder": 3,
216226
}
@@ -222,9 +232,9 @@ class WalkingWorkout(BaseWorkout):
222232

223233
sportType: dict[str, Any] = Field(
224234
default_factory=lambda: {
225-
"sportTypeId": SportType.WALKING,
235+
"sportTypeId": 17,
226236
"sportTypeKey": "walking",
227-
"displayOrder": 4,
237+
"displayOrder": 17,
228238
}
229239
)
230240

@@ -236,7 +246,7 @@ class MultiSportWorkout(BaseWorkout):
236246
default_factory=lambda: {
237247
"sportTypeId": SportType.MULTI_SPORT,
238248
"sportTypeKey": "multi_sport",
239-
"displayOrder": 5,
249+
"displayOrder": 10,
240250
}
241251
)
242252

@@ -246,8 +256,8 @@ class FitnessEquipmentWorkout(BaseWorkout):
246256

247257
sportType: dict[str, Any] = Field(
248258
default_factory=lambda: {
249-
"sportTypeId": SportType.FITNESS_EQUIPMENT,
250-
"sportTypeKey": "fitness_equipment",
259+
"sportTypeId": SportType.CARDIO_TRAINING,
260+
"sportTypeKey": "cardio_training",
251261
"displayOrder": 6,
252262
}
253263
)
@@ -258,9 +268,9 @@ class HikingWorkout(BaseWorkout):
258268

259269
sportType: dict[str, Any] = Field(
260270
default_factory=lambda: {
261-
"sportTypeId": SportType.HIKING,
271+
"sportTypeId": 18,
262272
"sportTypeKey": "hiking",
263-
"displayOrder": 7,
273+
"displayOrder": 18,
264274
}
265275
)
266276

tests/test_workout_constants.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717
def test_target_type_ids() -> None:
1818
"""Pin TargetType IDs to match Garmin API values (issue #333)."""
1919
assert TargetType.NO_TARGET == 1
20-
assert TargetType.POWER == 2
20+
assert TargetType.POWER_ZONE == 2
2121
assert TargetType.CADENCE == 3
22-
assert TargetType.HEART_RATE == 4
23-
assert TargetType.SPEED == 5
24-
assert TargetType.OPEN == 6
22+
assert TargetType.HEART_RATE_ZONE == 4
23+
assert TargetType.SPEED_ZONE == 5
24+
assert TargetType.PACE_ZONE == 6
25+
assert TargetType.GRADE == 7
26+
assert TargetType.HEART_RATE_LAP == 8
27+
assert TargetType.POWER_LAP == 9
28+
assert TargetType.RESISTANCE == 15
2529

2630

2731
def test_step_type_ids() -> None:
@@ -32,29 +36,37 @@ def test_step_type_ids() -> None:
3236
assert StepType.RECOVERY == 4
3337
assert StepType.REST == 5
3438
assert StepType.REPEAT == 6
39+
assert StepType.OTHER == 7
40+
assert StepType.MAIN == 8
3541

3642

3743
def test_condition_type_ids() -> None:
38-
"""Pin ConditionType IDs to match Garmin API values."""
39-
assert ConditionType.DISTANCE == 1
44+
"""Pin ConditionType IDs to match Garmin API values (fixes issue #370)."""
45+
assert ConditionType.LAP_BUTTON == 1
4046
assert ConditionType.TIME == 2
41-
assert ConditionType.HEART_RATE == 3
47+
assert ConditionType.DISTANCE == 3
4248
assert ConditionType.CALORIES == 4
43-
assert ConditionType.CADENCE == 5
44-
assert ConditionType.POWER == 6
49+
assert ConditionType.POWER == 5
50+
assert ConditionType.HEART_RATE == 6
4551
assert ConditionType.ITERATIONS == 7
52+
assert ConditionType.FIXED_REST == 8
53+
assert ConditionType.FIXED_REPETITION == 9
54+
assert ConditionType.REPS == 10
4655

4756

4857
def test_sport_type_ids() -> None:
4958
"""Pin SportType IDs to match Garmin API values."""
5059
assert SportType.RUNNING == 1
5160
assert SportType.CYCLING == 2
52-
assert SportType.SWIMMING == 3
53-
assert SportType.WALKING == 4
54-
assert SportType.MULTI_SPORT == 5
55-
assert SportType.FITNESS_EQUIPMENT == 6
56-
assert SportType.HIKING == 7
57-
assert SportType.OTHER == 8
61+
assert SportType.OTHER == 3
62+
assert SportType.SWIMMING == 4
63+
assert SportType.STRENGTH_TRAINING == 5
64+
assert SportType.CARDIO_TRAINING == 6
65+
assert SportType.YOGA == 7
66+
assert SportType.PILATES == 8
67+
assert SportType.HIIT == 9
68+
assert SportType.MULTI_SPORT == 10
69+
assert SportType.MOBILITY == 11
5870

5971

6072
def test_swimming_workout_uses_expected_sport_type_id() -> None:

0 commit comments

Comments
 (0)