1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-07-03 11:33:19 +02:00

Garmin: Map all supported workout types

This commit is contained in:
José Rebelo 2024-05-05 14:42:04 +01:00 committed by Daniele Gobbetti
parent 8be679d1fd
commit 553f6171e6
4 changed files with 165 additions and 23 deletions

View File

@ -49,6 +49,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryData;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.enums.GarminSport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionSleepStage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitEvent;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFileId;
@ -61,6 +62,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitStressLevel;
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTimeInZone;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Optional;
public class FitImporter {
private static final Logger LOG = LoggerFactory.getLogger(FitImporter.class);
@ -301,29 +303,51 @@ public class FitImporter {
}
private int getActivityKind(final Integer sport, final Integer subsport) {
// TODO map all sports
if (sport != null) {
switch (sport) {
case 2:
return ActivityKind.TYPE_CYCLING;
case 4: // fitness_equipment
case 10: // training
if (subsport != null) {
switch (subsport) {
case 15:
return ActivityKind.TYPE_ELLIPTICAL_TRAINER;
case 20:
return ActivityKind.TYPE_STRENGTH_TRAINING;
default:
LOG.warn("Unknown sub sport {} for {}", subsport, sport);
}
break;
}
case 11:
return ActivityKind.TYPE_WALKING;
default:
LOG.warn("Unknown sport {}", sport);
}
final Optional<GarminSport> garminSport = GarminSport.fromCodes(sport, subsport);
if (garminSport.isEmpty()) {
LOG.warn("Unknown garmin sport {}/{}", sport, subsport);
return ActivityKind.TYPE_UNKNOWN;
}
switch (garminSport.get()) {
case RUN:
case PUSH_RUN_SPEED:
case INDOOR_PUSH_RUN_SPEED:
case INDOOR_TRACK:
return ActivityKind.TYPE_RUNNING;
case TREADMILL:
return ActivityKind.TYPE_TREADMILL;
case E_BIKE:
case BIKE:
return ActivityKind.TYPE_CYCLING;
case BIKE_INDOOR:
return ActivityKind.TYPE_INDOOR_CYCLING;
case ELLIPTICAL:
return ActivityKind.TYPE_ELLIPTICAL_TRAINER;
case STAIR_STEPPER:
case PILATES:
case CARDIO:
return ActivityKind.TYPE_EXERCISE;
case POOL_SWIM:
return ActivityKind.TYPE_SWIMMING;
case OPEN_WATER:
return ActivityKind.TYPE_SWIMMING_OPENWATER;
case SOCCER:
return ActivityKind.TYPE_SOCCER;
case STRENGTH:
return ActivityKind.TYPE_STRENGTH_TRAINING;
case YOGA:
return ActivityKind.TYPE_YOGA;
case WALK:
case WALK_INDOOR:
case PUSH_WALK_SPEED:
case INDOOR_PUSH_WALK_SPEED:
return ActivityKind.TYPE_WALKING;
case HIKE:
return ActivityKind.TYPE_HIKING;
case CLIMB_INDOOR:
case BOULDERING:
return ActivityKind.TYPE_CLIMBING;
}
return ActivityKind.TYPE_UNKNOWN;

View File

@ -0,0 +1,83 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.enums;
import nodomain.freeyourgadget.gadgetbridge.util.Optional;
// Taken from CHANGELOG.fit of a Venu 3
public enum GarminSport {
NAVIGATE(0, 50),
RUN(1, 0),
TREADMILL(1, 1),
INDOOR_TRACK(1, 45),
BIKE(2, 0),
BIKE_INDOOR(2, 6),
HANDCYCLING(2, 12),
E_BIKE(2, 28),
HANDCYCLING_INDOOR(2, 88),
ELLIPTICAL(4, 15),
STAIR_STEPPER(4, 16),
PILATES(4, 44),
POOL_SWIM(5, 17),
OPEN_WATER(5, 18),
SOCCER(7, 0),
TENNIS(8, 0),
PLATFORM_TENNIS(8, 93),
TABLE_TENNIS(8, 97),
STRENGTH(10, 20),
CARDIO(10, 26),
YOGA(10, 43),
BREATHWORK(10, 62),
WALK(11, 0),
WALK_INDOOR(11, 27),
XC_CLASSIC_SKI(12, 0),
SKI(13, 0),
SNOWBOARD(14, 0),
HIKE(17, 0),
CLIMB_INDOOR(31, 68),
BOULDERING(31, 69),
SNOWSHOE(35, 0),
STAND_UP_PADDLEBOARDING(37, 0),
SOFTBALL(50, 0),
HEALTH_SNAPSHOT(60, 0),
HIIT(62, 0),
PICKLEBALL(64, 84),
PADEL(64, 85),
SQUASH(64, 94),
RACQUETBALL(64, 96),
PUSH_WALK_SPEED(65, 0),
INDOOR_PUSH_WALK_SPEED(65, 86),
PUSH_RUN_SPEED(66, 0),
INDOOR_PUSH_RUN_SPEED(66, 87),
DISC_GOLF(69, 0),
ULTIMATE_DISC(69, 92),
RUGBY(72, 0),
LACROSSE(74, 0),
VOLLEYBALL(75, 0),
MIXED_MARTIAL_ARTS(80, 0), // aka MMA
;
private final int type;
private final int subtype;
GarminSport(final int type, final int subtype) {
this.type = type;
this.subtype = subtype;
}
public int getType() {
return type;
}
public int getSubtype() {
return subtype;
}
public static Optional<GarminSport> fromCodes(final int type, final int subtype) {
for (final GarminSport value : GarminSport.values()) {
if (value.getType() == type && value.getSubtype() == subtype) {
return Optional.of(value);
}
}
return Optional.empty();
}
}

View File

@ -40,6 +40,10 @@ public final class Optional<T> {
return value;
}
public boolean isEmpty() {
return value == null;
}
public boolean isPresent() {
return value != null;
}

View File

@ -0,0 +1,31 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.enums;
import static org.junit.Assert.assertTrue;
import android.util.Pair;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.test.TestBase;
public class GarminSportTest extends TestBase {
@Test
public void testNoDuplicates() {
// Ensure there are no duplicated sports with the same type and subtype
final Set<GarminSport> duplicates = new HashSet<>();
final Set<Pair<Integer, Integer>> seen = new HashSet<>();
for (final GarminSport sport : GarminSport.values()) {
final Pair<Integer, Integer> codePair = Pair.create(sport.getType(), sport.getSubtype());
if (seen.contains(codePair)) {
duplicates.add(sport);
}
seen.add(codePair);
}
assertTrue("Duplicated sport codes: " + duplicates, duplicates.isEmpty());
}
}