diff --git a/clusters/homelab/apps/garmin/configmap.yaml b/clusters/homelab/apps/garmin/configmap.yaml index b178af2..d1971be 100644 --- a/clusters/homelab/apps/garmin/configmap.yaml +++ b/clusters/homelab/apps/garmin/configmap.yaml @@ -1,125 +1,131 @@ -import os -import time -from datetime import date, timedelta -import psycopg2 -from garminconnect import Garmin +apiVersion: v1 +kind: ConfigMap +metadata: + name: garmin-sync-script + namespace: garmin +data: + sync.py: | + import os + import time + from datetime import date, timedelta + import psycopg2 + from garminconnect import Garmin -email = os.environ["GARMIN_EMAIL"] -password = os.environ["GARMIN_PASSWORD"] -db_url = os.environ["DATABASE_URL"] + email = os.environ["GARMIN_EMAIL"] + password = os.environ["GARMIN_PASSWORD"] + db_url = os.environ["DATABASE_URL"] -# Retry-Login bei 429 -client = Garmin(email, password) -for attempt in range(5): - try: - client.login() - print(f"Login erfolgreich (Versuch {attempt + 1})") - break - except Exception as e: - if "429" in str(e): - wait = 60 * (attempt + 1) - print(f"Rate limited (429), warte {wait}s...") - time.sleep(wait) - else: - raise -else: - raise Exception("Login nach 5 Versuchen fehlgeschlagen") + client = Garmin(email, password) + for attempt in range(5): + try: + client.login() + print(f"Login erfolgreich (Versuch {attempt + 1})") + break + except Exception as e: + if "429" in str(e): + wait = 60 * (attempt + 1) + print(f"Rate limited (429), warte {wait}s...") + time.sleep(wait) + else: + raise + else: + raise Exception("Login nach 5 Versuchen fehlgeschlagen") -today = date.today() -start = today - timedelta(days=365 * 3) + today = date.today() + start = today - timedelta(days=365 * 3) -activities = client.get_activities_by_date( - start.isoformat(), today.isoformat() -) - -conn = psycopg2.connect(db_url) -cur = conn.cursor() - -cur.execute(""" - CREATE TABLE IF NOT EXISTS activities ( - id BIGINT PRIMARY KEY, - 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 + activities = client.get_activities_by_date( + start.isoformat(), today.isoformat() ) -""") -cur.execute(""" - ALTER TABLE activities - ADD COLUMN IF NOT EXISTS max_hr INTEGER, - ADD COLUMN IF NOT EXISTS vo2max FLOAT, - ADD COLUMN IF NOT EXISTS calories FLOAT, - ADD COLUMN IF NOT EXISTS elevation_gain FLOAT, - ADD COLUMN IF NOT EXISTS steps INTEGER, - ADD COLUMN IF NOT EXISTS cadence FLOAT, - ADD COLUMN IF NOT EXISTS hr_zone_1 FLOAT, - ADD COLUMN IF NOT EXISTS hr_zone_2 FLOAT, - ADD COLUMN IF NOT EXISTS hr_zone_3 FLOAT, - ADD COLUMN IF NOT EXISTS hr_zone_4 FLOAT, - ADD COLUMN IF NOT EXISTS hr_zone_5 FLOAT -""") + conn = psycopg2.connect(db_url) + cur = conn.cursor() -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"), - )) + CREATE TABLE IF NOT EXISTS activities ( + id BIGINT PRIMARY KEY, + 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 + ) + """) -conn.commit() -cur.close() -conn.close() -print(f"Synced {len(activities)} activities") + cur.execute(""" + ALTER TABLE activities + ADD COLUMN IF NOT EXISTS max_hr INTEGER, + ADD COLUMN IF NOT EXISTS vo2max FLOAT, + ADD COLUMN IF NOT EXISTS calories FLOAT, + ADD COLUMN IF NOT EXISTS elevation_gain FLOAT, + ADD COLUMN IF NOT EXISTS steps INTEGER, + ADD COLUMN IF NOT EXISTS cadence FLOAT, + ADD COLUMN IF NOT EXISTS hr_zone_1 FLOAT, + ADD COLUMN IF NOT EXISTS hr_zone_2 FLOAT, + ADD COLUMN IF NOT EXISTS hr_zone_3 FLOAT, + ADD COLUMN IF NOT EXISTS hr_zone_4 FLOAT, + ADD COLUMN IF NOT EXISTS hr_zone_5 FLOAT + """) + + 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() + cur.close() + conn.close() + print(f"Synced {len(activities)} activities")