1.x updates
This commit is contained in:
164
db.py
164
db.py
@@ -1,162 +1,2 @@
|
||||
"""SQLite schema + connection helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
|
||||
DB_PATH = Path(__file__).parent / "data" / "garmin.db"
|
||||
|
||||
SCHEMA = """
|
||||
CREATE TABLE IF NOT EXISTS activities (
|
||||
activity_id INTEGER PRIMARY KEY,
|
||||
start_time_local TEXT,
|
||||
start_time_gmt TEXT,
|
||||
activity_type TEXT,
|
||||
activity_name TEXT,
|
||||
distance_m REAL,
|
||||
duration_s REAL,
|
||||
moving_duration_s REAL,
|
||||
avg_speed_mps REAL,
|
||||
max_speed_mps REAL,
|
||||
avg_hr REAL,
|
||||
max_hr REAL,
|
||||
calories REAL,
|
||||
elevation_gain_m REAL,
|
||||
elevation_loss_m REAL,
|
||||
training_load REAL,
|
||||
aerobic_te REAL,
|
||||
anaerobic_te REAL,
|
||||
vo2_max REAL,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_activities_start ON activities(start_time_local);
|
||||
CREATE INDEX IF NOT EXISTS idx_activities_type ON activities(activity_type);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activity_splits (
|
||||
activity_id INTEGER NOT NULL,
|
||||
split_index INTEGER NOT NULL,
|
||||
distance_m REAL,
|
||||
duration_s REAL,
|
||||
avg_hr REAL,
|
||||
avg_speed_mps REAL,
|
||||
elevation_gain_m REAL,
|
||||
raw TEXT NOT NULL,
|
||||
PRIMARY KEY (activity_id, split_index),
|
||||
FOREIGN KEY (activity_id) REFERENCES activities(activity_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_steps (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
total_steps INTEGER,
|
||||
step_goal INTEGER,
|
||||
distance_m REAL,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_sleep (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
sleep_start_gmt TEXT,
|
||||
sleep_end_gmt TEXT,
|
||||
deep_s REAL,
|
||||
light_s REAL,
|
||||
rem_s REAL,
|
||||
awake_s REAL,
|
||||
sleep_score REAL,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_stress (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
avg_stress REAL,
|
||||
max_stress REAL,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_hrv (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
weekly_avg REAL,
|
||||
last_night_avg REAL,
|
||||
last_night_5min REAL,
|
||||
status TEXT,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_body_battery (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
charged INTEGER,
|
||||
drained INTEGER,
|
||||
highest INTEGER,
|
||||
lowest INTEGER,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_intensity_minutes (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
moderate_minutes INTEGER,
|
||||
vigorous_minutes INTEGER,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS daily_resting_hr (
|
||||
calendar_date TEXT PRIMARY KEY,
|
||||
resting_hr INTEGER,
|
||||
raw TEXT NOT NULL,
|
||||
fetched_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activity_fit_files (
|
||||
activity_id INTEGER PRIMARY KEY,
|
||||
fit_path TEXT NOT NULL,
|
||||
indexed_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activity_time_in_zone (
|
||||
activity_id INTEGER PRIMARY KEY,
|
||||
z1_s REAL,
|
||||
z2_s REAL,
|
||||
z3_s REAL,
|
||||
z4_s REAL,
|
||||
z5_s REAL,
|
||||
total_s REAL,
|
||||
source TEXT,
|
||||
computed_at TEXT NOT NULL,
|
||||
FOREIGN KEY (activity_id) REFERENCES activities(activity_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sync_state (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
def connect() -> sqlite3.Connection:
|
||||
DB_PATH.parent.mkdir(exist_ok=True)
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.execute("PRAGMA journal_mode = WAL")
|
||||
conn.execute("PRAGMA foreign_keys = ON")
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.executescript(SCHEMA)
|
||||
return conn
|
||||
|
||||
|
||||
def set_state(conn: sqlite3.Connection, key: str, value: str) -> None:
|
||||
conn.execute(
|
||||
"INSERT INTO sync_state(key, value, updated_at) VALUES (?, ?, datetime('now')) "
|
||||
"ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at",
|
||||
(key, value),
|
||||
)
|
||||
|
||||
|
||||
def get_state(conn: sqlite3.Connection, key: str) -> str | None:
|
||||
row = conn.execute("SELECT value FROM sync_state WHERE key = ?", (key,)).fetchone()
|
||||
return row["value"] if row else None
|
||||
"""Back-compat shim — see openrun.db."""
|
||||
from openrun.db import SCHEMA, connect, get_state, set_state # noqa: F401
|
||||
|
||||
Reference in New Issue
Block a user