diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminWorkoutParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminWorkoutParser.java index a2576605f..97433a4b6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminWorkoutParser.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminWorkoutParser.java @@ -180,6 +180,27 @@ public class GarminWorkoutParser implements ActivitySummaryParser { if (session.getMaxHeartRate() != null) { summaryData.add(HR_MAX, session.getMaxHeartRate(), UNIT_BPM); } + if (session.getHrvSdrr() != null) { + summaryData.add(HRV_SDRR, session.getHrvSdrr(), UNIT_MILLISECONDS); + } + if (session.getHrvRmssd() != null) { + summaryData.add(HRV_RMSSD, session.getHrvRmssd(), UNIT_MILLISECONDS); + } + if (session.getAvgSpo2() != null) { + summaryData.add(SPO2_AVG, session.getAvgSpo2(), UNIT_PERCENTAGE); + } + if (session.getEnhancedAvgRespirationRate() != null) { + summaryData.add(RESPIRATION_AVG, session.getEnhancedAvgRespirationRate(), UNIT_BREATHS_PER_MIN); + } + if (session.getEnhancedMaxRespirationRate() != null) { + summaryData.add(RESPIRATION_MAX, session.getEnhancedMaxRespirationRate(), UNIT_BREATHS_PER_MIN); + } + if (session.getEnhancedMinRespirationRate() != null) { + summaryData.add(RESPIRATION_MIN, session.getEnhancedMinRespirationRate(), UNIT_BREATHS_PER_MIN); + } + if (session.getAvgStress() != null) { + summaryData.add(STRESS_AVG, session.getAvgStress(), UNIT_NONE); + } if (session.getAverageCadence() != null) { summaryData.add(CADENCE_AVG, session.getAverageCadence(), UNIT_SPM); } @@ -213,9 +234,19 @@ public class GarminWorkoutParser implements ActivitySummaryParser { // Find the first time in zone for the session (assumes single-session) if (fitTimeInZone.getReferenceMessage() != null && fitTimeInZone.getReferenceMessage() == 18) { final Double[] timeInZones = fitTimeInZone.getTimeInZone(); - final double totalTime = Arrays.stream(timeInZones).mapToInt(Double::intValue).sum(); + if (timeInZones == null) { + continue; + } + final double totalTime = Arrays.stream(timeInZones).mapToDouble(Number::doubleValue).sum(); + if (totalTime == 0) { + continue; + } + if (timeInZones[0] != null && timeInZones[0] == totalTime) { + // The total time is N/A, so do not add the section + continue; + } final List zoneOrder = Arrays.asList(HR_ZONE_NA, HR_ZONE_WARM_UP, HR_ZONE_EASY, HR_ZONE_AEROBIC, HR_ZONE_THRESHOLD, HR_ZONE_MAXIMUM); - for (int i = 1; i < zoneOrder.size(); i++) { + for (int i = 0; i < zoneOrder.size(); i++) { double timeInZone = timeInZones[i] != null ? Math.rint(timeInZones[i]) : 0; summaryData.add( zoneOrder.get(i), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java index 1d8b08264..00e9a8a5a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java @@ -77,6 +77,14 @@ public class ActivitySummaryEntries { public static final String HR_ZONE_EXTREME = "hrZoneExtreme"; public static final String HR_ZONE_MAXIMUM = "hrZoneMaximum"; + public static final String RESPIRATION_AVG = "average_respiration_rate"; + public static final String RESPIRATION_MAX = "max_respiration_rate"; + public static final String RESPIRATION_MIN = "min_respiration_rate"; + public static final String SPO2_AVG = "menuitem_spo2"; + public static final String STRESS_AVG = "menuitem_stress"; + public static final String HRV_SDRR = "hrv_sdrr"; + public static final String HRV_RMSSD = "hrv_rmssd"; + public static final String LANE_LENGTH = "laneLength"; public static final String LAPS = "laps"; public static final String LAP_PACE_AVERAGE = "averageLapPace"; @@ -118,6 +126,7 @@ public class ActivitySummaryEntries { public static final String SETS = "workoutSets"; public static final String UNIT_BPM = "bpm"; + public static final String UNIT_BREATHS_PER_MIN = "breaths_per_min"; public static final String UNIT_CM = "cm"; public static final String UNIT_UNIX_EPOCH_SECONDS = "unix_epoch_seconds"; public static final String UNIT_KCAL = "calories_unit"; @@ -125,11 +134,12 @@ public class ActivitySummaryEntries { public static final String UNIT_LAPS = "laps_unit"; public static final String UNIT_KILOMETERS = "km"; public static final String UNIT_METERS = "meters"; + public static final String UNIT_PERCENTAGE = "%"; public static final String UNIT_ML_KG_MIN = "ml/kg/min"; public static final String UNIT_NONE = ""; public static final String UNIT_HOURS = "hours"; public static final String UNIT_SECONDS = "seconds"; - public static final String UNIT_MILLISECONDS = "milliseconds"; + public static final String UNIT_MILLISECONDS = "milliseconds_ms"; public static final String UNIT_SECONDS_PER_KM = "seconds_km"; public static final String UNIT_SECONDS_PER_M = "seconds_m"; public static final String UNIT_METERS_PER_SECOND = "meters_second"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalFITMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalFITMessage.java index 75dc79a85..7507f7121 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalFITMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalFITMessage.java @@ -117,7 +117,14 @@ public class GlobalFITMessage { new FieldDefinitionPrimitive(110, BaseType.STRING, 64, "sport_profile_name"), new FieldDefinitionPrimitive(124, BaseType.UINT32, "enhanced_avg_speed", 1000, 0), // m/s new FieldDefinitionPrimitive(125, BaseType.UINT32, "enhanced_max_speed", 1000, 0), // m/s + new FieldDefinitionPrimitive(169, BaseType.UINT16, "enhanced_avg_respiration_rate", 100, 0 ), // breaths/min + new FieldDefinitionPrimitive(170, BaseType.UINT16, "enhanced_max_respiration_rate", 100, 0 ), // breaths/min new FieldDefinitionPrimitive(178, BaseType.UINT16, "estimated_sweat_loss"), // ml + new FieldDefinitionPrimitive(180, BaseType.UINT16, "enhanced_min_respiration_rate", 100, 0 ), // breaths/min + new FieldDefinitionPrimitive(194, BaseType.UINT8, "avg_spo2"), + new FieldDefinitionPrimitive(195, BaseType.UINT8, "avg_stress"), + new FieldDefinitionPrimitive(197, BaseType.UINT8, "hrv_sdrr"), // ms + new FieldDefinitionPrimitive(198, BaseType.UINT8, "hrv_rmssd"), // ms new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP) )); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSession.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSession.java index 41284081c..7ef307bb7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSession.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/messages/FitSession.java @@ -165,11 +165,46 @@ public class FitSession extends RecordData { return (Double) getFieldByNumber(125); } + @Nullable + public Float getEnhancedAvgRespirationRate() { + return (Float) getFieldByNumber(169); + } + + @Nullable + public Float getEnhancedMaxRespirationRate() { + return (Float) getFieldByNumber(170); + } + @Nullable public Integer getEstimatedSweatLoss() { return (Integer) getFieldByNumber(178); } + @Nullable + public Float getEnhancedMinRespirationRate() { + return (Float) getFieldByNumber(180); + } + + @Nullable + public Integer getAvgSpo2() { + return (Integer) getFieldByNumber(194); + } + + @Nullable + public Integer getAvgStress() { + return (Integer) getFieldByNumber(195); + } + + @Nullable + public Integer getHrvSdrr() { + return (Integer) getFieldByNumber(197); + } + + @Nullable + public Integer getHrvRmssd() { + return (Integer) getFieldByNumber(198); + } + @Nullable public Long getTimestamp() { return (Long) getFieldByNumber(253); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cfb2cc5c8..888e50d88 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2188,6 +2188,12 @@ Threshold Extreme Maximum + Respiration Rate + Max Respiration Rate + Min Respiration Rate + HRV SDRR + HRV RMSSD + breaths/min Training Effect Aerobic Effect Anaerobic Effect @@ -2264,6 +2270,7 @@ str sec milliseconds + ms swolf index swim style laps