mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-08 19:27:04 +01:00
Garmin: Parse workout physiological metrics
This commit is contained in:
parent
21de228204
commit
42dfb6ad4a
@ -106,6 +106,7 @@ public class ActivitySummaryEntries {
|
||||
public static final String MAXIMUM_OXYGEN_UPTAKE = "maximumOxygenUptake";
|
||||
public static final String RECOVERY_TIME = "recoveryTime";
|
||||
public static final String ESTIMATED_SWEAT_LOSS = "estimatedSweatLoss";
|
||||
public static final String LACTATE_THRESHOLD_HR = "lactateThresholdHeartRate";
|
||||
|
||||
public static final String CYCLING_POWER_AVERAGE = "cyclingPowerAverage";
|
||||
public static final String CYCLING_POWER_MIN = "cyclingPowerMin";
|
||||
|
@ -226,7 +226,7 @@ public class ActivitySummaryJsonSummary {
|
||||
));
|
||||
put("TrainingEffect", Arrays.asList(
|
||||
TRAINING_EFFECT_AEROBIC, TRAINING_EFFECT_ANAEROBIC, WORKOUT_LOAD,
|
||||
MAXIMUM_OXYGEN_UPTAKE
|
||||
MAXIMUM_OXYGEN_UPTAKE, RECOVERY_TIME, LACTATE_THRESHOLD_HR
|
||||
));
|
||||
put("laps", Arrays.asList(
|
||||
LAP_PACE_AVERAGE, LAPS, LANE_LENGTH
|
||||
|
@ -14,11 +14,20 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.HR_ZONE_FAT_BURN;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.HR_ZONE_NA;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.HR_ZONE_WARM_UP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.LACTATE_THRESHOLD_HR;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.MAXIMUM_OXYGEN_UPTAKE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.RECOVERY_TIME;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.TRAINING_EFFECT_AEROBIC;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.TRAINING_EFFECT_ANAEROBIC;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_BPM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_HOURS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_KCAL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_METERS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_ML;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_ML_KG_MIN;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_NONE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_SECONDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.WORKOUT_LOAD;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
@ -76,6 +85,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHrvSummary;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHrvValue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMonitoring;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitPhysiologicalMetrics;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitRecord;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSleepStage;
|
||||
@ -105,6 +115,7 @@ public class FitImporter {
|
||||
private FitFileId fileId = null;
|
||||
private FitSession session = null;
|
||||
private FitSport sport = null;
|
||||
private FitPhysiologicalMetrics physiologicalMetrics = null;
|
||||
|
||||
public FitImporter(final Context context, final GBDevice gbDevice) {
|
||||
this.context = context;
|
||||
@ -201,6 +212,9 @@ public class FitImporter {
|
||||
// We only support 1 session
|
||||
session = (FitSession) record;
|
||||
}
|
||||
} else if (record instanceof FitPhysiologicalMetrics) {
|
||||
LOG.debug("Physiological Metrics: {}", record);
|
||||
physiologicalMetrics = (FitPhysiologicalMetrics) record;
|
||||
} else if (record instanceof FitSport) {
|
||||
LOG.debug("Sport: {}", record);
|
||||
if (sport != null) {
|
||||
@ -379,6 +393,25 @@ public class FitImporter {
|
||||
}
|
||||
}
|
||||
|
||||
if (physiologicalMetrics != null) {
|
||||
// TODO lactate_threshold_heart_rate
|
||||
if (physiologicalMetrics.getAerobicEffect() != null) {
|
||||
summaryData.add(TRAINING_EFFECT_AEROBIC, physiologicalMetrics.getAerobicEffect(), UNIT_NONE);
|
||||
}
|
||||
if (physiologicalMetrics.getAnaerobicEffect() != null) {
|
||||
summaryData.add(TRAINING_EFFECT_ANAEROBIC, physiologicalMetrics.getAnaerobicEffect(), UNIT_NONE);
|
||||
}
|
||||
if (physiologicalMetrics.getMetMax() != null) {
|
||||
summaryData.add(MAXIMUM_OXYGEN_UPTAKE, physiologicalMetrics.getMetMax().floatValue() * 3.5f, UNIT_ML_KG_MIN);
|
||||
}
|
||||
if (physiologicalMetrics.getRecoveryTime() != null) {
|
||||
summaryData.add(RECOVERY_TIME, physiologicalMetrics.getRecoveryTime() / 60f, UNIT_HOURS);
|
||||
}
|
||||
if (physiologicalMetrics.getLactateThresholdHeartRate() != null) {
|
||||
summaryData.add(LACTATE_THRESHOLD_HR, physiologicalMetrics.getLactateThresholdHeartRate(), UNIT_BPM);
|
||||
}
|
||||
}
|
||||
|
||||
summary.setSummaryData(summaryData.toString());
|
||||
if (file != null) {
|
||||
summary.setRawDetailsPath(file.getAbsolutePath());
|
||||
@ -457,6 +490,7 @@ public class FitImporter {
|
||||
fileId = null;
|
||||
session = null;
|
||||
sport = null;
|
||||
physiologicalMetrics = null;
|
||||
}
|
||||
|
||||
private void persistActivitySamples() {
|
||||
|
@ -208,6 +208,17 @@ public class GlobalFITMessage {
|
||||
new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP)
|
||||
));
|
||||
|
||||
// https://github.com/GoldenCheetah/GoldenCheetah/blob/71e3928bc614f3209d9977d90cc50b942999b855/src/FileIO/FitRideFile.cpp#L1998
|
||||
public static GlobalFITMessage PHYSIOLOGICAL_METRICS = new GlobalFITMessage(140, "PHYSIOLOGICAL_METRICS", Arrays.asList(
|
||||
new FieldDefinitionPrimitive(4, BaseType.UINT8, "aerobic_effect", 10, 0),
|
||||
new FieldDefinitionPrimitive(7, BaseType.SINT32, "met_max", 65536, 0),
|
||||
new FieldDefinitionPrimitive(9, BaseType.UINT16, "recovery_time", 1, 0), // minutes
|
||||
new FieldDefinitionPrimitive(14, BaseType.UINT16, "lactate_threshold_heart_rate", 1, 0), // bpm
|
||||
//new FieldDefinitionPrimitive(15, BaseType.UINT16, "lactate_threshold_speed", 1, 0), // m/s // TODO confirm scale
|
||||
new FieldDefinitionPrimitive(20, BaseType.UINT8, "anaerobic_effect", 10, 0),
|
||||
new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP)
|
||||
));
|
||||
|
||||
public static GlobalFITMessage WATCHFACE_SETTINGS = new GlobalFITMessage(159, "WATCHFACE_SETTINGS", Arrays.asList(
|
||||
new FieldDefinitionPrimitive(0, BaseType.ENUM, "mode"), //1=analog
|
||||
new FieldDefinitionPrimitive(1, BaseType.BASE_TYPE_BYTE, "layout")
|
||||
@ -314,6 +325,7 @@ public class GlobalFITMessage {
|
||||
put(55, MONITORING);
|
||||
put(127, CONNECTIVITY);
|
||||
put(128, WEATHER);
|
||||
put(140, PHYSIOLOGICAL_METRICS);
|
||||
put(159, WATCHFACE_SETTINGS);
|
||||
put(160, GPS_METADATA);
|
||||
put(206, FIELD_DESCRIPTION);
|
||||
|
@ -0,0 +1,52 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
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 nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.codegen.FitCodeGen
|
||||
//
|
||||
public class FitPhysiologicalMetrics extends RecordData {
|
||||
public FitPhysiologicalMetrics(final RecordDefinition recordDefinition, final RecordHeader recordHeader) {
|
||||
super(recordDefinition, recordHeader);
|
||||
|
||||
final int globalNumber = recordDefinition.getGlobalFITMessage().getNumber();
|
||||
if (globalNumber != 140) {
|
||||
throw new IllegalArgumentException("FitPhysiologicalMetrics expects global messages of " + 140 + ", got " + globalNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Float getAerobicEffect() {
|
||||
return (Float) getFieldByNumber(4);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Double getMetMax() {
|
||||
return (Double) getFieldByNumber(7);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getRecoveryTime() {
|
||||
return (Integer) getFieldByNumber(9);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getLactateThresholdHeartRate() {
|
||||
return (Integer) getFieldByNumber(14);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Float getAnaerobicEffect() {
|
||||
return (Float) getFieldByNumber(20);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getTimestamp() {
|
||||
return (Long) getFieldByNumber(253);
|
||||
}
|
||||
}
|
@ -47,6 +47,8 @@ public class FitRecordDataFactory {
|
||||
return new FitConnectivity(recordDefinition, recordHeader);
|
||||
case 128:
|
||||
return new FitWeather(recordDefinition, recordHeader);
|
||||
case 140:
|
||||
return new FitPhysiologicalMetrics(recordDefinition, recordHeader);
|
||||
case 159:
|
||||
return new FitWatchfaceSettings(recordDefinition, recordHeader);
|
||||
case 160:
|
||||
|
@ -2131,6 +2131,8 @@
|
||||
<string name="currentWorkoutLoad">Workout Load</string>
|
||||
<string name="maximumOxygenUptake">Maximum Oxygen Uptake</string>
|
||||
<string name="estimatedSweatLoss">Estimated Sweat Loss</string>
|
||||
<string name="lactateThresholdHeartRate">Lactate Threshold Heart Rate</string>
|
||||
<string name="recoveryTime">Recovery Time</string>
|
||||
<string name="averageStride">Average Stride</string>
|
||||
<string name="maxStride">Max Stride</string>
|
||||
<string name="minStride">Min Stride</string>
|
||||
|
Loading…
Reference in New Issue
Block a user