Garmin: export FIT laps as GPX track segments

This commit is contained in:
Thomas Kuehne
2026-04-07 00:14:44 +02:00
committed by José Rebelo
parent 68aa74bc39
commit fc6dcc793b
2 changed files with 40 additions and 10 deletions
@@ -1,4 +1,4 @@
/* Copyright (C) 2026 José Rebelo
/* Copyright (C) 2026 José Rebelo, Thomas Kuehne
This file is part of Gadgetbridge.
@@ -24,12 +24,13 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Iterator;
import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FitFile;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.exception.FitParseException;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitLap;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitRecord;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@@ -58,14 +59,43 @@ public class FitActivityTrackProvider implements ActivityTrackProvider {
return null;
}
final List<ActivityPoint> activityPoints = fitFile.getRecords().stream()
.filter(r -> r instanceof FitRecord)
.map(r -> ((FitRecord) r).toActivityPoint())
.collect(Collectors.toList());
final ActivityTrack activityTrack = new ActivityTrack();
activityTrack.setName(summary.getName());
activityTrack.addTrackPoints(activityPoints);
final Iterator<FitRecord> records = fitFile.getRecords().stream()
.filter(r -> r instanceof FitRecord)
.map(r -> (FitRecord) r)
.iterator();
final Iterator<Long> lapStarts = fitFile.getRecords().stream()
.filter(record -> record instanceof FitLap)
.map(record -> (FitLap) record)
.filter(lap -> {
Integer event = lap.getEvent();
if (event != null && event != 9) {
return false;
}
Integer eventType = lap.getEventType();
return (eventType == null || eventType == 1);
})
.map(FitLap::getStartTime)
.filter(Objects::nonNull)
.iterator();
// skip first lap start
if(lapStarts.hasNext()){
lapStarts.next();
}
long nextLapStart = (lapStarts.hasNext() ? lapStarts.next() : Long.MAX_VALUE);
while (records.hasNext()) {
FitRecord record = records.next();
if (record.getComputedTimestamp() >= nextLapStart) {
activityTrack.startNewSegment();
nextLapStart = (lapStarts.hasNext() ? lapStarts.next() : Long.MAX_VALUE);
}
activityTrack.addTrackPoint(record.toActivityPoint());
}
return activityTrack;
}
@@ -389,7 +389,7 @@ public class NativeFITMessage {
public static NativeFITMessage LAP = new NativeFITMessage(19, "LAP", Arrays.asList(
new FieldDefinitionPrimitive(0, BaseType.ENUM, "event"), // 9 lap
new FieldDefinitionPrimitive(1, BaseType.ENUM, "event_type"), // 1 stop
new FieldDefinitionPrimitive(2, BaseType.UINT32, "start_time"),
new FieldDefinitionPrimitive(2, BaseType.UINT32, "start_time", FieldDefinitionFactory.FIELD.TIMESTAMP),
new FieldDefinitionPrimitive(3, BaseType.SINT32, "start_lat", FieldDefinitionFactory.FIELD.COORDINATE),
new FieldDefinitionPrimitive(4, BaseType.SINT32, "start_long", FieldDefinitionFactory.FIELD.COORDINATE),
new FieldDefinitionPrimitive(5, BaseType.SINT32, "end_lat", FieldDefinitionFactory.FIELD.COORDINATE),