ETL-Update: Excel- & Coros-Gesundheitsdaten nahtlos in meine BigQuery-Pipeline integrieren
Motivation: Mehr Coros-Daten, ein Format mehr
Nach FIT-Dateien (Aktivitäten) und CSV-Exports (tägliche Metriken) kam der nächste logische Schritt:
Excel-Exports (.xlsx) von Coros, insbesondere für tägliche Gesundheitsdaten wie Herzfrequenz, HRV und Schlaf.
Das Ziel war klar:
- kein separater Import-Flow
- keine manuelle Schema-Anpassung
- keine Dashboard-Brüche
- weiterhin idempotent & automatisiert
Kurz: Ein weiteres Datenformat sollte sich nahtlos in die bestehende Pipeline einfügen.
1. Modell-Erweiterung: Mehr Herzfrequenz, gleiche API
Im zentralen Datenmodell (src/config.py) wurde die bestehende metrics-Tabelle erweitert, um die Excel-Daten vollständig abzubilden.
Neu hinzugekommen sind u.a.:
Heart Rate
resting_heart_ratemin_heart_ratemax_heart_rateavg_heart_rate
HRV
hrv_avg
Wichtig war mir dabei Rückwärtskompatibilität:
Das bestehende Feld pulse wird weiterhin mit dem Average Heart Rate befüllt, damit:
- bestehende Dashboards unverändert weiterlaufen
- keine API-Verträge brechen
- neue Daten sofort sichtbar werden
➡️ Neue Daten, keine Migration-Schmerzen.
2. Automatisches Schema-Update in BigQuery
Mit wachsendem Datenmodell wird eines schnell lästig:
manuelle Schema-Updates in BigQuery.
Deshalb wurde der BigQueryClient (src/bigquery_client.py) erweitert:
- Beim Start der Pipeline wird geprüft:
- Welche Spalten existieren bereits?
- Welche fehlen im Vergleich zum aktuellen Modell?
- Fehlende Spalten werden automatisch per
ALTER TABLE ADD COLUMNergänzt.
Das bedeutet konkret:
- kein Löschen von Tabellen
- kein Re-Deploy
- kein Risiko für bestehende Daten
➡️ Schema-Evolution als Teil der Pipeline, nicht als manueller Schritt.
3. Neuer Excel-Parser (src/excel_parser.py)
Für die .xlsx-Exports wurde ein dedizierter Parser implementiert.
Validierung
Der Parser erkennt automatisch, ob eine Excel-Datei das erwartete Format besitzt, z.B.:
User IDDate- Schlaf- und HR-Spalten
Fehlerhafte oder fremde Excel-Dateien werden sauber abgelehnt.
Einheiten-Konversion
Ein klassisches Problem:
Coros liefert viele Schlafwerte in Minuten, das interne Modell arbeitet jedoch mit Stunden.
Der Parser übernimmt automatisch:
time_in_deep_sleeptime_in_light_sleeptime_awakesleep_hours
➡️ Einheitlich, unabhängig von der Datenquelle.
Header-Mapping
Die Excel-Header (teils deutsch/englisch gemischt) werden sauber auf technische Feldnamen gemappt, sodass:
- CSV
- Excel
- zukünftige Exporte
alle auf das gleiche BigQuery-Schema laufen.
4. Integration in die bestehende Pipeline
Die Pipeline selbst (src/etl_pipeline.py) musste nur minimal angepasst werden.
Dateierkennung
Der File-Scanner (find_unprocessed_files) sucht nun explizit nach:
.xlsx.XLSX
Dynamische Verarbeitung
Je nach Dateityp wird automatisch gewählt:
- FIT → FIT-Parser
- CSV → CSV-Parser
- XLSX → Excel-Parser
Idempotenz bleibt erhalten
Wie bei allen anderen Datenquellen gilt weiterhin:
- SHA-256 Hash pro Datei / Datensatz
- Prüfung gegen BigQuery
- kein doppeltes Laden – selbst bei mehrfachen Uploads
➡️ Excel-Daten sind first-class citizens der Pipeline.
5. Neue Abhängigkeiten
Für die Excel-Verarbeitung wurden ergänzt:
pandasopenpyxl
Beides etabliert, stabil und gut wartbar – keine exotischen Abhängigkeiten.
Status: Eine Pipeline für alle Sportdaten
Mit diesem Update verarbeitet die Pipeline nun in einem Lauf:
- FIT-Dateien → Aktivitäten & Zeitreihen
- CSV-Dateien → tägliche Metriken
- Excel-Dateien (.xlsx) → Coros-Gesundheitsdaten
Fazit
Dieses Update war weniger „Feature“, mehr Architektur-Test:
Wie erweiterbar ist meine Pipeline wirklich?
Die Antwort: sehr.
- Neues Format → kein Rewrite
- Neues Schema → kein manueller Eingriff
- Neue Daten → sofort sichtbar
Genau so soll sich ein privates Data-Analytics-Projekt anfühlen: kontrolliert wachsend, nicht fragil.