Fix avg_hr_day: remove dead averageHeartRate lookup; add max_hr_day from UDS export
garmin.get_stats() never returns averageHeartRate — avg_hr_day is only computable from intraday HR which Garmin's API only serves for recent dates (~90-120 days). The dead lookup gave false confidence that historical backfill would work. Also populate max_hr_day from the Garmin export's UDS daily summaries (maxHeartRate field is present for the full history), so historical max HR is available after re-importing the export. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -524,7 +524,7 @@ def _parse_day(stats, sleep_data, hrv_data) -> dict:
|
|||||||
|
|
||||||
if stats:
|
if stats:
|
||||||
_set(row, "resting_hr", stats.get("restingHeartRate"))
|
_set(row, "resting_hr", stats.get("restingHeartRate"))
|
||||||
_set(row, "avg_hr_day", stats.get("averageHeartRate"))
|
# averageHeartRate is absent from get_stats; avg_hr_day is computed below from intraday HR
|
||||||
_set(row, "max_hr_day", stats.get("maxHeartRate"))
|
_set(row, "max_hr_day", stats.get("maxHeartRate"))
|
||||||
_set(row, "steps", stats.get("totalSteps"))
|
_set(row, "steps", stats.get("totalSteps"))
|
||||||
_set(row, "floors_climbed", stats.get("floorsAscended"))
|
_set(row, "floors_climbed", stats.get("floorsAscended"))
|
||||||
|
|||||||
@@ -422,12 +422,13 @@ def process_garmin_health_zip(zip_path: str, user_id: int):
|
|||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
|
|
||||||
INSERT_SQL = text("""
|
INSERT_SQL = text("""
|
||||||
INSERT INTO health_metrics (user_id, date, resting_hr, steps,
|
INSERT INTO health_metrics (user_id, date, resting_hr, max_hr_day, steps,
|
||||||
floors_climbed, active_calories, total_calories, avg_stress, spo2_avg)
|
floors_climbed, active_calories, total_calories, avg_stress, spo2_avg)
|
||||||
VALUES (:user_id, :date, :resting_hr, :steps,
|
VALUES (:user_id, :date, :resting_hr, :max_hr_day, :steps,
|
||||||
:floors, :active_cal, :total_cal, :stress, :spo2)
|
:floors, :active_cal, :total_cal, :stress, :spo2)
|
||||||
ON CONFLICT (user_id, date) DO UPDATE SET
|
ON CONFLICT (user_id, date) DO UPDATE SET
|
||||||
resting_hr = COALESCE(EXCLUDED.resting_hr, health_metrics.resting_hr),
|
resting_hr = COALESCE(EXCLUDED.resting_hr, health_metrics.resting_hr),
|
||||||
|
max_hr_day = COALESCE(EXCLUDED.max_hr_day, health_metrics.max_hr_day),
|
||||||
steps = COALESCE(EXCLUDED.steps, health_metrics.steps),
|
steps = COALESCE(EXCLUDED.steps, health_metrics.steps),
|
||||||
floors_climbed = COALESCE(EXCLUDED.floors_climbed, health_metrics.floors_climbed),
|
floors_climbed = COALESCE(EXCLUDED.floors_climbed, health_metrics.floors_climbed),
|
||||||
active_calories = COALESCE(EXCLUDED.active_calories, health_metrics.active_calories),
|
active_calories = COALESCE(EXCLUDED.active_calories, health_metrics.active_calories),
|
||||||
@@ -463,6 +464,7 @@ def process_garmin_health_zip(zip_path: str, user_id: int):
|
|||||||
db.execute(INSERT_SQL, {
|
db.execute(INSERT_SQL, {
|
||||||
"user_id": user_id, "date": date_dt,
|
"user_id": user_id, "date": date_dt,
|
||||||
"resting_hr": item.get("restingHeartRate"),
|
"resting_hr": item.get("restingHeartRate"),
|
||||||
|
"max_hr_day": item.get("maxHeartRate"),
|
||||||
"steps": item.get("totalSteps"),
|
"steps": item.get("totalSteps"),
|
||||||
"floors": _floors_from_item(item),
|
"floors": _floors_from_item(item),
|
||||||
"active_cal": item.get("activeKilocalories"),
|
"active_cal": item.get("activeKilocalories"),
|
||||||
|
|||||||
Reference in New Issue
Block a user