GPXExporter: Include speed and cadence

This commit is contained in:
José Rebelo 2024-10-12 16:57:02 +01:00
parent bf7b6e2329
commit 6474a6092e
4 changed files with 45 additions and 27 deletions

View File

@ -45,12 +45,11 @@ public class GPXExporter implements ActivityTrackExporter {
private static final String NS_GPX_URI = "http://www.topografix.com/GPX/1/1"; private static final String NS_GPX_URI = "http://www.topografix.com/GPX/1/1";
private static final String NS_GPX_PREFIX = ""; private static final String NS_GPX_PREFIX = "";
private static final String NS_TRACKPOINT_EXTENSION = "gpxtpx"; private static final String NS_TRACKPOINT_EXTENSION = "gpxtpx";
private static final String NS_TRACKPOINT_EXTENSION_URI = "http://www.garmin.com/xmlschemas/TrackPointExtension/v1"; private static final String NS_TRACKPOINT_EXTENSION_URI = "https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd";
private static final String NS_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance"; private static final String NS_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
private static final String TOPOGRAFIX_NAMESPACE_XSD = "http://www.topografix.com/GPX/1/1/gpx.xsd"; private static final String TOPOGRAFIX_NAMESPACE_XSD = "http://www.topografix.com/GPX/1/1/gpx.xsd";
private static final String OPENTRACKS_PREFIX = "opentracks"; private static final String OPENTRACKS_PREFIX = "opentracks";
private static final String OPENTRACKS_NAMESPACE_URI = "http://opentracksapp.com/xmlschemas/v1"; private static final String OPENTRACKS_NAMESPACE_URI = "http://opentracksapp.com/xmlschemas/v1";
private static final String OPENTRACKS_NAMESPACE_XSD = "http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd";
private String creator; private String creator;
private boolean includeHeartRate = true; private boolean includeHeartRate = true;
@ -75,9 +74,7 @@ public class GPXExporter implements ActivityTrackExporter {
} else { } else {
ser.attribute(null, "creator", GBApplication.app().getNameAndVersion()); ser.attribute(null, "creator", GBApplication.app().getNameAndVersion());
} }
ser.attribute(NS_XSI_URI, "schemaLocation", NS_GPX_URI + " " ser.attribute(NS_XSI_URI, "schemaLocation",NS_GPX_URI + " " + TOPOGRAFIX_NAMESPACE_XSD);
+ TOPOGRAFIX_NAMESPACE_XSD + " "
+ OPENTRACKS_NAMESPACE_URI + " " + OPENTRACKS_NAMESPACE_XSD);
exportMetadata(ser, track); exportMetadata(ser, track);
exportTrack(ser, track); exportTrack(ser, track);
@ -146,10 +143,10 @@ public class GPXExporter implements ActivityTrackExporter {
} }
ser.startTag(NS_GPX_URI, "trkpt"); ser.startTag(NS_GPX_URI, "trkpt");
// lon and lat attributes do not have an explicit namespace // lon and lat attributes do not have an explicit namespace
ser.attribute(null, "lon", formatLocation(location.getLongitude())); ser.attribute(null, "lon", formatDouble(location.getLongitude()));
ser.attribute(null, "lat", formatLocation(location.getLatitude())); ser.attribute(null, "lat", formatDouble(location.getLatitude()));
if (location.getAltitude() != GPSCoordinate.UNKNOWN_ALTITUDE) { if (location.getAltitude() != GPSCoordinate.UNKNOWN_ALTITUDE) {
ser.startTag(NS_GPX_URI, "ele").text(formatLocation(location.getAltitude())).endTag(NS_GPX_URI, "ele"); ser.startTag(NS_GPX_URI, "ele").text(formatDouble(location.getAltitude())).endTag(NS_GPX_URI, "ele");
} }
ser.startTag(NS_GPX_URI, "time").text(DateTimeUtils.formatIso8601UTC(point.getTime())).endTag(NS_GPX_URI, "time"); ser.startTag(NS_GPX_URI, "time").text(DateTimeUtils.formatIso8601UTC(point.getTime())).endTag(NS_GPX_URI, "time");
String description = point.getDescription(); String description = point.getDescription();
@ -170,27 +167,37 @@ public class GPXExporter implements ActivityTrackExporter {
return; return;
} }
float speed = point.getSpeed();
int cadence = point.getCadence();
int hr = point.getHeartRate(); int hr = point.getHeartRate();
if (!HeartRateUtils.getInstance().isValidHeartRateValue(hr)) { if (!HeartRateUtils.getInstance().isValidHeartRateValue(hr) && includeHeartRateOfNearestSample) {
if (!includeHeartRateOfNearestSample) {
return;
}
ActivityPoint closestPointItem = findClosestSensibleActivityPoint(point.getTime(), trackPoints); ActivityPoint closestPointItem = findClosestSensibleActivityPoint(point.getTime(), trackPoints);
if(closestPointItem == null) { if (closestPointItem != null) {
return; hr = closestPointItem.getHeartRate();
} }
hr = closestPointItem.getHeartRate();
if (!HeartRateUtils.getInstance().isValidHeartRateValue(hr)) {
return;
} }
boolean exportHr = HeartRateUtils.getInstance().isValidHeartRateValue(hr) && includeHeartRate;
if (!exportHr && speed < 0 && cadence < 0) {
// No valid data to export in extensions
return;
} }
ser.startTag(NS_GPX_URI, "extensions"); ser.startTag(NS_GPX_URI, "extensions");
ser.setPrefix(NS_TRACKPOINT_EXTENSION, NS_TRACKPOINT_EXTENSION_URI); ser.setPrefix(NS_TRACKPOINT_EXTENSION, NS_TRACKPOINT_EXTENSION_URI);
ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "TrackPointExtension"); ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "TrackPointExtension");
if (exportHr) {
ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "hr").text(String.valueOf(hr)).endTag(NS_TRACKPOINT_EXTENSION_URI, "hr"); ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "hr").text(String.valueOf(hr)).endTag(NS_TRACKPOINT_EXTENSION_URI, "hr");
}
if (cadence >= 0) {
ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "cad").text(String.valueOf(cadence)).endTag(NS_TRACKPOINT_EXTENSION_URI, "cad");
}
if (speed >= 0) {
ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "speed").text(formatDouble(speed)).endTag(NS_TRACKPOINT_EXTENSION_URI, "speed");
}
ser.endTag(NS_TRACKPOINT_EXTENSION_URI, "TrackPointExtension"); ser.endTag(NS_TRACKPOINT_EXTENSION_URI, "TrackPointExtension");
ser.endTag(NS_GPX_URI, "extensions"); ser.endTag(NS_GPX_URI, "extensions");
} }
@ -217,7 +224,7 @@ public class GPXExporter implements ActivityTrackExporter {
return closestPointItem; return closestPointItem;
} }
private String formatLocation(double value) { private String formatDouble(double value) {
return new BigDecimal(value).setScale(GPSCoordinate.GPS_DECIMAL_DEGREES_SCALE, RoundingMode.HALF_UP).toPlainString(); return new BigDecimal(value).setScale(GPSCoordinate.GPS_DECIMAL_DEGREES_SCALE, RoundingMode.HALF_UP).toPlainString();
} }

View File

@ -30,6 +30,7 @@ import androidx.annotation.Nullable;
<gpxtpx:atemp>11</gpxtpx:atemp> <gpxtpx:atemp>11</gpxtpx:atemp>
<gpxtpx:hr>92</gpxtpx:hr> <gpxtpx:hr>92</gpxtpx:hr>
<gpxtpx:cad>0</gpxtpx:cad> <gpxtpx:cad>0</gpxtpx:cad>
<gpxtpx:speed>0.5</gpxtpx:speed>
</gpxtpx:TrackPointExtension> </gpxtpx:TrackPointExtension>
</extensions> </extensions>
</trkpt> </trkpt>
@ -39,6 +40,7 @@ public class ActivityPoint {
private GPSCoordinate location; private GPSCoordinate location;
private int heartRate; private int heartRate;
private float speed = -1; private float speed = -1;
private int cadence = -1;
// e.g. to describe a pause during the activity // e.g. to describe a pause during the activity
private @Nullable String description; private @Nullable String description;
@ -90,4 +92,12 @@ public class ActivityPoint {
public void setSpeed(float speed) { public void setSpeed(float speed) {
this.speed = speed; this.speed = speed;
} }
public int getCadence() {
return cadence;
}
public void setCadence(final int cadence) {
this.cadence = cadence;
}
} }

View File

@ -138,6 +138,9 @@ public class FitRecord extends RecordData {
if (getEnhancedSpeed() != null) { if (getEnhancedSpeed() != null) {
activityPoint.setSpeed(getEnhancedSpeed().floatValue()); activityPoint.setSpeed(getEnhancedSpeed().floatValue());
} }
if (getCadence() != null) {
activityPoint.setCadence(getCadence());
}
return activityPoint; return activityPoint;
} }
} }

View File

@ -104,6 +104,4 @@ public class HuamiActivityDetailsParserTest extends TestBase {
private InputStream getContents(URL hexFile) throws IOException { private InputStream getContents(URL hexFile) throws IOException {
return new HexToBinaryInputStream(hexFile.openStream()); return new HexToBinaryInputStream(hexFile.openStream());
} }
} }