Fix SDK field names - use camelCase throughout
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
FIT and GPX file parser using the official Garmin FIT Python SDK.
|
||||
Field names from the SDK are camelCase as per the SDK documentation.
|
||||
"""
|
||||
import math
|
||||
from datetime import datetime, timezone
|
||||
@@ -59,6 +60,7 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
merge_heart_rates=True,
|
||||
)
|
||||
|
||||
# SDK returns camelCase keys
|
||||
sessions = messages.get("session", [{}])
|
||||
session = sessions[0] if sessions else {}
|
||||
records = messages.get("record", [])
|
||||
@@ -73,12 +75,12 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
}
|
||||
sport_type = sport_map.get(sport, sport)
|
||||
|
||||
start_time = _ensure_utc(session.get("start_time"))
|
||||
start_time = _ensure_utc(session.get("startTime"))
|
||||
|
||||
coords = []
|
||||
for r in records:
|
||||
lat = r.get("position_lat")
|
||||
lon = r.get("position_long")
|
||||
lat = r.get("positionLat")
|
||||
lon = r.get("positionLong")
|
||||
if lat is not None and lon is not None:
|
||||
if -90 <= lat <= 90 and -180 <= lon <= 180:
|
||||
coords.append((lat, lon))
|
||||
@@ -89,8 +91,8 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
normalized_points = []
|
||||
for r in records:
|
||||
ts = _ensure_utc(r.get("timestamp"))
|
||||
lat = r.get("position_lat")
|
||||
lon = r.get("position_long")
|
||||
lat = r.get("positionLat")
|
||||
lon = r.get("positionLong")
|
||||
|
||||
if lat is not None and not (-90 <= lat <= 90):
|
||||
lat = None
|
||||
@@ -101,10 +103,10 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
"timestamp": ts.isoformat() if ts else None,
|
||||
"latitude": _safe_float(lat),
|
||||
"longitude": _safe_float(lon),
|
||||
"altitude_m": _safe_float(r.get("altitude") or r.get("enhanced_altitude")),
|
||||
"heart_rate": _safe_float(r.get("heart_rate")),
|
||||
"altitude_m": _safe_float(r.get("altitude") or r.get("enhancedAltitude")),
|
||||
"heart_rate": _safe_float(r.get("heartRate")),
|
||||
"cadence": _safe_float(r.get("cadence")),
|
||||
"speed_ms": _safe_float(r.get("speed") or r.get("enhanced_speed")),
|
||||
"speed_ms": _safe_float(r.get("speed") or r.get("enhancedSpeed")),
|
||||
"power": _safe_float(r.get("power")),
|
||||
"temperature_c": _safe_float(r.get("temperature")),
|
||||
"distance_m": _safe_float(r.get("distance")),
|
||||
@@ -112,16 +114,16 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
|
||||
normalized_laps = []
|
||||
for i, lap in enumerate(laps):
|
||||
ls = _ensure_utc(lap.get("start_time"))
|
||||
ls = _ensure_utc(lap.get("startTime"))
|
||||
normalized_laps.append({
|
||||
"lap_number": i + 1,
|
||||
"start_time": ls.isoformat() if ls else None,
|
||||
"duration_s": _safe_float(lap.get("total_elapsed_time")),
|
||||
"distance_m": _safe_float(lap.get("total_distance")),
|
||||
"avg_heart_rate": _safe_float(lap.get("avg_heart_rate")),
|
||||
"avg_cadence": _safe_float(lap.get("avg_cadence")),
|
||||
"avg_speed_ms": _safe_float(lap.get("avg_speed") or lap.get("enhanced_avg_speed")),
|
||||
"avg_power": _safe_float(lap.get("avg_power")),
|
||||
"duration_s": _safe_float(lap.get("totalElapsedTime")),
|
||||
"distance_m": _safe_float(lap.get("totalDistance")),
|
||||
"avg_heart_rate": _safe_float(lap.get("avgHeartRate")),
|
||||
"avg_cadence": _safe_float(lap.get("avgCadence")),
|
||||
"avg_speed_ms": _safe_float(lap.get("avgSpeed") or lap.get("enhancedAvgSpeed")),
|
||||
"avg_power": _safe_float(lap.get("avgPower")),
|
||||
})
|
||||
|
||||
name = sport_type.title()
|
||||
@@ -132,21 +134,21 @@ def parse_fit_file(filepath: str) -> dict:
|
||||
"name": name,
|
||||
"sport_type": sport_type,
|
||||
"start_time": start_time.isoformat() if start_time else None,
|
||||
"distance_m": _safe_float(session.get("total_distance")),
|
||||
"duration_s": _safe_float(session.get("total_elapsed_time")),
|
||||
"elevation_gain_m": _safe_float(session.get("total_ascent")),
|
||||
"elevation_loss_m": _safe_float(session.get("total_descent")),
|
||||
"avg_heart_rate": _safe_float(session.get("avg_heart_rate")),
|
||||
"max_heart_rate": _safe_float(session.get("max_heart_rate")),
|
||||
"avg_cadence": _safe_float(session.get("avg_cadence")),
|
||||
"avg_power": _safe_float(session.get("avg_power")),
|
||||
"normalized_power": _safe_float(session.get("normalized_power")),
|
||||
"avg_speed_ms": _safe_float(session.get("avg_speed") or session.get("enhanced_avg_speed")),
|
||||
"max_speed_ms": _safe_float(session.get("max_speed") or session.get("enhanced_max_speed")),
|
||||
"avg_temperature_c": _safe_float(session.get("avg_temperature")),
|
||||
"calories": _safe_float(session.get("total_calories")),
|
||||
"training_stress_score": _safe_float(session.get("training_stress_score")),
|
||||
"vo2max_estimate": _safe_float(session.get("total_training_effect")),
|
||||
"distance_m": _safe_float(session.get("totalDistance")),
|
||||
"duration_s": _safe_float(session.get("totalElapsedTime")),
|
||||
"elevation_gain_m": _safe_float(session.get("totalAscent")),
|
||||
"elevation_loss_m": _safe_float(session.get("totalDescent")),
|
||||
"avg_heart_rate": _safe_float(session.get("avgHeartRate")),
|
||||
"max_heart_rate": _safe_float(session.get("maxHeartRate")),
|
||||
"avg_cadence": _safe_float(session.get("avgCadence")),
|
||||
"avg_power": _safe_float(session.get("avgPower")),
|
||||
"normalized_power": _safe_float(session.get("normalizedPower")),
|
||||
"avg_speed_ms": _safe_float(session.get("avgSpeed") or session.get("enhancedAvgSpeed")),
|
||||
"max_speed_ms": _safe_float(session.get("maxSpeed") or session.get("enhancedMaxSpeed")),
|
||||
"avg_temperature_c": _safe_float(session.get("avgTemperature")),
|
||||
"calories": _safe_float(session.get("totalCalories")),
|
||||
"training_stress_score": _safe_float(session.get("trainingStressScore")),
|
||||
"vo2max_estimate": _safe_float(session.get("totalTrainingEffect")),
|
||||
"polyline": encoded_polyline,
|
||||
"bounding_box": bounding_box,
|
||||
"source_type": "fit",
|
||||
|
||||
Reference in New Issue
Block a user