Add support for swimming lengths in FIT file parsing

Introduces parsing and handling of 'length' frames from FIT files, storing their data in a new 'lengths' array. Updates relevant functions to include and utilize 'lengths', particularly for more accurate swimming pace calculations based on active lengths.
This commit is contained in:
João Vitória Silva
2025-12-02 17:23:21 +00:00
parent 7b9b393c7f
commit 1b7c7da4de

View File

@@ -92,6 +92,7 @@ def create_activity_objects(
session_record["session"]["total_timer_time"],
session_record["session"]["activity_type"],
session_record["split_summary"],
session_record["lengths"],
)
if activity_type != 3 and activity_type != 7:
@@ -303,6 +304,7 @@ def split_records_by_activity(parsed_data: dict) -> dict:
"split_summary": parsed_data["split_summary"],
"workout_steps": parsed_data["workout_steps"],
"sets": parsed_data["sets"],
"lengths": parsed_data["lengths"],
}
# Only parse arrays if the respective flag is set
@@ -465,6 +467,9 @@ def parse_fit_file(
# Array to store exercises titles
exercises_titles = []
# Array to store lengths
lengths = []
# Initialize variables to store previous latitude and longitude
prev_latitude, prev_longitude = None, None
@@ -713,6 +718,9 @@ def parse_fit_file(
time_offset = parse_frame_device_settings(frame)
time_offset = interpret_time_offset(time_offset)
if frame.name == "length":
lengths.append(parse_frame_length(frame))
# Check if exercises titles is not none
if exercises_titles:
activity_exercise_titles_crud.create_activity_exercise_titles(
@@ -742,6 +750,7 @@ def parse_fit_file(
"split_summary": split_summary,
"sets": sets,
"workout_steps": workout_steps,
"lengths": lengths,
}
except HTTPException as http_err:
raise http_err
@@ -1047,6 +1056,20 @@ def parse_frame_device_settings(frame):
return get_value_from_frame(frame, "time_offset")
def parse_frame_length(frame):
return {
"message_index": get_value_from_frame(frame, "message_index"),
"start_time": get_value_from_frame(frame, "start_time"),
"total_elapsed_time": get_value_from_frame(frame, "total_elapsed_time"),
"total_timer_time": get_value_from_frame(frame, "total_timer_time"),
"total_strokes": get_value_from_frame(frame, "total_strokes"),
"avg_speed": get_value_from_frame(frame, "avg_speed"),
"swim_stroke": get_value_from_frame(frame, "swim_stroke"),
"avg_swimming_cadence": get_value_from_frame(frame, "avg_swimming_cadence"),
"length_type": get_value_from_frame(frame, "length_type"),
}
def interpret_time_offset(raw_offset):
# Check for two's complement representation (values > 2^31)
if raw_offset != 0 and raw_offset is not None:
@@ -1085,10 +1108,20 @@ def append_if_not_none(waypoint_list, time, value, key):
waypoint_list.append({"time": time, key: value})
def calculate_pace(distance, total_timer_time, activity_type, split_summary):
def calculate_pace(distance, total_timer_time, activity_type, split_summary, lengths):
if distance:
if activity_type != "lap_swimming" or not split_summary:
if activity_type != "lap_swimming":
return total_timer_time, total_timer_time / distance
if activity_type == "lap_swimming" and lengths:
core_logger.print_to_log("Calculating swimming pace based on lengths")
# Swimming pace calculation based on lengths
time_active = 0
for length in lengths:
if length["length_type"] == "active":
time_active += length["total_timer_time"]
return time_active, time_active / distance
# Swimming pace calculation based on split summary
time_active = 0
for split in split_summary:
if split["split_type"] != 4: