fix: find keys

This commit is contained in:
2026-05-10 13:54:07 +02:00
parent dbe75abacc
commit c5c2a5b5bd
+16 -228
View File
@@ -6,14 +6,13 @@ metadata:
data: data:
sync.py: | sync.py: |
import os import os
import json
import time import time
from datetime import date, timedelta from datetime import date, timedelta
import psycopg2
from garminconnect import Garmin from garminconnect import Garmin
email = os.environ["GARMIN_EMAIL"] email = os.environ["GARMIN_EMAIL"]
password = os.environ["GARMIN_PASSWORD"] password = os.environ["GARMIN_PASSWORD"]
db_url = os.environ["DATABASE_URL"]
client = Garmin(email, password) client = Garmin(email, password)
for attempt in range(5): for attempt in range(5):
@@ -31,232 +30,21 @@ data:
else: else:
raise Exception("Login nach 5 Versuchen fehlgeschlagen") raise Exception("Login nach 5 Versuchen fehlgeschlagen")
today = date.today() d = (date.today() - timedelta(days=1)).isoformat()
start = today - timedelta(days=365 * 3) print(f"=== Debug fuer {d} ===")
conn = psycopg2.connect(db_url) for name, fn, args in [
cur = conn.cursor() ("stats", client.get_stats, [d]),
("stress", client.get_stress_data, [d]),
# ── Schema ──────────────────────────────────────────────────────────────── ("bb", client.get_body_battery, [d, d]),
("spo2", client.get_spo2_data, [d]),
cur.execute(""" ("resp", client.get_respiration_data, [d]),
CREATE TABLE IF NOT EXISTS activities ( ("hrv", client.get_hrv_data, [d]),
id BIGINT PRIMARY KEY, ("sleep", client.get_sleep_data, [d]),
name TEXT, ]:
type TEXT,
start_time TIMESTAMP,
duration_seconds FLOAT,
distance_meters FLOAT,
avg_hr INTEGER,
max_hr INTEGER,
avg_pace FLOAT,
vo2max FLOAT,
calories FLOAT,
elevation_gain FLOAT,
steps INTEGER,
cadence FLOAT,
hr_zone_1 FLOAT,
hr_zone_2 FLOAT,
hr_zone_3 FLOAT,
hr_zone_4 FLOAT,
hr_zone_5 FLOAT
)
""")
cur.execute("""
CREATE TABLE IF NOT EXISTS daily_health (
date DATE PRIMARY KEY,
resting_hr INTEGER,
total_steps INTEGER,
total_distance_meters FLOAT,
active_calories FLOAT,
total_calories FLOAT,
stress_avg INTEGER,
stress_max INTEGER,
body_battery_high INTEGER,
body_battery_low INTEGER,
spo2_avg FLOAT,
spo2_min FLOAT,
respiration_avg FLOAT,
hrv_weekly_avg FLOAT,
hrv_last_night FLOAT,
hrv_status TEXT,
sleep_duration_seconds INTEGER,
sleep_deep_seconds INTEGER,
sleep_light_seconds INTEGER,
sleep_rem_seconds INTEGER,
sleep_awake_seconds INTEGER,
sleep_score INTEGER,
sleep_feedback TEXT
)
""")
conn.commit()
# ── Activities ────────────────────────────────────────────────────────────
activities = client.get_activities_by_date(
start.isoformat(), today.isoformat()
)
for a in activities:
cur.execute("""
INSERT INTO activities
(id, name, type, start_time, duration_seconds, distance_meters,
avg_hr, max_hr, avg_pace, vo2max, calories, elevation_gain,
steps, cadence, hr_zone_1, hr_zone_2, hr_zone_3, hr_zone_4, hr_zone_5)
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
ON CONFLICT (id) DO UPDATE SET
duration_seconds = EXCLUDED.duration_seconds,
distance_meters = EXCLUDED.distance_meters,
avg_hr = EXCLUDED.avg_hr,
max_hr = EXCLUDED.max_hr,
avg_pace = EXCLUDED.avg_pace,
vo2max = EXCLUDED.vo2max,
calories = EXCLUDED.calories,
elevation_gain = EXCLUDED.elevation_gain,
steps = EXCLUDED.steps,
cadence = EXCLUDED.cadence,
hr_zone_1 = EXCLUDED.hr_zone_1,
hr_zone_2 = EXCLUDED.hr_zone_2,
hr_zone_3 = EXCLUDED.hr_zone_3,
hr_zone_4 = EXCLUDED.hr_zone_4,
hr_zone_5 = EXCLUDED.hr_zone_5
""", (
a.get("activityId"),
a.get("activityName"),
a.get("activityType", {}).get("typeKey"),
a.get("startTimeLocal"),
a.get("duration"),
a.get("distance"),
a.get("averageHR"),
a.get("maxHR"),
a.get("averageSpeed"),
a.get("vO2MaxValue"),
a.get("calories"),
a.get("elevationGain"),
a.get("steps"),
a.get("averageRunningCadenceInStepsPerMinute"),
a.get("hrTimeInZone_1"),
a.get("hrTimeInZone_2"),
a.get("hrTimeInZone_3"),
a.get("hrTimeInZone_4"),
a.get("hrTimeInZone_5"),
))
conn.commit()
print(f"Synced {len(activities)} activities")
# ── Daily Health (letzte 7 Tage, inkrementell) ────────────────────────────
def safe_get(fn, *args):
try: try:
return fn(*args) result = fn(*args)
print(f"\n=== {name} ===")
print(json.dumps(result, indent=2, default=str)[:3000])
except Exception as e: except Exception as e:
print(f" Warnung {fn.__name__}: {e}") print(f"\n=== {name} FEHLER: {e} ===")
return None
health_start = today - timedelta(days=7)
check_date = health_start
synced = 0
while check_date <= today:
d = check_date.isoformat()
stats = safe_get(client.get_stats, d) or {}
stress = safe_get(client.get_stress_data, d) or {}
bb_list = safe_get(client.get_body_battery, d, d) or []
spo2 = safe_get(client.get_spo2_data, d) or {}
resp = safe_get(client.get_respiration_data, d) or {}
hrv_raw = safe_get(client.get_hrv_data, d) or {}
sleep_raw = safe_get(client.get_sleep_data, d) or {}
hrv = hrv_raw.get("hrvSummary", {})
sleep = sleep_raw.get("dailySleepDTO", {})
bb_high = max((e.get("charged", 0) for e in bb_list), default=None)
bb_low = min((e.get("drained", 0) for e in bb_list), default=None)
cur.execute("""
INSERT INTO daily_health (
date,
resting_hr, total_steps, total_distance_meters,
active_calories, total_calories,
stress_avg, stress_max,
body_battery_high, body_battery_low,
spo2_avg, spo2_min,
respiration_avg,
hrv_weekly_avg, hrv_last_night, hrv_status,
sleep_duration_seconds, sleep_deep_seconds,
sleep_light_seconds, sleep_rem_seconds, sleep_awake_seconds,
sleep_score, sleep_feedback
) VALUES (
%s,
%s,%s,%s,
%s,%s,
%s,%s,
%s,%s,
%s,%s,
%s,
%s,%s,%s,
%s,%s,
%s,%s,%s,
%s,%s
)
ON CONFLICT (date) DO UPDATE SET
resting_hr = EXCLUDED.resting_hr,
total_steps = EXCLUDED.total_steps,
total_distance_meters = EXCLUDED.total_distance_meters,
active_calories = EXCLUDED.active_calories,
total_calories = EXCLUDED.total_calories,
stress_avg = EXCLUDED.stress_avg,
stress_max = EXCLUDED.stress_max,
body_battery_high = EXCLUDED.body_battery_high,
body_battery_low = EXCLUDED.body_battery_low,
spo2_avg = EXCLUDED.spo2_avg,
spo2_min = EXCLUDED.spo2_min,
respiration_avg = EXCLUDED.respiration_avg,
hrv_weekly_avg = EXCLUDED.hrv_weekly_avg,
hrv_last_night = EXCLUDED.hrv_last_night,
hrv_status = EXCLUDED.hrv_status,
sleep_duration_seconds = EXCLUDED.sleep_duration_seconds,
sleep_deep_seconds = EXCLUDED.sleep_deep_seconds,
sleep_light_seconds = EXCLUDED.sleep_light_seconds,
sleep_rem_seconds = EXCLUDED.sleep_rem_seconds,
sleep_awake_seconds = EXCLUDED.sleep_awake_seconds,
sleep_score = EXCLUDED.sleep_score,
sleep_feedback = EXCLUDED.sleep_feedback
""", (
check_date,
stats.get("restingHeartRate"),
stats.get("totalSteps"),
stats.get("totalDistanceMeters"),
stats.get("activeKilocalories"),
stats.get("totalKilocalories"),
stress.get("avgStressLevel"),
stress.get("maxStressLevel"),
bb_high,
bb_low,
spo2.get("avgSpo2"),
spo2.get("lowestSpo2"),
resp.get("avgWakingRespirationValue"),
hrv.get("weeklyAvg"),
hrv.get("lastNight"),
hrv.get("status"),
sleep.get("sleepTimeSeconds"),
sleep.get("deepSleepSeconds"),
sleep.get("lightSleepSeconds"),
sleep.get("remSleepSeconds"),
sleep.get("awakeSleepSeconds"),
(sleep.get("sleepScores") or {}).get("overall", {}).get("value"),
(sleep.get("sleepScores") or {}).get("overall", {}).get("qualifierKey"),
))
conn.commit()
synced += 1
check_date += timedelta(days=1)
time.sleep(0.5)
cur.close()
conn.close()
print(f"Synced {synced} daily health records")