diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/NativeFITMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/NativeFITMessage.java index 814c57f7f0..68db0f4243 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/NativeFITMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/NativeFITMessage.java @@ -2064,6 +2064,17 @@ public class NativeFITMessage { new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP) )); + public static NativeFITMessage SLEEP_DISRUPTION_SEVERITY_PERIOD = new NativeFITMessage(470, "SLEEP_DISRUPTION_SEVERITY_PERIOD", Arrays.asList( + new FieldDefinitionPrimitive(0, BaseType.ENUM, "severity"), + new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP), + new FieldDefinitionPrimitive(254, BaseType.UINT16, "message_index") + )); + + public static NativeFITMessage SLEEP_DISRUPTION_OVERNIGHT_SEVERITY = new NativeFITMessage(471, "SLEEP_DISRUPTION_OVERNIGHT_SEVERITY", Arrays.asList( + new FieldDefinitionPrimitive(0, BaseType.ENUM, "severity"), + new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP) + )); + public static Map KNOWN_MESSAGES = new HashMap<>() {{ put(0, FILE_ID); put(1, CAPABILITIES); @@ -2211,6 +2222,8 @@ public class NativeFITMessage { put(403, ENDURANCE_SCORE); put(409, HSA_WRIST_TEMPERATURE_DATA); put(412, NAP); + put(470, SLEEP_DISRUPTION_SEVERITY_PERIOD); + put(471, SLEEP_DISRUPTION_OVERNIGHT_SEVERITY); }}; private final int number; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitRecordDataFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitRecordDataFactory.java index ee6b90dc41..e2a3d882da 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitRecordDataFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitRecordDataFactory.java @@ -177,6 +177,8 @@ public class FitRecordDataFactory { case 403 -> new FitEnduranceScore(recordDefinition, recordHeader); case 409 -> new FitHsaWristTemperatureData(recordDefinition, recordHeader); case 412 -> new FitNap(recordDefinition, recordHeader); + case 470 -> new FitSleepDisruptionSeverityPeriod(recordDefinition, recordHeader); + case 471 -> new FitSleepDisruptionOvernightSeverity(recordDefinition, recordHeader); default -> new RecordData(recordDefinition, recordHeader); }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionOvernightSeverity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionOvernightSeverity.java new file mode 100644 index 0000000000..1473c98c2a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionOvernightSeverity.java @@ -0,0 +1,80 @@ +/* Copyright (C) 2026 Freeyourgadget + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages; + +import androidx.annotation.Nullable; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitRecordDataBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordData; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordDefinition; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordHeader; + +/** + * WARNING: This class was auto-generated, please avoid modifying it directly. + * See {@link nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.codegen.FitCodeGen} + * + * @noinspection unused + */ +public class FitSleepDisruptionOvernightSeverity extends RecordData { + public FitSleepDisruptionOvernightSeverity(final RecordDefinition recordDefinition, final RecordHeader recordHeader) { + super(recordDefinition, recordHeader); + + final int nativeNumber = recordDefinition.getNativeFITMessage().getNumber(); + if (nativeNumber != 471) { + throw new IllegalArgumentException("FitSleepDisruptionOvernightSeverity expects native messages of " + 471 + ", got " + nativeNumber); + } + } + + @Nullable + public Integer getSeverity() { + return getFieldByNumber(0, Integer.class); + } + + @Nullable + public Long getTimestamp() { + return getFieldByNumber(253, Long.class); + } + + /** + * @noinspection unused + */ + public static class Builder extends FitRecordDataBuilder { + public Builder() { + super(471); + } + + public Builder setSeverity(final Integer value) { + setFieldByNumber(0, value); + return this; + } + + public Builder setTimestamp(final Long value) { + setFieldByNumber(253, value); + return this; + } + + @Override + public FitSleepDisruptionOvernightSeverity build() { + return (FitSleepDisruptionOvernightSeverity) super.build(); + } + + @Override + public FitSleepDisruptionOvernightSeverity build(final int localMessageType) { + return (FitSleepDisruptionOvernightSeverity) super.build(localMessageType); + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionSeverityPeriod.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionSeverityPeriod.java new file mode 100644 index 0000000000..028409a2f7 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSleepDisruptionSeverityPeriod.java @@ -0,0 +1,90 @@ +/* Copyright (C) 2026 Freeyourgadget + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages; + +import androidx.annotation.Nullable; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitRecordDataBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordData; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordDefinition; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.RecordHeader; + +/** + * WARNING: This class was auto-generated, please avoid modifying it directly. + * See {@link nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.codegen.FitCodeGen} + * + * @noinspection unused + */ +public class FitSleepDisruptionSeverityPeriod extends RecordData { + public FitSleepDisruptionSeverityPeriod(final RecordDefinition recordDefinition, final RecordHeader recordHeader) { + super(recordDefinition, recordHeader); + + final int nativeNumber = recordDefinition.getNativeFITMessage().getNumber(); + if (nativeNumber != 470) { + throw new IllegalArgumentException("FitSleepDisruptionSeverityPeriod expects native messages of " + 470 + ", got " + nativeNumber); + } + } + + @Nullable + public Integer getSeverity() { + return getFieldByNumber(0, Integer.class); + } + + @Nullable + public Long getTimestamp() { + return getFieldByNumber(253, Long.class); + } + + @Nullable + public Integer getMessageIndex() { + return getFieldByNumber(254, Integer.class); + } + + /** + * @noinspection unused + */ + public static class Builder extends FitRecordDataBuilder { + public Builder() { + super(470); + } + + public Builder setSeverity(final Integer value) { + setFieldByNumber(0, value); + return this; + } + + public Builder setTimestamp(final Long value) { + setFieldByNumber(253, value); + return this; + } + + public Builder setMessageIndex(final Integer value) { + setFieldByNumber(254, value); + return this; + } + + @Override + public FitSleepDisruptionSeverityPeriod build() { + return (FitSleepDisruptionSeverityPeriod) super.build(); + } + + @Override + public FitSleepDisruptionSeverityPeriod build(final int localMessageType) { + return (FitSleepDisruptionSeverityPeriod) super.build(localMessageType); + } + } +} diff --git a/app/src/test/resources/TestFitMessageTypeParsing.fit b/app/src/test/resources/TestFitMessageTypeParsing.fit index 2899f18f54..4f65740ec6 100644 Binary files a/app/src/test/resources/TestFitMessageTypeParsing.fit and b/app/src/test/resources/TestFitMessageTypeParsing.fit differ diff --git a/app/src/test/resources/TestFitMessageTypeParsing.txt b/app/src/test/resources/TestFitMessageTypeParsing.txt index 6f999b42aa..723460b1d8 100644 --- a/app/src/test/resources/TestFitMessageTypeParsing.txt +++ b/app/src/test/resources/TestFitMessageTypeParsing.txt @@ -12,7 +12,7 @@ FitMetZone{high_bpm=1, calories=1.0, fat_calories=1.0, message_index=1}, FitSport{sport=1, sub_sport=1, name=a}, FitTrainingSettings{target_distance=1.0, target_speed=1.0, target_time=1, precise_target_speed=1.0}, FitGoals{sport=1, sub_sport=1, start_date=1127433599, end_date=1127433599, type=distance, value=1, repeat=1, target_value=1, recurrence=1, recurrence_value=1, enabled=1, source=community, message_index=1}, -FitSession{2025-09-21 23:59:59.000, event=3, event_type=1, start_time=1127433599, start_latitude=8.381903171539307E-8, start_longitude=8.381903171539307E-8, sport=1, sub_sport=1, total_elapsed_time=1000, total_timer_time=1000, total_distance=100, total_cycles=1, total_calories=1, total_fat_calories=1, avg_speed=1.0, max_speed=1.0, average_heart_rate=1, max_heart_rate=1, avg_cadence=1, max_cadence=1, avg_power=1, max_power=1, total_ascent=1, total_descent=1, total_training_effect=1.0, first_lap_index=1, num_laps=1, event_group=1, trigger=1, nec_latitude=8.381903171539307E-8, nec_longitude=8.381903171539307E-8, swc_latitude=8.381903171539307E-8, swc_longitude=8.381903171539307E-8, num_lengths=1, normalized_power=1, training_stress_score=1.0, intensity_factor=1.0, left_right_balance=1, end_latitude=8.381903171539307E-8, end_longitude=8.381903171539307E-8, avg_stroke_count=10, avg_stroke_distance=1.0, swim_stroke=1, pool_length=1.0, threshold_power=1, pool_length_unit=1, num_active_lengths=1, total_work=1, avg_altitude=1.0, max_altitude=1.0, gps_accuracy=1, avg_grade=1.0, avg_pos_grade=1.0, avg_neg_grade=1.0, max_pos_grade=1.0, max_neg_grade=1.0, avg_temperature=1, max_temperature=1, total_moving_time=1.0, avg_pos_vertical_speed=1.0, avg_neg_vertical_speed=1.0, max_pos_vertical_speed=1.0, max_neg_vertical_speed=1.0, min_heart_rate=1, time_in_hr_zone=[1.0,,4.2], time_in_speed_zone=[1.0,,4.2], time_in_cadence_zone=[1.0,,4.2], time_in_power_zone=[1.0,,4.2], avg_lap_time=1.0, best_lap_index=1, min_altitude=1.0, player_score=1, opponent_score=1, opponent_name=a, stroke_count=[1,,65534], zone_count=[1,,65534], max_ball_speed=1.0, avg_ball_speed=1.0, avg_vertical_oscillation=1.0, avg_stance_time_percent=1.0, avg_stance_time=1.0, avg_fractional_cadence=1.0, max_fractional_cadence=1.0, total_fractional_cycles=1.0, avg_total_hemoglobin_conc=[1.0,,4.2], min_total_hemoglobin_conc=[1.0,,4.2], max_total_hemoglobin_conc=[1.0,,4.2], avg_saturated_hemoglobin_percent=[1.0,,4.2], min_saturated_hemoglobin_percent=[1.0,,4.2], max_saturated_hemoglobin_percent=[1.0,,4.2], avg_left_torque_effectiveness=1.0, avg_right_torque_effectiveness=1.0, avg_left_pedal_smoothness=1.0, avg_right_pedal_smoothness=1.0, avg_combined_pedal_smoothness=1.0, sport_profile_name=a, sport_index=1, stand_time=1000, stand_count=1, avg_left_pco=1, avg_right_pco=1, avg_left_power_phase=[1,,3], avg_left_power_phase_peak=[1,,3], avg_right_power_phase=[1,,3], avg_right_power_phase_peak=[1,,3], avg_power_position=[1,,65534], max_power_position=[1,,65534], avg_cadence_position=[1,,254], max_cadence_position=[1,,254], enhanced_avg_speed=1.0, enhanced_max_speed=1.0, enhanced_avg_altitude=1.0, enhanced_min_altitude=1.0, enhanced_max_altitude=1.0, avg_lev_motor_power=1, max_lev_motor_power=1, lev_battery_consumption=1.0, avg_vertical_ratio=1.0, avg_stance_time_balance=1.0, avg_step_length=1.0, total_anaerobic_training_effect=1.0, avg_vam=1.0, avg_depth=1.0, max_depth=1.0, surface_interval=1, start_cns=1, end_cns=1, start_n2=1, end_n2=1, avg_respiration_rate=1, max_respiration_rate=1, min_respiration_rate=1, min_temperature=1, o2_toxicity=1, dive_number=1, training_load_peak=1.0, enhanced_avg_respiration_rate=1.0, enhanced_max_respiration_rate=1.0, enhanced_min_respiration_rate=1.0, total_grit=1.0, total_flow=1.0, jump_count=1, avg_grit=1.0, avg_flow=1.0, workout_feel=1, workout_rpe=1, avg_spo2=1, avg_stress=1, hrv_sdrr=1, hrv_rmssd=1, total_fractional_ascent=1.0, total_fractional_descent=1.0, avg_core_temperature=1.0, min_core_temperature=1.0, max_core_temperature=1.0, timestamp=1758499199, message_index=1}, +FitSession{2025-09-21 23:59:59.000, event=3, event_type=1, start_time=1127433599, start_latitude=8.381903171539307E-8, start_longitude=8.381903171539307E-8, sport=1, sub_sport=1, total_elapsed_time=1000, total_timer_time=1000, total_distance=100, total_cycles=1, total_calories=1, total_fat_calories=1, avg_speed=1.0, max_speed=1.0, average_heart_rate=1, max_heart_rate=1, avg_cadence=1, max_cadence=1, avg_power=1, max_power=1, total_ascent=1, total_descent=1, total_training_effect=1.0, first_lap_index=1, num_laps=1, event_group=1, trigger=1, nec_latitude=8.381903171539307E-8, nec_longitude=8.381903171539307E-8, swc_latitude=8.381903171539307E-8, swc_longitude=8.381903171539307E-8, num_lengths=1, normalized_power=1, training_stress_score=1.0, intensity_factor=1.0, left_right_balance=1, end_latitude=8.381903171539307E-8, end_longitude=8.381903171539307E-8, avg_stroke_count=10, avg_stroke_distance=1.0, swim_stroke=1, pool_length=1.0, threshold_power=1, pool_length_unit=1, num_active_lengths=1, total_work=1, avg_altitude=1.0, max_altitude=1.0, gps_accuracy=1, avg_grade=1.0, avg_pos_grade=1.0, avg_neg_grade=1.0, max_pos_grade=1.0, max_neg_grade=1.0, avg_temperature=1, max_temperature=1, total_moving_time=1.0, avg_pos_vertical_speed=1.0, avg_neg_vertical_speed=1.0, max_pos_vertical_speed=1.0, max_neg_vertical_speed=1.0, min_heart_rate=1, time_in_hr_zone=[1.0,,4.2], time_in_speed_zone=[1.0,,4.2], time_in_cadence_zone=[1.0,,4.2], time_in_power_zone=[1.0,,4.2], avg_lap_time=1.0, best_lap_index=1, min_altitude=1.0, player_score=1, opponent_score=1, opponent_name=a, stroke_count=[1,,65534], zone_count=[1,,65534], max_ball_speed=1.0, avg_ball_speed=1.0, avg_vertical_oscillation=1.0, avg_stance_time_percent=1.0, avg_stance_time=1.0, avg_fractional_cadence=1.0, max_fractional_cadence=1.0, total_fractional_cycles=1.0, avg_total_hemoglobin_conc=[1.0,,4.2], min_total_hemoglobin_conc=[1.0,,4.2], max_total_hemoglobin_conc=[1.0,,4.2], avg_saturated_hemoglobin_percent=[1.0,,4.2], min_saturated_hemoglobin_percent=[1.0,,4.2], max_saturated_hemoglobin_percent=[1.0,,4.2], avg_left_torque_effectiveness=1.0, avg_right_torque_effectiveness=1.0, avg_left_pedal_smoothness=1.0, avg_right_pedal_smoothness=1.0, avg_combined_pedal_smoothness=1.0, sport_profile_name=a, sport_index=1, stand_time=1000, stand_count=1, avg_left_pco=1, avg_right_pco=1, avg_left_power_phase=[1,,3], avg_left_power_phase_peak=[1,,3], avg_right_power_phase=[1,,3], avg_right_power_phase_peak=[1,,3], avg_power_position=[1,,65534], max_power_position=[1,,65534], avg_cadence_position=[1,,254], max_cadence_position=[1,,254], enhanced_avg_speed=1.0, enhanced_max_speed=1.0, enhanced_avg_altitude=1.0, enhanced_min_altitude=1.0, enhanced_max_altitude=1.0, avg_lev_motor_power=1, max_lev_motor_power=1, lev_battery_consumption=1.0, avg_vertical_ratio=1.0, avg_stance_time_balance=1.0, avg_step_length=1.0, total_anaerobic_training_effect=1.0, avg_vam=1.0, avg_depth=1.0, max_depth=1.0, surface_interval=1, start_cns=1, end_cns=1, start_n2=1, end_n2=1, avg_respiration_rate=1, max_respiration_rate=1, min_respiration_rate=1, min_temperature=1, o2_toxicity=1, dive_number=1, training_load_peak=1.0, enhanced_avg_respiration_rate=1.0, enhanced_max_respiration_rate=1.0, enhanced_min_respiration_rate=1.0, total_grit=1.0, total_flow=1.0, jump_count=1, avg_grit=1.0, avg_flow=1.0, workout_feel=1, workout_rpe=1, avg_spo2=1, avg_stress=1, resting_calories=1, hrv_sdrr=1, hrv_rmssd=1, total_fractional_ascent=1.0, total_fractional_descent=1.0, avg_core_temperature=1.0, min_core_temperature=1.0, max_core_temperature=1.0, timestamp=1758499199, message_index=1}, FitLap{2025-09-21 23:59:59.000, event=3, event_type=1, start_time=1127433599, start_lat=8.381903171539307E-8, start_long=8.381903171539307E-8, end_lat=8.381903171539307E-8, end_long=8.381903171539307E-8, total_elapsed_time=1.0, total_timer_time=1.0, total_distance=1.0, total_cycles=1, total_calories=1, total_fat_calories=1, avg_speed=1.0, max_speed=1.0, avg_heart_rate=1, max_heart_rate=1, avg_cadence=1, max_cadence=1, avg_power=1, max_power=1, total_ascent=1, total_descent=1, intensity=1, lap_trigger=1, sport=1, event_group=1, num_lengths=1, normalized_power=1, left_right_balance=1, first_length_index=1, avg_stroke_distance=100, swim_style=BACKSTROKE, sub_sport=1, num_active_lengths=1, total_work=1, avg_altitude=1.0, max_altitude=1.0, gps_accuracy=1, avg_grade=1.0, avg_pos_grade=1.0, avg_neg_grade=1.0, max_pos_grade=1.0, max_neg_grade=1.0, avg_temperature=1, max_temperature=1, total_moving_time=1.0, avg_pos_vertical_speed=1.0, avg_neg_vertical_speed=1.0, max_pos_vertical_speed=1.0, max_neg_vertical_speed=1.0, time_in_hr_zone=[1.0,,4.2], time_in_speed_zone=[1.0,,4.2], time_in_cadence_zone=[1.0,,4.2], time_in_power_zone=[1.0,,4.2], repetition_num=1, min_altitude=1.0, min_heart_rate=1, wkt_step_index=1, opponent_score=1, stroke_count=[1,,65534], zone_count=[1,,65534], avg_vertical_oscillation=1.0, avg_stance_time_percent=1.0, avg_stance_time=1.0, avg_fractional_cadence=1.0, max_fractional_cadence=1.0, total_fractional_cycles=1.0, player_score=1, avg_total_hemoglobin_conc=[1.0,,4.2], min_total_hemoglobin_conc=[1.0,,4.2], max_total_hemoglobin_conc=[1.0,,4.2], avg_saturated_hemoglobin_percent=[1.0,,4.2], min_saturated_hemoglobin_percent=[1.0,,4.2], max_saturated_hemoglobin_percent=[1.0,,4.2], avg_left_torque_effectiveness=1.0, avg_right_torque_effectiveness=1.0, avg_left_pedal_smoothness=1.0, avg_right_pedal_smoothness=1.0, avg_combined_pedal_smoothness=1.0, time_standing=1.0, stand_count=1, avg_left_pco=1, avg_right_pco=1, avg_left_power_phase=[1,,3], avg_left_power_phase_peak=[1,,3], avg_right_power_phase=[1,,3], avg_right_power_phase_peak=[1,,3], avg_power_position=[1,,65534], max_power_position=[1,,65534], avg_cadence_position=[1,,254], max_cadence_position=[1,,254], enhanced_avg_speed=1.0, enhanced_max_speed=1.0, enhanced_avg_altitude=1.0, enhanced_min_altitude=1.0, enhanced_max_altitude=1.0, avg_lev_motor_power=1, max_lev_motor_power=1, lev_battery_consumption=1.0, avg_vertical_ratio=1.0, avg_stance_time_balance=1.0, avg_step_length=1.0, avg_vam=1.0, avg_depth=1.0, max_depth=1.0, min_temperature=1, enhanced_avg_respiration_rate=1.0, enhanced_max_respiration_rate=1.0, avg_respiration_rate=1, max_respiration_rate=1, total_grit=1.0, total_flow=1.0, jump_count=1, avg_grit=1.0, avg_flow=1.0, total_fractional_ascent=1.0, total_fractional_descent=1.0, avg_core_temperature=1.0, min_core_temperature=1.0, max_core_temperature=1.0, timestamp=1758499199, message_index=1}, FitRecord{2025-09-21 23:59:59.000, latitude=8.381903171539307E-8, longitude=8.381903171539307E-8, altitude=1.0, heart_rate=1, cadence=1, distance=1.0, speed=1.0, power=1, compressed_speed_distance=[1,,254], grade=1.0, resistance=1, time_from_course=1.0, cycle_length=1.0, temperature=1, speed_1s=[1.0,,4.1875], cycles=1, total_cycles=1, compressed_accumulated_power=1, accumulated_power=1, left_right_balance=1, gps_accuracy=1, vertical_speed=1.0, calories=1, oscillation=1.0, stance_time_percent=1.0, stance_time=1.0, activity=1, left_torque_effectiveness=1.0, right_torque_effectiveness=1.0, left_pedal_smoothness=1.0, right_pedal_smoothness=1.0, combined_pedal_smoothness=1.0, time128=1.0, stroke_type=1, zone=1, ball_speed=1.0, cadence256=1.0, fractional_cadence=1.0, avg_total_hemoglobin_conc=1.0, min_total_hemoglobin_conc=1.0, max_total_hemoglobin_conc=1.0, avg_saturated_hemoglobin_percent=1.0, min_saturated_hemoglobin_percent=1.0, max_saturated_hemoglobin_percent=1.0, device_index=1, left_pco=1, right_pco=1, left_power_phase=[1,,3], left_power_phase_peak=[1,,3], right_power_phase=[1,,3], right_power_phase_peak=[1,,3], enhanced_speed=1.0, enhanced_altitude=1.0, battery_soc=1.0, motor_power=1, vertical_ratio=1.0, stance_time_balance=1.0, step_length=1.0, cycle_length16=1.0, absolute_pressure=1, depth=1.0, next_stop_depth=1.0, next_stop_time=1, time_to_surface=1, ndl_time=1, cns_load=1, n2_load=1, respiration_rate=1, enhanced_respiration_rate=1.0, grit=1.0, flow=1.0, current_stress=1.0, ebike_travel_rang=1, ebike_battery_level=1, ebike_assist_mode=1, ebike_assist_level_percent=1, air_time_remaining=1, pressure_sac=1.0, volume_sac=1.0, rmv=1.0, ascent_rate=1.0, po2=1.0, core_temperature=1.0, timestamp=1758499199}, FitEvent{2025-09-21 23:59:59.000, event=3, event_type=1, data16=1, data=1, event_group=1, score=1, opponent_score=1, front_gear_num=1, front_gear=1, rear_gear_num=1, rear_gear=1, device_index=1, activity_type=1, start_timestamp=1127433599, radar_threat_level_max=1, radar_threat_count=1, radar_threat_avg_approach_speed=1.0, radar_threat_max_approach_speed=1.0, timestamp=1758499199}, @@ -119,6 +119,8 @@ FitHsaConfigurationData{2025-09-21 23:59:59.000, data=[1,,254], data_size=1, tim FitDiveApneaAlarm{2025-09-21 23:59:59.000, depth=1.0, time=1, enabled=true, alarm_type=1, sound=1, dive_types=[1,,0], id=1, popup_enabled=true, trigger_on_descent=true, trigger_on_ascent=true, repeating=true, speed=1.0, message_index=1}, FitSkinTempOvernight{2025-09-21 23:59:59.000, local_timestamp=1, average_deviation=1.0, average_7_day_deviation=1.0, nightly_value=1.0, timestamp=1758499199}, FitHsaWristTemperatureData{2025-09-21 23:59:59.000, processing_interval=1, value=[1.0,,4.2], timestamp=1758499199}, +FitSleepDisruptionSeverityPeriod{2025-09-21 23:59:59.000, severity=1, timestamp=1758499199, message_index=1}, +FitSleepDisruptionOvernightSeverity{2025-09-21 23:59:59.000, severity=1, timestamp=1758499199}, FitLap{2025-09-21 23:59:59.000, event=11, event_type=3, start_time=1127433599, time_in_hr_zone=1.0, time_in_speed_zone=[1.0,2.0], time_in_cadence_zone=[1.0,0.0,3.0], avg_total_hemoglobin_conc=1.0, min_total_hemoglobin_conc=[1.0,2.0], max_total_hemoglobin_conc=[1.0,0.0,3.0], lev_battery_consumption=20.0, timestamp=1758499199, message_index=2}, FitSegmentFile{2025-09-21 23:59:59.000, leader_activity_id_string=a, message_index=0}, FitSegmentFile{2025-09-21 23:59:59.000, leader_activity_id_string=a, message_index=1},