fix: correct placeholder count daily_health
This commit is contained in:
@@ -63,73 +63,63 @@ data:
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Keys verified: (D) = aus deinem Debug-Output direkt bestaetigt
|
|
||||||
# (S) = aus Quellcode/Pydantic-Models
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS daily_health (
|
CREATE TABLE IF NOT EXISTS daily_health (
|
||||||
date DATE PRIMARY KEY,
|
date DATE PRIMARY KEY,
|
||||||
|
resting_hr INTEGER,
|
||||||
-- get_stats (D)
|
min_hr INTEGER,
|
||||||
resting_hr INTEGER, -- restingHeartRate
|
max_hr INTEGER,
|
||||||
min_hr INTEGER, -- minHeartRate
|
total_steps INTEGER,
|
||||||
max_hr INTEGER, -- maxHeartRate
|
daily_step_goal INTEGER,
|
||||||
total_steps INTEGER, -- totalSteps
|
total_distance_meters FLOAT,
|
||||||
daily_step_goal INTEGER, -- dailyStepGoal
|
active_calories FLOAT,
|
||||||
total_distance_meters FLOAT, -- totalDistanceMeters
|
total_calories FLOAT,
|
||||||
active_calories FLOAT, -- activeKilocalories
|
bmr_calories FLOAT,
|
||||||
total_calories FLOAT, -- totalKilocalories
|
highly_active_seconds INTEGER,
|
||||||
bmr_calories FLOAT, -- bmrKilocalories
|
active_seconds INTEGER,
|
||||||
highly_active_seconds INTEGER, -- highlyActiveSeconds
|
sedentary_seconds INTEGER,
|
||||||
active_seconds INTEGER, -- activeSeconds
|
sleeping_seconds INTEGER,
|
||||||
sedentary_seconds INTEGER, -- sedentarySeconds
|
moderate_intensity_minutes INTEGER,
|
||||||
sleeping_seconds INTEGER, -- sleepingSeconds
|
vigorous_intensity_minutes INTEGER,
|
||||||
moderate_intensity_minutes INTEGER, -- moderateIntensityMinutes
|
floors_ascended FLOAT,
|
||||||
vigorous_intensity_minutes INTEGER, -- vigorousIntensityMinutes
|
floors_descended FLOAT,
|
||||||
floors_ascended FLOAT, -- floorsAscended
|
average_stress INTEGER,
|
||||||
floors_descended FLOAT, -- floorsDescended
|
max_stress INTEGER,
|
||||||
average_stress INTEGER, -- averageStressLevel
|
rest_stress_duration INTEGER,
|
||||||
max_stress INTEGER, -- maxStressLevel
|
low_stress_duration INTEGER,
|
||||||
rest_stress_duration INTEGER, -- restStressDuration
|
medium_stress_duration INTEGER,
|
||||||
low_stress_duration INTEGER, -- lowStressDuration
|
high_stress_duration INTEGER,
|
||||||
medium_stress_duration INTEGER, -- mediumStressDuration
|
stress_qualifier TEXT,
|
||||||
high_stress_duration INTEGER, -- highStressDuration
|
body_battery_highest INTEGER,
|
||||||
stress_qualifier TEXT, -- stressQualifier
|
body_battery_lowest INTEGER,
|
||||||
body_battery_highest INTEGER, -- bodyBatteryHighestValue
|
body_battery_most_recent INTEGER,
|
||||||
body_battery_lowest INTEGER, -- bodyBatteryLowestValue
|
body_battery_at_wake INTEGER,
|
||||||
body_battery_most_recent INTEGER, -- bodyBatteryMostRecentValue
|
body_battery_during_sleep INTEGER,
|
||||||
body_battery_at_wake INTEGER, -- bodyBatteryAtWakeTime
|
average_spo2 FLOAT,
|
||||||
body_battery_during_sleep INTEGER, -- bodyBatteryDuringSleep
|
lowest_spo2 FLOAT,
|
||||||
average_spo2 FLOAT, -- averageSpo2
|
latest_spo2 FLOAT,
|
||||||
lowest_spo2 FLOAT, -- lowestSpo2
|
hrv_weekly_avg FLOAT,
|
||||||
latest_spo2 FLOAT, -- latestSpo2
|
hrv_last_night FLOAT,
|
||||||
|
hrv_last_night_5min_high FLOAT,
|
||||||
-- get_hrv_data -> hrvSummary (S - wird null wenn Uhr nicht getragen)
|
hrv_baseline_low FLOAT,
|
||||||
hrv_weekly_avg FLOAT, -- weeklyAvg
|
hrv_baseline_high FLOAT,
|
||||||
hrv_last_night FLOAT, -- lastNight
|
hrv_status TEXT,
|
||||||
hrv_last_night_5min_high FLOAT, -- lastNight5MinHigh
|
hrv_feedback TEXT,
|
||||||
hrv_baseline_low FLOAT, -- baselineLowUpper
|
sleep_start_local TIMESTAMP,
|
||||||
hrv_baseline_high FLOAT, -- baselineBalancedLower
|
sleep_end_local TIMESTAMP,
|
||||||
hrv_status TEXT, -- status
|
sleep_duration_seconds INTEGER,
|
||||||
hrv_feedback TEXT, -- feedbackPhrase
|
sleep_nap_seconds INTEGER,
|
||||||
|
sleep_deep_seconds INTEGER,
|
||||||
-- get_sleep_data -> dailySleepDTO (D)
|
sleep_light_seconds INTEGER,
|
||||||
sleep_start_local TIMESTAMP, -- sleepStartTimestampLocal
|
sleep_rem_seconds INTEGER,
|
||||||
sleep_end_local TIMESTAMP, -- sleepEndTimestampLocal
|
sleep_awake_seconds INTEGER,
|
||||||
sleep_duration_seconds INTEGER, -- sleepTimeSeconds
|
sleep_rem_capable BOOLEAN,
|
||||||
sleep_nap_seconds INTEGER, -- napTimeSeconds
|
sleep_score INTEGER,
|
||||||
sleep_deep_seconds INTEGER, -- deepSleepSeconds
|
sleep_feedback TEXT,
|
||||||
sleep_light_seconds INTEGER, -- lightSleepSeconds
|
respiration_avg_waking FLOAT,
|
||||||
sleep_rem_seconds INTEGER, -- remSleepSeconds
|
respiration_avg_sleep FLOAT,
|
||||||
sleep_awake_seconds INTEGER, -- awakeSleepSeconds
|
respiration_lowest FLOAT,
|
||||||
sleep_rem_capable BOOLEAN, -- deviceRemCapable
|
respiration_highest FLOAT
|
||||||
sleep_score INTEGER, -- sleepScores.overall.value
|
|
||||||
sleep_feedback TEXT, -- sleepScores.overall.qualifierKey
|
|
||||||
|
|
||||||
-- get_respiration_data (D)
|
|
||||||
respiration_avg_waking FLOAT, -- avgWakingRespirationValue
|
|
||||||
respiration_avg_sleep FLOAT, -- avgSleepRespirationValue
|
|
||||||
respiration_lowest FLOAT, -- lowestRespirationValue
|
|
||||||
respiration_highest FLOAT -- highestRespirationValue
|
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@@ -198,6 +188,50 @@ data:
|
|||||||
print(f" Warnung {fn.__name__}: {e}")
|
print(f" Warnung {fn.__name__}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
COLS = """
|
||||||
|
date,
|
||||||
|
resting_hr, min_hr, max_hr,
|
||||||
|
total_steps, daily_step_goal, total_distance_meters,
|
||||||
|
active_calories, total_calories, bmr_calories,
|
||||||
|
highly_active_seconds, active_seconds,
|
||||||
|
sedentary_seconds, sleeping_seconds,
|
||||||
|
moderate_intensity_minutes, vigorous_intensity_minutes,
|
||||||
|
floors_ascended, floors_descended,
|
||||||
|
average_stress, max_stress,
|
||||||
|
rest_stress_duration, low_stress_duration,
|
||||||
|
medium_stress_duration, high_stress_duration,
|
||||||
|
stress_qualifier,
|
||||||
|
body_battery_highest, body_battery_lowest,
|
||||||
|
body_battery_most_recent, body_battery_at_wake,
|
||||||
|
body_battery_during_sleep,
|
||||||
|
average_spo2, lowest_spo2, latest_spo2,
|
||||||
|
hrv_weekly_avg, hrv_last_night, hrv_last_night_5min_high,
|
||||||
|
hrv_baseline_low, hrv_baseline_high,
|
||||||
|
hrv_status, hrv_feedback,
|
||||||
|
sleep_start_local, sleep_end_local,
|
||||||
|
sleep_duration_seconds, sleep_nap_seconds,
|
||||||
|
sleep_deep_seconds, sleep_light_seconds,
|
||||||
|
sleep_rem_seconds, sleep_awake_seconds,
|
||||||
|
sleep_rem_capable, sleep_score, sleep_feedback,
|
||||||
|
respiration_avg_waking, respiration_avg_sleep,
|
||||||
|
respiration_lowest, respiration_highest
|
||||||
|
"""
|
||||||
|
|
||||||
|
N = len([c for c in COLS.split(",") if c.strip()]) # = 55
|
||||||
|
PLACEHOLDERS = ",".join(["%s"] * N)
|
||||||
|
|
||||||
|
UPDATE = ", ".join(
|
||||||
|
f"{c.strip()} = EXCLUDED.{c.strip()}"
|
||||||
|
for c in COLS.split(",")
|
||||||
|
if c.strip() and c.strip() != "date"
|
||||||
|
)
|
||||||
|
|
||||||
|
INSERT_SQL = f"""
|
||||||
|
INSERT INTO daily_health ({COLS})
|
||||||
|
VALUES ({PLACEHOLDERS})
|
||||||
|
ON CONFLICT (date) DO UPDATE SET {UPDATE}
|
||||||
|
"""
|
||||||
|
|
||||||
synced = 0
|
synced = 0
|
||||||
check_date = today - timedelta(days=7)
|
check_date = today - timedelta(days=7)
|
||||||
|
|
||||||
@@ -211,123 +245,10 @@ data:
|
|||||||
|
|
||||||
hrv = hrv_raw.get("hrvSummary") or {}
|
hrv = hrv_raw.get("hrvSummary") or {}
|
||||||
sleep = sleep_r.get("dailySleepDTO") or {}
|
sleep = sleep_r.get("dailySleepDTO") or {}
|
||||||
scores = ((sleep.get("sleepScores") or {}).get("overall") or {})
|
scores = (sleep.get("sleepScores") or {}).get("overall") or {}
|
||||||
|
|
||||||
cur.execute("""
|
values = (
|
||||||
INSERT INTO daily_health (
|
|
||||||
date,
|
|
||||||
resting_hr, min_hr, max_hr,
|
|
||||||
total_steps, daily_step_goal, total_distance_meters,
|
|
||||||
active_calories, total_calories, bmr_calories,
|
|
||||||
highly_active_seconds, active_seconds,
|
|
||||||
sedentary_seconds, sleeping_seconds,
|
|
||||||
moderate_intensity_minutes, vigorous_intensity_minutes,
|
|
||||||
floors_ascended, floors_descended,
|
|
||||||
average_stress, max_stress,
|
|
||||||
rest_stress_duration, low_stress_duration,
|
|
||||||
medium_stress_duration, high_stress_duration,
|
|
||||||
stress_qualifier,
|
|
||||||
body_battery_highest, body_battery_lowest,
|
|
||||||
body_battery_most_recent, body_battery_at_wake,
|
|
||||||
body_battery_during_sleep,
|
|
||||||
average_spo2, lowest_spo2, latest_spo2,
|
|
||||||
hrv_weekly_avg, hrv_last_night, hrv_last_night_5min_high,
|
|
||||||
hrv_baseline_low, hrv_baseline_high,
|
|
||||||
hrv_status, hrv_feedback,
|
|
||||||
sleep_start_local, sleep_end_local,
|
|
||||||
sleep_duration_seconds, sleep_nap_seconds,
|
|
||||||
sleep_deep_seconds, sleep_light_seconds,
|
|
||||||
sleep_rem_seconds, sleep_awake_seconds,
|
|
||||||
sleep_rem_capable, sleep_score, sleep_feedback,
|
|
||||||
respiration_avg_waking, respiration_avg_sleep,
|
|
||||||
respiration_lowest, respiration_highest
|
|
||||||
) VALUES (
|
|
||||||
%s,
|
|
||||||
%s,%s,%s,
|
|
||||||
%s,%s,%s,
|
|
||||||
%s,%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,%s,
|
|
||||||
%s,
|
|
||||||
%s,%s,%s,
|
|
||||||
%s,%s,%s,
|
|
||||||
%s,%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,
|
|
||||||
min_hr = EXCLUDED.min_hr,
|
|
||||||
max_hr = EXCLUDED.max_hr,
|
|
||||||
total_steps = EXCLUDED.total_steps,
|
|
||||||
daily_step_goal = EXCLUDED.daily_step_goal,
|
|
||||||
total_distance_meters = EXCLUDED.total_distance_meters,
|
|
||||||
active_calories = EXCLUDED.active_calories,
|
|
||||||
total_calories = EXCLUDED.total_calories,
|
|
||||||
bmr_calories = EXCLUDED.bmr_calories,
|
|
||||||
highly_active_seconds = EXCLUDED.highly_active_seconds,
|
|
||||||
active_seconds = EXCLUDED.active_seconds,
|
|
||||||
sedentary_seconds = EXCLUDED.sedentary_seconds,
|
|
||||||
sleeping_seconds = EXCLUDED.sleeping_seconds,
|
|
||||||
moderate_intensity_minutes = EXCLUDED.moderate_intensity_minutes,
|
|
||||||
vigorous_intensity_minutes = EXCLUDED.vigorous_intensity_minutes,
|
|
||||||
floors_ascended = EXCLUDED.floors_ascended,
|
|
||||||
floors_descended = EXCLUDED.floors_descended,
|
|
||||||
average_stress = EXCLUDED.average_stress,
|
|
||||||
max_stress = EXCLUDED.max_stress,
|
|
||||||
rest_stress_duration = EXCLUDED.rest_stress_duration,
|
|
||||||
low_stress_duration = EXCLUDED.low_stress_duration,
|
|
||||||
medium_stress_duration = EXCLUDED.medium_stress_duration,
|
|
||||||
high_stress_duration = EXCLUDED.high_stress_duration,
|
|
||||||
stress_qualifier = EXCLUDED.stress_qualifier,
|
|
||||||
body_battery_highest = EXCLUDED.body_battery_highest,
|
|
||||||
body_battery_lowest = EXCLUDED.body_battery_lowest,
|
|
||||||
body_battery_most_recent = EXCLUDED.body_battery_most_recent,
|
|
||||||
body_battery_at_wake = EXCLUDED.body_battery_at_wake,
|
|
||||||
body_battery_during_sleep = EXCLUDED.body_battery_during_sleep,
|
|
||||||
average_spo2 = EXCLUDED.average_spo2,
|
|
||||||
lowest_spo2 = EXCLUDED.lowest_spo2,
|
|
||||||
latest_spo2 = EXCLUDED.latest_spo2,
|
|
||||||
hrv_weekly_avg = EXCLUDED.hrv_weekly_avg,
|
|
||||||
hrv_last_night = EXCLUDED.hrv_last_night,
|
|
||||||
hrv_last_night_5min_high = EXCLUDED.hrv_last_night_5min_high,
|
|
||||||
hrv_baseline_low = EXCLUDED.hrv_baseline_low,
|
|
||||||
hrv_baseline_high = EXCLUDED.hrv_baseline_high,
|
|
||||||
hrv_status = EXCLUDED.hrv_status,
|
|
||||||
hrv_feedback = EXCLUDED.hrv_feedback,
|
|
||||||
sleep_start_local = EXCLUDED.sleep_start_local,
|
|
||||||
sleep_end_local = EXCLUDED.sleep_end_local,
|
|
||||||
sleep_duration_seconds = EXCLUDED.sleep_duration_seconds,
|
|
||||||
sleep_nap_seconds = EXCLUDED.sleep_nap_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_rem_capable = EXCLUDED.sleep_rem_capable,
|
|
||||||
sleep_score = EXCLUDED.sleep_score,
|
|
||||||
sleep_feedback = EXCLUDED.sleep_feedback,
|
|
||||||
respiration_avg_waking = EXCLUDED.respiration_avg_waking,
|
|
||||||
respiration_avg_sleep = EXCLUDED.respiration_avg_sleep,
|
|
||||||
respiration_lowest = EXCLUDED.respiration_lowest,
|
|
||||||
respiration_highest = EXCLUDED.respiration_highest
|
|
||||||
""", (
|
|
||||||
check_date,
|
check_date,
|
||||||
# get_stats
|
|
||||||
stats.get("restingHeartRate"),
|
stats.get("restingHeartRate"),
|
||||||
stats.get("minHeartRate"),
|
stats.get("minHeartRate"),
|
||||||
stats.get("maxHeartRate"),
|
stats.get("maxHeartRate"),
|
||||||
@@ -360,7 +281,6 @@ data:
|
|||||||
stats.get("averageSpo2"),
|
stats.get("averageSpo2"),
|
||||||
stats.get("lowestSpo2"),
|
stats.get("lowestSpo2"),
|
||||||
stats.get("latestSpo2"),
|
stats.get("latestSpo2"),
|
||||||
# get_hrv_data
|
|
||||||
hrv.get("weeklyAvg"),
|
hrv.get("weeklyAvg"),
|
||||||
hrv.get("lastNight"),
|
hrv.get("lastNight"),
|
||||||
hrv.get("lastNight5MinHigh"),
|
hrv.get("lastNight5MinHigh"),
|
||||||
@@ -368,7 +288,6 @@ data:
|
|||||||
hrv.get("baselineBalancedLower"),
|
hrv.get("baselineBalancedLower"),
|
||||||
hrv.get("status"),
|
hrv.get("status"),
|
||||||
hrv.get("feedbackPhrase"),
|
hrv.get("feedbackPhrase"),
|
||||||
# get_sleep_data
|
|
||||||
sleep.get("sleepStartTimestampLocal"),
|
sleep.get("sleepStartTimestampLocal"),
|
||||||
sleep.get("sleepEndTimestampLocal"),
|
sleep.get("sleepEndTimestampLocal"),
|
||||||
sleep.get("sleepTimeSeconds"),
|
sleep.get("sleepTimeSeconds"),
|
||||||
@@ -380,13 +299,14 @@ data:
|
|||||||
sleep.get("deviceRemCapable"),
|
sleep.get("deviceRemCapable"),
|
||||||
scores.get("value"),
|
scores.get("value"),
|
||||||
scores.get("qualifierKey"),
|
scores.get("qualifierKey"),
|
||||||
# get_respiration_data
|
|
||||||
resp.get("avgWakingRespirationValue"),
|
resp.get("avgWakingRespirationValue"),
|
||||||
resp.get("avgSleepRespirationValue"),
|
resp.get("avgSleepRespirationValue"),
|
||||||
resp.get("lowestRespirationValue"),
|
resp.get("lowestRespirationValue"),
|
||||||
resp.get("highestRespirationValue"),
|
resp.get("highestRespirationValue"),
|
||||||
))
|
)
|
||||||
|
|
||||||
|
assert len(values) == N, f"Mismatch: {len(values)} values vs {N} columns"
|
||||||
|
cur.execute(INSERT_SQL, values)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
synced += 1
|
synced += 1
|
||||||
check_date += timedelta(days=1)
|
check_date += timedelta(days=1)
|
||||||
|
|||||||
Reference in New Issue
Block a user