mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: enhance activity summaries
- add fallback sources for HR_AVG, TOTAL_ASCENT, TOTAL_DESCENT, AVG_POWER, BODY_ENERGY_AT_START and BODY_ENERGY_AT_END - fallback to lap average speed if the lap enhanced average speed isn't available - ensure that paces/speeds are only rounded by WorkoutValueFormatter and not also by GarminWorkoutParser - add diving lap summary for apnea - add scuba tank summary - fix diving summary gaps when CNS, N2 load or O2 toxicity values are 0
This commit is contained in:
Generated
+1
@@ -168,6 +168,7 @@
|
|||||||
<w>stefanek</w>
|
<w>stefanek</w>
|
||||||
<w>stringset</w>
|
<w>stringset</w>
|
||||||
<w>subsport</w>
|
<w>subsport</w>
|
||||||
|
<w>suunto</w>
|
||||||
<w>szymon</w>
|
<w>szymon</w>
|
||||||
<w>taavi</w>
|
<w>taavi</w>
|
||||||
<w>tablename</w>
|
<w>tablename</w>
|
||||||
|
|||||||
+139
-33
@@ -70,6 +70,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSession;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSet;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSet;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitSport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTankSummary;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTimeInZone;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTimeInZone;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitUserMetrics;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitUserMetrics;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitUserProfile;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitUserProfile;
|
||||||
@@ -97,8 +98,10 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
private FitPhysiologicalMetrics physiologicalMetrics = null;
|
private FitPhysiologicalMetrics physiologicalMetrics = null;
|
||||||
@Nullable
|
@Nullable
|
||||||
private FitDiveSettings diveSettings = null;
|
private FitDiveSettings diveSettings = null;
|
||||||
|
private final List<FitDiveSummary> diveLaps = new ArrayList<>();
|
||||||
@Nullable
|
@Nullable
|
||||||
private FitDiveSummary diveSummary = null;
|
private FitDiveSummary diveSummary = null;
|
||||||
|
private final List<FitTankSummary> diveTanks = new ArrayList<>();
|
||||||
private final List<FitDiveGas> diveGases = new ArrayList<>();
|
private final List<FitDiveGas> diveGases = new ArrayList<>();
|
||||||
private final List<FitSet> sets = new ArrayList<>();
|
private final List<FitSet> sets = new ArrayList<>();
|
||||||
private final List<FitLap> laps = new ArrayList<>();
|
private final List<FitLap> laps = new ArrayList<>();
|
||||||
@@ -195,9 +198,11 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
userMetrics = null;
|
userMetrics = null;
|
||||||
userProfile = null;
|
userProfile = null;
|
||||||
physiologicalMetrics = null;
|
physiologicalMetrics = null;
|
||||||
|
diveLaps.clear();
|
||||||
diveSettings = null;
|
diveSettings = null;
|
||||||
diveSummary = null;
|
diveSummary = null;
|
||||||
diveGases.clear();
|
diveGases.clear();
|
||||||
|
diveTanks.clear();
|
||||||
sets.clear();
|
sets.clear();
|
||||||
laps.clear();
|
laps.clear();
|
||||||
deviceInfos.clear();
|
deviceInfos.clear();
|
||||||
@@ -264,21 +269,22 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
}
|
}
|
||||||
} else if (record instanceof FitDiveSummary newDiveSummary) {
|
} else if (record instanceof FitDiveSummary newDiveSummary) {
|
||||||
LOG.trace("Dive summary: {}", newDiveSummary);
|
LOG.trace("Dive summary: {}", newDiveSummary);
|
||||||
if (diveSummary != null) {
|
Integer referenceMesg = newDiveSummary.getReferenceMesg();
|
||||||
Integer referenceMesg = newDiveSummary.getReferenceMesg();
|
if (referenceMesg != null && referenceMesg == 19) {
|
||||||
if (referenceMesg != null && referenceMesg != 18) {
|
// laps
|
||||||
// prioritize diving session (18) over records like diving laps (19)
|
diveLaps.add(newDiveSummary);
|
||||||
// wish list for apnea diving: parse the multiple laps (19)
|
} else if (referenceMesg == null || referenceMesg == 18) {
|
||||||
return false;
|
// sessions
|
||||||
}
|
|
||||||
|
|
||||||
Integer referenceIndex = newDiveSummary.getReferenceIndex();
|
Integer referenceIndex = newDiveSummary.getReferenceIndex();
|
||||||
if (referenceIndex != null && referenceIndex != 0) {
|
if (referenceIndex == null || referenceIndex == 0) {
|
||||||
// prioritize first session/lap over other session/lap
|
diveSummary = newDiveSummary;
|
||||||
|
} else {
|
||||||
|
LOG.warn("Got multiple dive sessions - NOT SUPPORTED: {}", newDiveSummary);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
diveSummary = newDiveSummary;
|
|
||||||
} else if (record instanceof FitDiveGas fitDiveGas) {
|
} else if (record instanceof FitDiveGas fitDiveGas) {
|
||||||
LOG.trace("Dive gas: {}", fitDiveGas);
|
LOG.trace("Dive gas: {}", fitDiveGas);
|
||||||
diveGases.add(fitDiveGas);
|
diveGases.add(fitDiveGas);
|
||||||
@@ -329,6 +335,15 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
} else {
|
} else {
|
||||||
workout = fitWorkout;
|
workout = fitWorkout;
|
||||||
}
|
}
|
||||||
|
} else if (record instanceof FitTankSummary fitTankSummary){
|
||||||
|
final Float start = fitTankSummary.getStartPressure();
|
||||||
|
final Float end = fitTankSummary.getEndPressure();
|
||||||
|
final Double used = fitTankSummary.getVolumeUsed();
|
||||||
|
if ((start != null && start > 0)
|
||||||
|
|| (end != null && end > 0)
|
||||||
|
|| (used != null && used != 0)) {
|
||||||
|
diveTanks.add(fitTankSummary);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -411,7 +426,9 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
summaryData.add(FLUID_CONSUMED, session.getFluidConsumed(), UNIT_ML);
|
summaryData.add(FLUID_CONSUMED, session.getFluidConsumed(), UNIT_ML);
|
||||||
summaryData.add(ESTIMATED_SWEAT_LOSS, session.getEstimatedSweatLoss(), UNIT_ML);
|
summaryData.add(ESTIMATED_SWEAT_LOSS, session.getEstimatedSweatLoss(), UNIT_ML);
|
||||||
summaryData.add(HR_MIN, session.getMinHeartRate(), UNIT_BPM);
|
summaryData.add(HR_MIN, session.getMinHeartRate(), UNIT_BPM);
|
||||||
summaryData.add(HR_AVG, session.getAverageHeartRate(), UNIT_BPM);
|
if (!summaryData.add(HR_AVG, session.getAverageHeartRate(), UNIT_BPM) && physiologicalMetrics != null) {
|
||||||
|
summaryData.add(HR_AVG, physiologicalMetrics.getAverageHeartRate(), UNIT_BPM);
|
||||||
|
}
|
||||||
summaryData.add(HR_MAX, session.getMaxHeartRate(), UNIT_BPM);
|
summaryData.add(HR_MAX, session.getMaxHeartRate(), UNIT_BPM);
|
||||||
summaryData.add(HRV_SDRR, session.getHrvSdrr(), UNIT_MILLISECONDS);
|
summaryData.add(HRV_SDRR, session.getHrvSdrr(), UNIT_MILLISECONDS);
|
||||||
summaryData.add(HRV_RMSSD, session.getHrvRmssd(), UNIT_MILLISECONDS);
|
summaryData.add(HRV_RMSSD, session.getHrvRmssd(), UNIT_MILLISECONDS);
|
||||||
@@ -449,8 +466,12 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ActivityKind.isDiving(activityKind)) {
|
if (!ActivityKind.isDiving(activityKind)) {
|
||||||
summaryData.add(TOTAL_ASCENT, session.getTotalAscent(), UNIT_METERS);
|
if(!summaryData.add(TOTAL_ASCENT, session.getTotalAscent(), UNIT_METERS) && physiologicalMetrics != null){
|
||||||
summaryData.add(TOTAL_DESCENT, session.getTotalDescent(), UNIT_METERS);
|
summaryData.add(TOTAL_ASCENT, physiologicalMetrics.getTotalAscent(), UNIT_METERS);
|
||||||
|
}
|
||||||
|
if(!summaryData.add(TOTAL_DESCENT, session.getTotalDescent(), UNIT_METERS) && physiologicalMetrics != null){
|
||||||
|
summaryData.add(TOTAL_DESCENT, physiologicalMetrics.getTotalDescent(), UNIT_METERS);
|
||||||
|
}
|
||||||
if (session.getAvgVam() != null) {
|
if (session.getAvgVam() != null) {
|
||||||
summaryData.add(AVERAGE_ASCENT_VELOCITY, session.getAvgVam() * 3600, UNIT_METERS_PER_HOUR);
|
summaryData.add(AVERAGE_ASCENT_VELOCITY, session.getAvgVam() * 3600, UNIT_METERS_PER_HOUR);
|
||||||
}
|
}
|
||||||
@@ -463,7 +484,7 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
}
|
}
|
||||||
if (speedAvg != null) {
|
if (speedAvg != null) {
|
||||||
if (ActivityKind.isPaceActivity(activityKind)) {
|
if (ActivityKind.isPaceActivity(activityKind)) {
|
||||||
summaryData.add(PACE_AVG_SECONDS_KM, Math.round((60 / (speedAvg.doubleValue() * 3.6)) * 60), UNIT_SECONDS_PER_KM);
|
summaryData.add(PACE_AVG_SECONDS_KM, 1000.0 / speedAvg.doubleValue(), UNIT_SECONDS_PER_KM);
|
||||||
} else if (ActivityKind.isDiving(activityKind)) {
|
} else if (ActivityKind.isDiving(activityKind)) {
|
||||||
// Hide speed for diving activities
|
// Hide speed for diving activities
|
||||||
} else {
|
} else {
|
||||||
@@ -477,7 +498,7 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
}
|
}
|
||||||
if (speedMax != null) {
|
if (speedMax != null) {
|
||||||
if (ActivityKind.isPaceActivity(activityKind)) {
|
if (ActivityKind.isPaceActivity(activityKind)) {
|
||||||
summaryData.add(PACE_MAX, Math.round((60 / (speedMax.doubleValue() * 3.6)) * 60), UNIT_SECONDS_PER_KM);
|
summaryData.add(PACE_MAX, 1000.0 / speedMax.doubleValue(), UNIT_SECONDS_PER_KM);
|
||||||
} else if (ActivityKind.isDiving(activityKind)) {
|
} else if (ActivityKind.isDiving(activityKind)) {
|
||||||
// Hide speed for diving activities
|
// Hide speed for diving activities
|
||||||
} else {
|
} else {
|
||||||
@@ -489,7 +510,9 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
summaryData.add(RATING_OF_PERCEIVED_EXERTION, session.getWorkoutRpe(), UNIT_PERCENTAGE);
|
summaryData.add(RATING_OF_PERCEIVED_EXERTION, session.getWorkoutRpe(), UNIT_PERCENTAGE);
|
||||||
summaryData.add(WORKOUT_FEEL, session.getWorkoutFeel(), UNIT_PERCENTAGE);
|
summaryData.add(WORKOUT_FEEL, session.getWorkoutFeel(), UNIT_PERCENTAGE);
|
||||||
|
|
||||||
summaryData.add(AVG_POWER, session.getAvgPower(), UNIT_WATT);
|
if(!summaryData.add(AVG_POWER, session.getAvgPower(), UNIT_WATT) && physiologicalMetrics != null){
|
||||||
|
summaryData.add(AVG_POWER, physiologicalMetrics.getAveragePower(), UNIT_WATT);
|
||||||
|
}
|
||||||
summaryData.add(MAX_POWER, session.getMaxPower(), UNIT_WATT);
|
summaryData.add(MAX_POWER, session.getMaxPower(), UNIT_WATT);
|
||||||
summaryData.add(NORMALIZED_POWER, session.getNormalizedPower(), UNIT_WATT);
|
summaryData.add(NORMALIZED_POWER, session.getNormalizedPower(), UNIT_WATT);
|
||||||
summaryData.add(TOTAL_WORK, session.getTotalWork(), UNIT_JOULE);
|
summaryData.add(TOTAL_WORK, session.getTotalWork(), UNIT_JOULE);
|
||||||
@@ -711,19 +734,48 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
summaryData.add(BOTTOM_TIME, diveSummary.getBottomTime(), UNIT_SECONDS);
|
summaryData.add(BOTTOM_TIME, diveSummary.getBottomTime(), UNIT_SECONDS);
|
||||||
summaryData.add(AVG_DEPTH, diveSummary.getAvgDepth(), UNIT_METERS);
|
summaryData.add(AVG_DEPTH, diveSummary.getAvgDepth(), UNIT_METERS);
|
||||||
summaryData.add(MAX_DEPTH, diveSummary.getMaxDepth(), UNIT_METERS);
|
summaryData.add(MAX_DEPTH, diveSummary.getMaxDepth(), UNIT_METERS);
|
||||||
if (diveSummary.getStartCns() != null) {
|
|
||||||
summaryData.add(START_CNS, diveSummary.getStartCns(), UNIT_PERCENTAGE, true);
|
// force display even if value is 0
|
||||||
}
|
summaryData.add(START_CNS, diveSummary.getStartCns(), UNIT_PERCENTAGE, true);
|
||||||
summaryData.add(END_CNS, diveSummary.getEndCns(), UNIT_PERCENTAGE);
|
summaryData.add(END_CNS, diveSummary.getEndCns(), UNIT_PERCENTAGE, true);
|
||||||
if (diveSummary.getStartN2() != null) {
|
summaryData.add(START_N2, diveSummary.getStartN2(), UNIT_PERCENTAGE, true);
|
||||||
summaryData.add(START_N2, diveSummary.getStartN2(), UNIT_PERCENTAGE, true);
|
summaryData.add(END_N2, diveSummary.getEndN2(), UNIT_PERCENTAGE, true);
|
||||||
}
|
summaryData.add(OXYGEN_TOXICITY, diveSummary.getO2Toxicity(), UNIT_OXYGEN_TOXICITY_UNITs, true);
|
||||||
summaryData.add(END_N2, diveSummary.getEndN2(), UNIT_PERCENTAGE);
|
|
||||||
summaryData.add(OXYGEN_TOXICITY, diveSummary.getO2Toxicity(), UNIT_OXYGEN_TOXICITY_UNITs);
|
|
||||||
summaryData.add(SURFACE_INTERVAL, diveSummary.getSurfaceInterval(), UNIT_SECONDS);
|
summaryData.add(SURFACE_INTERVAL, diveSummary.getSurfaceInterval(), UNIT_SECONDS);
|
||||||
summaryData.add(PRESSURE_SAC_AVG, diveSummary.getAvgPressureSac(), UNIT_BAR_PER_MINUTE);
|
summaryData.add(PRESSURE_SAC_AVG, diveSummary.getAvgPressureSac(), UNIT_BAR_PER_MINUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unlike other diving, apnea encodes most information in the lap and not in the summary
|
||||||
|
// -> display interval table even if it is the only lap
|
||||||
|
if (diveLaps.size() > 1 || (!diveLaps.isEmpty() && null != diveLaps.get(0).getHangTime())) {
|
||||||
|
final List<String> header = new ArrayList<>(5);
|
||||||
|
header.add("#");
|
||||||
|
header.add(SURFACE_INTERVAL);
|
||||||
|
header.add(BOTTOM_TIME);
|
||||||
|
header.add("diving_depth");
|
||||||
|
header.add(DIVING_HANG_TIME);
|
||||||
|
final ActivitySummaryTableBuilder tableBuilder = new ActivitySummaryTableBuilder(GROUP_INTERVALS, "intervals_header", header);
|
||||||
|
|
||||||
|
for (int i = 0; i < diveLaps.size(); i++) {
|
||||||
|
FitDiveSummary diveLap = diveLaps.get(i);
|
||||||
|
tableBuilder.addRow(
|
||||||
|
"interval_" + i,
|
||||||
|
Arrays.asList(
|
||||||
|
new ActivitySummaryValue(i + 1, UNIT_NONE),
|
||||||
|
new ActivitySummaryValue(diveLap.getSurfaceInterval(), UNIT_SECONDS),
|
||||||
|
new ActivitySummaryValue(diveLap.getBottomTime(), UNIT_SECONDS),
|
||||||
|
new ActivitySummaryValue(diveLap.getMaxDepth(), UNIT_METERS),
|
||||||
|
new ActivitySummaryValue(diveLap.getHangTime(), UNIT_SECONDS)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tableBuilder.hasRows()) {
|
||||||
|
tableBuilder.addToSummaryData(summaryData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (diveSettings != null) {
|
if (diveSettings != null) {
|
||||||
if (diveSettings.getWaterDensity() != null) {
|
if (diveSettings.getWaterDensity() != null) {
|
||||||
summaryData.add(WATER_TYPE, diveSettings.getWaterDensity(), UNIT_KG_PER_M3);
|
summaryData.add(WATER_TYPE, diveSettings.getWaterDensity(), UNIT_KG_PER_M3);
|
||||||
@@ -750,8 +802,16 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
summaryData.add(INTENSITY_FACTOR, session.getIntensityFactor(), UNIT_NONE);
|
summaryData.add(INTENSITY_FACTOR, session.getIntensityFactor(), UNIT_NONE);
|
||||||
summaryData.add(TRAINING_STRESS_SCORE, session.getTrainingStressScore(), UNIT_NONE);
|
summaryData.add(TRAINING_STRESS_SCORE, session.getTrainingStressScore(), UNIT_NONE);
|
||||||
summaryData.add(TRAINING_EFFECT_TOTAL, session.getTotalTrainingEffect(), UNIT_NONE);
|
summaryData.add(TRAINING_EFFECT_TOTAL, session.getTotalTrainingEffect(), UNIT_NONE);
|
||||||
summaryData.add(BODY_ENERGY_AT_START, session.getBeginningBodyBattery(), UNIT_PERCENTAGE);
|
if (!summaryData.add(BODY_ENERGY_AT_START, session.getBeginningBodyBattery(), UNIT_PERCENTAGE)) {
|
||||||
summaryData.add(BODY_ENERGY_AT_END, session.getEndingBodyBattery(), UNIT_PERCENTAGE);
|
if (userMetrics != null) {
|
||||||
|
summaryData.add(BODY_ENERGY_AT_START, userMetrics.getBeginningBodyBattery(), UNIT_PERCENTAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!summaryData.add(BODY_ENERGY_AT_END, session.getEndingBodyBattery(), UNIT_PERCENTAGE)) {
|
||||||
|
if (physiologicalMetrics != null) {
|
||||||
|
summaryData.add(BODY_ENERGY_AT_END, physiologicalMetrics.getEndingBodyBattery(), UNIT_PERCENTAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
summaryData.add(SOLAR_INTENSITY, session.getSolarIntensity(), UNIT_PERCENTAGE);
|
summaryData.add(SOLAR_INTENSITY, session.getSolarIntensity(), UNIT_PERCENTAGE);
|
||||||
summaryData.add(BATTERY_GAIN, session.getBatteryGain(), UNIT_SECONDS);
|
summaryData.add(BATTERY_GAIN, session.getBatteryGain(), UNIT_SECONDS);
|
||||||
@@ -792,6 +852,49 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!diveTanks.isEmpty()) {
|
||||||
|
final ActivitySummaryTableBuilder tableBuilder = new ActivitySummaryTableBuilder(GROUP_GAS, "tanks_header", Arrays.asList(
|
||||||
|
"diving_tank",
|
||||||
|
"activity_detail_start_label",
|
||||||
|
"activity_detail_end_label",
|
||||||
|
"diving_tank_used"
|
||||||
|
));
|
||||||
|
for(int i = 0; i< diveTanks.size(); i++) {
|
||||||
|
FitTankSummary tankSummary = diveTanks.get(i);
|
||||||
|
String label = AntGadget.Companion.formatAntID(tankSummary.getSensor());
|
||||||
|
Float start = tankSummary.getStartPressure();
|
||||||
|
Float end = tankSummary.getEndPressure();
|
||||||
|
Double used = tankSummary.getVolumeUsed();
|
||||||
|
String usedUOM = UNIT_LITER;
|
||||||
|
|
||||||
|
if(label == null){
|
||||||
|
label = Integer.toString(i);
|
||||||
|
}
|
||||||
|
if(start == null){
|
||||||
|
start = 0.0f;
|
||||||
|
}
|
||||||
|
if(end == null){
|
||||||
|
end = 0.0f;
|
||||||
|
}
|
||||||
|
if(used == null){
|
||||||
|
used = (double)(start - end);
|
||||||
|
usedUOM = UNIT_BAR;
|
||||||
|
}
|
||||||
|
tableBuilder.addRow(
|
||||||
|
"tank_" + i,
|
||||||
|
Arrays.asList(
|
||||||
|
new ActivitySummaryValue(label, UNIT_NONE),
|
||||||
|
new ActivitySummaryValue(start, UNIT_BAR),
|
||||||
|
new ActivitySummaryValue(end, UNIT_BAR),
|
||||||
|
new ActivitySummaryValue(used, usedUOM)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (tableBuilder.hasRows()) {
|
||||||
|
tableBuilder.addToSummaryData(summaryData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (userProfile != null) {
|
if (userProfile != null) {
|
||||||
summaryData.add(HR_USER_RESTING, userProfile.getRestingHeartRate(), UNIT_BPM);
|
summaryData.add(HR_USER_RESTING, userProfile.getRestingHeartRate(), UNIT_BPM);
|
||||||
}
|
}
|
||||||
@@ -907,7 +1010,7 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
final boolean anySwimmingLaps = laps.stream()
|
final boolean anySwimmingLaps = laps.stream()
|
||||||
.anyMatch(lap -> lap.getSwimStyle() != null);
|
.anyMatch(lap -> lap.getSwimStyle() != null);
|
||||||
|
|
||||||
if (anyValidLaps) {
|
if (anyValidLaps && diveLaps.isEmpty()) {
|
||||||
// Unfortunately our tables do not yet scroll horizontally, so can't always add all possible columns
|
// Unfortunately our tables do not yet scroll horizontally, so can't always add all possible columns
|
||||||
final List<String> header = new ArrayList<>();
|
final List<String> header = new ArrayList<>();
|
||||||
header.add("#");
|
header.add("#");
|
||||||
@@ -931,14 +1034,17 @@ public class GarminWorkoutParser implements ActivitySummaryParser {
|
|||||||
|
|
||||||
final List<ActivitySummaryValue> row = new ArrayList<>();
|
final List<ActivitySummaryValue> row = new ArrayList<>();
|
||||||
|
|
||||||
final Double speedValue;
|
Number speedValue = lap.getEnhancedAvgSpeed();
|
||||||
final String speedUnit;
|
final String speedUnit;
|
||||||
if (lap.getEnhancedAvgSpeed() != null) {
|
if(speedValue == null){
|
||||||
|
speedValue = lap.getAvgSpeed();
|
||||||
|
}
|
||||||
|
if (speedValue != null) {
|
||||||
if (ActivityKind.isPaceActivity(activityKind)) {
|
if (ActivityKind.isPaceActivity(activityKind)) {
|
||||||
speedValue = (double) Math.round((60 / (lap.getEnhancedAvgSpeed() * 3.6)) * 60);
|
speedValue = 1000.0 / speedValue.doubleValue();
|
||||||
speedUnit = UNIT_SECONDS_PER_KM;
|
speedUnit = UNIT_SECONDS_PER_KM;
|
||||||
} else {
|
} else {
|
||||||
speedValue = Math.round((lap.getEnhancedAvgSpeed() * 3600 / 1000) * 100.0) / 100.0;
|
speedValue = speedValue.doubleValue() * 3600.0 / 1000.0;
|
||||||
speedUnit = UNIT_KMPH;
|
speedUnit = UNIT_KMPH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+24
-15
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2024 José Rebelo
|
/* Copyright (C) 2024-2026 José Rebelo, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -62,42 +62,51 @@ public class ActivitySummaryData {
|
|||||||
this.entries = entries;
|
this.entries = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String key, final Number value, final String unit) {
|
/// @return {@code true} if the value was actually added
|
||||||
add(null, key, value, unit, false);
|
public boolean add(final String key, final Number value, final String unit) {
|
||||||
|
return add(null, key, value, unit, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String key, final String unit, final Number value, final Number valueFallback) {
|
/// @return {@code true} if the value was actually added
|
||||||
|
public boolean add(final String key, final String unit, final Number value, final Number valueFallback) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
add(null, key, value, unit, false);
|
return add(null, key, value, unit, false);
|
||||||
} else {
|
} else {
|
||||||
add(null, key, valueFallback, unit, false);
|
return add(null, key, valueFallback, unit, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String key, final Number value, final String unit, boolean forceDisplay) {
|
/// @return {@code true} if the value was actually added
|
||||||
add(null, key, value, unit, forceDisplay);
|
public boolean add(final String key, final Number value, final String unit, boolean forceDisplay) {
|
||||||
|
return add(null, key, value, unit, forceDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String group, final String key, final Number value, final String unit) {
|
/// @return {@code true} if the value was actually added
|
||||||
add(group, key, value, unit, false);
|
public boolean add(final String group, final String key, final Number value, final String unit) {
|
||||||
|
return add(group, key, value, unit, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String group, final String key, final Number value, final String unit, boolean forceDisplay) {
|
/// @return {@code true} if the value was actually added
|
||||||
|
public boolean add(final String group, final String key, final Number value, final String unit, boolean forceDisplay) {
|
||||||
if (value != null && (value.doubleValue() != 0 || forceDisplay)) {
|
if (value != null && (value.doubleValue() != 0 || forceDisplay)) {
|
||||||
entries.put(key, new ActivitySummarySimpleEntry(group, value, unit));
|
entries.put(key, new ActivitySummarySimpleEntry(group, value, unit));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String key, final String value) {
|
/// @return {@code true} if the value was actually added
|
||||||
add(null, key, value);
|
public boolean add(final String key, final String value) {
|
||||||
|
return add(null, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String group, final String key, final String value) {
|
public boolean add(final String group, final String key, final String value) {
|
||||||
if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
|
if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.put(key, new ActivitySummarySimpleEntry(group, value, ActivitySummaryEntries.UNIT_STRING));
|
entries.put(key, new ActivitySummarySimpleEntry(group, value, ActivitySummaryEntries.UNIT_STRING));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String key, final ActivitySummaryEntry entry) {
|
public void add(final String key, final ActivitySummaryEntry entry) {
|
||||||
|
|||||||
+3
@@ -265,6 +265,8 @@ public class ActivitySummaryEntries {
|
|||||||
public static final String UNIT_BAR_PER_MINUTE = "unit_bar_per_minute";
|
public static final String UNIT_BAR_PER_MINUTE = "unit_bar_per_minute";
|
||||||
public static final String UNIT_VOLT = "unit_volt";
|
public static final String UNIT_VOLT = "unit_volt";
|
||||||
public static final String UNIT_KG_PER_M3 = "unit_kg_per_m3";
|
public static final String UNIT_KG_PER_M3 = "unit_kg_per_m3";
|
||||||
|
public static final String UNIT_BAR = "unit_bar";
|
||||||
|
public static final String UNIT_LITER = "unit_liter";
|
||||||
|
|
||||||
public static final String GROUP_PACE = "Pace";
|
public static final String GROUP_PACE = "Pace";
|
||||||
public static final String GROUP_ACTIVITY = "Activity";
|
public static final String GROUP_ACTIVITY = "Activity";
|
||||||
@@ -314,6 +316,7 @@ public class ActivitySummaryEntries {
|
|||||||
public static final String MAX_DEPTH = "diving_maximum_diving_depth";
|
public static final String MAX_DEPTH = "diving_maximum_diving_depth";
|
||||||
public static final String WATER_TYPE = "diving_water_type";
|
public static final String WATER_TYPE = "diving_water_type";
|
||||||
public static final String GROUP_GAS = "diving_gas";
|
public static final String GROUP_GAS = "diving_gas";
|
||||||
|
public static final String DIVING_HANG_TIME = "diving_hang_time";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to signal that this activity has a gps track. This is currently used by ActivitySummaryDetail
|
* Used to signal that this activity has a gps track. This is currently used by ActivitySummaryDetail
|
||||||
|
|||||||
@@ -1063,7 +1063,7 @@
|
|||||||
<string name="diving_nitrogen_load">Nitrogen load</string>
|
<string name="diving_nitrogen_load">Nitrogen load</string>
|
||||||
<string name="diving_oxygen_toxicity">Oxygen toxicity</string>
|
<string name="diving_oxygen_toxicity">Oxygen toxicity</string>
|
||||||
<string name="unit_oxygen_toxicity_units">OTU</string>
|
<string name="unit_oxygen_toxicity_units">OTU</string>
|
||||||
<string name="diving_surface_interval">Surface interval</string>
|
<string name="diving_surface_interval">Surface Interval</string>
|
||||||
<string name="clock">Clock</string>
|
<string name="clock">Clock</string>
|
||||||
<string name="heart_rate">Heart rate</string>
|
<string name="heart_rate">Heart rate</string>
|
||||||
<string name="hr_resting">Resting</string>
|
<string name="hr_resting">Resting</string>
|
||||||
@@ -2735,6 +2735,12 @@
|
|||||||
<string name="unit_bar_per_minute">bar/min</string>
|
<string name="unit_bar_per_minute">bar/min</string>
|
||||||
<string name="unit_kg_per_m3">kg/m³</string>
|
<string name="unit_kg_per_m3">kg/m³</string>
|
||||||
<string name="unit_volt">V</string>
|
<string name="unit_volt">V</string>
|
||||||
|
<string name="unit_bar">bar</string>
|
||||||
|
<string name="unit_liter">L</string>
|
||||||
|
<string name="diving_tank">Tank</string>
|
||||||
|
<!-- consumed volume or pressure from a diving gas tank -->
|
||||||
|
<string name="diving_tank_used">Used</string>
|
||||||
|
<string name="diving_hang_time">Hang Time</string>
|
||||||
<string name="water_type_custom">Custom</string>
|
<string name="water_type_custom">Custom</string>
|
||||||
<string name="water_type_en13319">EN13319</string>
|
<string name="water_type_en13319">EN13319</string>
|
||||||
<string name="water_type_fresh">Fresh</string>
|
<string name="water_type_fresh">Fresh</string>
|
||||||
@@ -2820,7 +2826,7 @@
|
|||||||
<string name="diving_start_n2">Start N2 load</string>
|
<string name="diving_start_n2">Start N2 load</string>
|
||||||
<string name="diving_end_n2">End N2 load</string>
|
<string name="diving_end_n2">End N2 load</string>
|
||||||
<string name="dive_number">Dive number</string>
|
<string name="dive_number">Dive number</string>
|
||||||
<string name="diving_bottom_time">Bottom time</string>
|
<string name="diving_bottom_time">Bottom Time</string>
|
||||||
<!-- activity summary units-->
|
<!-- activity summary units-->
|
||||||
<string name="meters">m</string>
|
<string name="meters">m</string>
|
||||||
<string name="cm">cm</string>
|
<string name="cm">cm</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user