Skip to content

Commit a4580a4

Browse files
committed
Add get_running_tolerance method (issue #328)
1 parent 2c96940 commit a4580a4

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
The Garmin Connect API library comes with two examples:
1212

1313
- **`example.py`** - Simple getting-started example showing authentication, token storage, and basic API calls
14-
- **`demo.py`** - Comprehensive demo providing access to **126+ API methods** organized into **13 categories** for easy navigation
14+
- **`demo.py`** - Comprehensive demo providing access to **127+ API methods** organized into **13 categories** for easy navigation
1515

1616
```bash
1717
$ ./demo.py
@@ -40,11 +40,11 @@ Make your selection:
4040

4141
## API Coverage Statistics
4242

43-
- **Total API Methods**: 126+ unique endpoints (snapshot)
43+
- **Total API Methods**: 127+ unique endpoints (snapshot)
4444
- **Categories**: 13 organized sections
4545
- **User & Profile**: 4 methods (basic user info, settings)
4646
- **Daily Health & Activity**: 9 methods (today's health data)
47-
- **Advanced Health Metrics**: 11 methods (fitness metrics, HRV, VO2, training readiness)
47+
- **Advanced Health Metrics**: 12 methods (fitness metrics, HRV, VO2, training readiness, running tolerance)
4848
- **Historical Data & Trends**: 9 methods (date range queries, weekly aggregates)
4949
- **Activities & Workouts**: 35 methods (comprehensive activity, workout management, typed workout uploads, scheduling, import)
5050
- **Body Composition & Weight**: 8 methods (weight tracking, body composition)
@@ -385,7 +385,7 @@ client.schedule_workout(result["workoutId"], "2026-03-20")
385385

386386
### Additional Resources
387387
- **Simple Example**: [example.py](https://raw.githubusercontent.com/cyberjunky/python-garminconnect/master/example.py) - Getting started guide
388-
- **Comprehensive Demo**: [demo.py](https://raw.githubusercontent.com/cyberjunky/python-garminconnect/master/demo.py) - All 126+ API methods
388+
- **Comprehensive Demo**: [demo.py](https://raw.githubusercontent.com/cyberjunky/python-garminconnect/master/demo.py) - All 127+ API methods
389389
- **API Documentation**: Comprehensive method documentation in source code
390390
- **Test Cases**: Real-world usage examples in `tests/` directory
391391

demo.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ def __init__(self):
202202
"desc": f"Get intensity minutes for '{config.today.isoformat()}'",
203203
"key": "get_intensity_minutes_data",
204204
},
205+
"b": {
206+
"desc": f"Get running tolerance from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'",
207+
"key": "get_running_tolerance",
208+
},
205209
},
206210
},
207211
"4": {
@@ -3640,6 +3644,11 @@ def execute_api_call(api: Garmin, key: str) -> None:
36403644
api_call_desc=f"api.get_all_day_stress('{config.today.isoformat()}')",
36413645
),
36423646
# Advanced Health Metrics
3647+
"get_running_tolerance": lambda: call_and_display(
3648+
api.get_running_tolerance,
3649+
config.week_start.isoformat(),
3650+
config.today.isoformat(),
3651+
),
36433652
"get_training_readiness": lambda: call_and_display(
36443653
api.get_training_readiness,
36453654
config.today.isoformat(),

garminconnect/__init__.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ def __init__(
208208
self.garmin_connect_endurance_score_url = (
209209
"/metrics-service/metrics/endurancescore"
210210
)
211+
self.garmin_connect_running_tolerance_url = (
212+
"/metrics-service/metrics/runningtolerance/stats"
213+
)
211214
self.garmin_connect_menstrual_calendar_url = (
212215
"/periodichealth-service/menstrualcycle/calendar"
213216
)
@@ -1584,6 +1587,41 @@ def get_endurance_score(
15841587

15851588
return self.connectapi(url, params=params)
15861589

1590+
def get_running_tolerance(
1591+
self, startdate: str, enddate: str, aggregation: str = "weekly"
1592+
) -> list[dict[str, Any]]:
1593+
"""Return running tolerance data for date range.
1594+
1595+
Args:
1596+
startdate: Start date in 'YYYY-MM-DD' format.
1597+
enddate: End date in 'YYYY-MM-DD' format.
1598+
aggregation: 'daily' or 'weekly' (default: 'weekly').
1599+
1600+
Returns:
1601+
List of running tolerance data points.
1602+
1603+
"""
1604+
startdate = _validate_date_format(startdate, "startdate")
1605+
enddate = _validate_date_format(enddate, "enddate")
1606+
if aggregation not in ("daily", "weekly"):
1607+
raise ValueError(
1608+
f"Invalid aggregation '{aggregation}'. Must be 'daily' or 'weekly'."
1609+
)
1610+
url = self.garmin_connect_running_tolerance_url
1611+
params = {
1612+
"startDate": str(startdate),
1613+
"endDate": str(enddate),
1614+
"aggregation": aggregation,
1615+
}
1616+
logger.debug(
1617+
"Requesting running tolerance data (%s) from %s to %s",
1618+
aggregation,
1619+
startdate,
1620+
enddate,
1621+
)
1622+
1623+
return self.connectapi(url, params=params)
1624+
15871625
def get_race_predictions(
15881626
self,
15891627
startdate: str | None = None,

0 commit comments

Comments
 (0)