Raw Text Content QR Remove
sloth-turtle-pigeon



Export.xml --> health data walking JSON for webserver

import xml.etree.ElementTree as ET
from datetime import datetime
import json
from collections import defaultdict

def parse_apple_health_robust(xml_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()

    # 1. DEFINITION: Priorität der Quellen (von wichtig/präzise zu unwichtig/ungenau)
    # Passe die Namen genau so an, wie sie in der XML-Datei vorkommen.
    PRIORITY_SOURCES = ['Zepp', 'Strava', 'Herr Montag']

    # 2. DATEN SAMMELN: Gruppiere alle Einträge nach Tag und Stunde
    daily_buckets = defaultdict(lambda: defaultdict(dict))

    for record in root.findall('Record'):
        if record.get('type') == 'HKQuantityTypeIdentifierDistanceWalkingRunning':
            source = record.get('sourceName', '').strip()
            unit = record.get('unit', '').lower()
            try:
                raw_value = float(record.get('value', 0))
            except ValueError:
                continue

            # Umrechnung in Kilometer
            value_km = raw_value
            if unit == 'mi':
                value_km = raw_value * 1.60934
            elif unit == 'm':
                value_km = raw_value / 1000

            # Datum verarbeiten
            date_str = record.get('startDate') or record.get('creationDate', '')
            if not date_str:
                continue
            try:
                date_str_clean = date_str.replace('Z', '+00:00')
                date_obj = datetime.fromisoformat(date_str_clean)
            except ValueError:
                continue

            day_key = date_obj.strftime('%Y-%m-%d')
            # Runde auf die volle Stunde, um Einträge derselben Aktivität zu gruppieren
            hour_key = date_obj.replace(minute=0, second=0, microsecond=0)

            # 3. DEDUPLIZIERUNG: Nur die Quelle mit höchster Priorität für diese Stunde behalten
            # Finde den Index der Quelle in der Prioritätenliste
            current_priority = len(PRIORITY_SOURCES)  # Standard: niedrigste Priorität
            for i, src in enumerate(PRIORITY_SOURCES):
                if src in source:
                    current_priority = i
                    break

            existing_entry = daily_buckets[day_key].get(hour_key)

            if not existing_entry or current_priority < existing_entry['priority']:
                daily_buckets[day_key][hour_key] = {
                    'value_km': value_km,
                    'source': source,
                    'priority': current_priority
                }

    # 4. SUMMIERUNG: Die deduplizierten Werte pro Tag aufaddieren
    daily_totals_km = {}
    for day, hours in daily_buckets.items():
        daily_totals_km[day] = round(sum(entry['value_km'] for entry in hours.values()), 2)  # Auf 2 Nachkommastellen runden

    print(f"[Info] Deduplizierung abgeschlossen. Verarbeitete Tage: {len(daily_totals_km)}")
    return daily_totals_km


# ==================== HAUPTPROGRAMM ====================
if __name__ == "__main__":
    print("Starte Analyse der Apple Health Daten...")
    
    # Pfad zur XML-Datei (im gleichen Verzeichnis wie das Skript)
    xml_file = 'Export.xml'
    
    # Daten analysieren und deduplizieren
    cleaned_data = parse_apple_health_robust(xml_file)
    
    # Ergebnisse speichern
    output_file = 'walking_data_cleaned.json'
    with open(output_file, 'w') as f:
        json.dump(cleaned_data, f, indent=2, sort_keys=True)
    
    print(f"✅ Bereinigte Daten wurden in '{output_file}' gespeichert.")
    
    # Zeige den Wert für den 18.01.2026 an
    target_date = "2026-01-18"
    if target_date in cleaned_data:
        print(f"\n📊 Distanz für {target_date}: {cleaned_data[target_date]} km")
    else:
        print(f"\nℹ️  Keine Daten für {target_date} gefunden.")

Read 13 times, last 108 minutes ago


WE LOVE YOU