From cd7c7092b246feed90f9f656202c54fecd50fc8e Mon Sep 17 00:00:00 2001 From: AndrewP Date: Sat, 7 Dec 2024 18:16:04 +0000 Subject: [PATCH] Xiaomi: Workout parser for jump roping (#4389) workout parser for jump roping incl. new field names, units und a group Co-authored-by: AndrewP <> Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/4389 Co-authored-by: AndrewP Co-committed-by: AndrewP --- .../model/ActivitySummaryEntries.java | 7 +++ .../model/ActivitySummaryJsonSummary.java | 3 ++ .../xiaomi/activity/XiaomiActivityFileId.java | 2 +- .../activity/impl/WorkoutSummaryParser.java | 51 +++++++++++++++++++ app/src/main/res/values/strings.xml | 6 +++ 5 files changed, 68 insertions(+), 1 deletion(-) 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 00e9a8a5a..ae9a1e7f6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryEntries.java @@ -104,6 +104,10 @@ public class ActivitySummaryEntries { public static final String STROKE_RATE_MAX = "maxStrokeRate"; public static final String STROKES = "strokes"; + public static final String JUMP_RATE_AVG = "avgJumpRate"; + public static final String JUMP_RATE_MAX = "maxJumpRate"; + public static final String JUMPS = "totalJumps"; + public static final String SWIM_STYLE = "swimStyle"; public static final String SWOLF_INDEX = "swolfIndex"; public static final String SWOLF_AVG = "swolfAvg"; @@ -149,6 +153,8 @@ public class ActivitySummaryEntries { public static final String UNIT_STROKES = "strokes_unit"; public static final String UNIT_STROKES_PER_MINUTE = "strokes_minute"; public static final String UNIT_STROKES_PER_SECOND = "strokes_second"; + public static final String UNIT_JUMPS = "jumps_unit"; + public static final String UNIT_JUMPS_PER_MINUTE = "jumps_minute"; public static final String UNIT_YARD = "yard"; public static final String UNIT_DEGREES = "degrees"; public static final String UNIT_STRING = "string"; @@ -161,6 +167,7 @@ public class ActivitySummaryEntries { public static final String GROUP_ELEVATION = "Elevation"; public static final String GROUP_HEART_RATE_ZONES = "HeartRateZones"; public static final String GROUP_STROKES = "Strokes"; + public static final String GROUP_JUMPS = "Jumps"; public static final String GROUP_SWIMMING = "Swimming"; public static final String GROUP_TRAINING_EFFECT = "TrainingEffect"; public static final String GROUP_LAPS = "laps"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryJsonSummary.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryJsonSummary.java index b21243812..658253468 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryJsonSummary.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySummaryJsonSummary.java @@ -180,6 +180,9 @@ public class ActivitySummaryJsonSummary { STROKE_DISTANCE_AVG, STROKE_AVG_PER_SECOND, STROKES, STROKE_RATE_AVG, STROKE_RATE_MAX )); + put(GROUP_JUMPS, Arrays.asList( + JUMPS, JUMP_RATE_AVG, JUMP_RATE_MAX + )); put(GROUP_SWIMMING, Arrays.asList( SWOLF_INDEX, SWOLF_AVG, SWOLF_MAX, SWOLF_MIN, SWIM_STYLE )); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/XiaomiActivityFileId.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/XiaomiActivityFileId.java index 1b797fcc4..ee6a1c351 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/XiaomiActivityFileId.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/XiaomiActivityFileId.java @@ -205,7 +205,7 @@ public class XiaomiActivityFileId implements Comparable { SPORTS_HIIT(Type.SPORTS, 0x10), SPORTS_ELLIPTICAL(Type.SPORTS, 0x0B), SPORTS_ROWING(Type.SPORTS, 0x0D), - SPORTS_ROPESKIPPING(Type.SPORTS, 0x0E), // TODO + SPORTS_JUMP_ROPING(Type.SPORTS, 0x0E), SPORTS_OUTDOOR_WALKING_V2(Type.SPORTS, 0x16), SPORTS_OUTDOOR_CYCLING(Type.SPORTS, 0x17), ; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/WorkoutSummaryParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/WorkoutSummaryParser.java index 2a13cd6b8..9b36ba10e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/WorkoutSummaryParser.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/WorkoutSummaryParser.java @@ -45,6 +45,9 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries. import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.STEPS; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.STROKES; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.STROKE_RATE_AVG; +import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.JUMPS; +import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.JUMP_RATE_AVG; +import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.JUMP_RATE_MAX; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.SWIM_STYLE; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.SWOLF_AVG; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.TIME_END; @@ -66,6 +69,8 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries. import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_STEPS; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_STROKES; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_STROKES_PER_MINUTE; +import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_JUMPS; +import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_JUMPS_PER_MINUTE; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.UNIT_UNIX_EPOCH_SECONDS; import static nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries.WORKOUT_LOAD; import static nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.impl.XiaomiSimpleActivityParser.XIAOMI_WORKOUT_TYPE; @@ -225,6 +230,10 @@ public class WorkoutSummaryParser extends XiaomiActivityParser implements Activi summary.setActivityKind(ActivityKind.ROWING.getCode()); parser = getRowingParser(fileId); break; + case SPORTS_JUMP_ROPING: + summary.setActivityKind(ActivityKind.JUMP_ROPING.getCode()); + parser = getJumpRopingParser(fileId); + break; default: LOG.warn("No workout summary parser for {}", fileId.getSubtypeCode()); break; @@ -794,4 +803,46 @@ public class WorkoutSummaryParser extends XiaomiActivityParser implements Activi return builder.build(); } + + @Nullable + private XiaomiSimpleActivityParser getJumpRopingParser(final XiaomiActivityFileId fileId) { + final int version = fileId.getVersion(); + final int headerSize; + switch (version) { + case 3: + headerSize = 5; + break; + default: + LOG.warn("Unable to parse workout summary version {}", fileId.getVersion()); + return null; + } + + final XiaomiSimpleActivityParser.Builder builder = new XiaomiSimpleActivityParser.Builder(); + builder.setHeaderSize(headerSize); + builder.addInt(TIME_START, UNIT_UNIX_EPOCH_SECONDS); + builder.addInt(TIME_END, UNIT_UNIX_EPOCH_SECONDS); + builder.addInt(ACTIVE_SECONDS, UNIT_SECONDS); + builder.addShort(CALORIES_BURNT, UNIT_KCAL); + builder.addByte(HR_AVG, UNIT_BPM); + builder.addByte(HR_MAX, UNIT_BPM); + builder.addByte(HR_MIN, UNIT_BPM); + builder.addUnknown(7); + builder.addInt(HR_ZONE_EXTREME, UNIT_SECONDS); + builder.addInt(HR_ZONE_ANAEROBIC, UNIT_SECONDS); + builder.addInt(HR_ZONE_AEROBIC, UNIT_SECONDS); + builder.addInt(HR_ZONE_FAT_BURN, UNIT_SECONDS); + builder.addInt(HR_ZONE_WARM_UP, UNIT_SECONDS); + builder.addUnknown(2); + builder.addInt(JUMPS, UNIT_JUMPS); + builder.addShort(JUMP_RATE_AVG, UNIT_JUMPS_PER_MINUTE); + builder.addUnknown(2); + builder.addShort(JUMP_RATE_MAX, UNIT_JUMPS_PER_MINUTE); + builder.addUnknown(43); + builder.addUnknown(2); // configuredJumpsGoal, UNIT_JUMPS + builder.addUnknown(2); + + return builder.build(); + } } + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 41549e197..a51cd498e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2246,6 +2246,9 @@ Average Stroke Rate Max Stroke Rate Total Strokes + Average Jump Rate + Max Jump Rate + Total Jumps Average Lap Pace SWOLF Average swolf @@ -2301,6 +2304,8 @@ str/s str/min str + jumps/min + jumps sec milliseconds ms @@ -2319,6 +2324,7 @@ Pace Strokes + Jumps Swimming Distance Elevation