diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java index 4a05e2cef..fdda9a68f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java @@ -19,6 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid; import java.util.HashMap; import java.util.Map; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; + public final class QHybridConstants { public static final String HYBRIDHR_WATCHFACE_VERSION = "1.6"; public static final int HYBRID_HR_WATCHFACE_WIDGET_SIZE = 76; @@ -39,20 +41,12 @@ public final class QHybridConstants { } }; - public static Map WORKOUT_TYPES_TO_OPENTRACKS_CATEGORY = new HashMap() { + public static Map WORKOUT_TYPES_TO_ACTIVITY_KIND = new HashMap() { { - put(1, "running"); - put(2, "cycling"); - put(8, "walking"); - put(12, "hiking"); - } - }; - public static Map WORKOUT_TYPES_TO_OPENTRACKS_ICON = new HashMap() { - { - put(1, "RUN"); - put(2, "BIKE"); - put(8, "WALK"); - put(12, "WALK"); + put(1, ActivityKind.TYPE_RUNNING); + put(2, ActivityKind.TYPE_CYCLING); + put(8, ActivityKind.TYPE_WALKING); + put(12, ActivityKind.TYPE_HIKING); } }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/opentracks/OpenTracksController.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/opentracks/OpenTracksController.java index 08c8736fd..9b0d20bdb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/opentracks/OpenTracksController.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/opentracks/OpenTracksController.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; @@ -60,7 +61,7 @@ public class OpenTracksController extends Activity { private static final String ACTION_DASHBOARD = "Intent.OpenTracks-Dashboard"; private static final String ACTION_DASHBOARD_PAYLOAD = ACTION_DASHBOARD + ".Payload"; - private final Logger LOG = LoggerFactory.getLogger(OpenTracksController.class); + private static final Logger LOG = LoggerFactory.getLogger(OpenTracksController.class); @Override public void onCreate(Bundle bundle) { @@ -111,7 +112,25 @@ public class OpenTracksController extends Activity { sendIntent(context, "de.dennisguse.opentracks.publicapi.StartRecording", null, null); } - public static void startRecording(Context context, String category, String icon) { + public static void startRecording(Context context, int activityKind) { + final String category = ActivityKind.asString(activityKind, context); + final String icon; + switch (activityKind) { + case ActivityKind.TYPE_CYCLING: + icon = "BIKE"; + break; + case ActivityKind.TYPE_HIKING: + case ActivityKind.TYPE_WALKING: + icon = "WALK"; + break; + case ActivityKind.TYPE_RUNNING: + icon = "RUN"; + break; + default: + LOG.warn("Unmapped activity kind icon for {}", String.format("0x%X", activityKind)); + icon = null; + } + sendIntent(context, "de.dennisguse.opentracks.publicapi.StartRecording", category, icon); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java index 4388d6509..68c6409c5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java @@ -130,6 +130,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.DoNotDisturb; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; @@ -2027,14 +2028,18 @@ public abstract class Huami2021Support extends HuamiSupport { case WORKOUT_CMD_APP_OPEN: final Huami2021WorkoutTrackActivityType activityType = Huami2021WorkoutTrackActivityType.fromCode(payload[3]); final boolean workoutNeedsGps = (payload[2] == 1); + final int activityKind; if (activityType == null) { LOG.warn("Unknown workout activity type {}", String.format("0x%x", payload[3])); + activityKind = ActivityKind.TYPE_UNKNOWN; + } else { + activityKind = activityType.toActivityKind(); } LOG.info("Workout starting on band: {}, needs gps = {}", activityType, workoutNeedsGps); - onWorkoutOpen(workoutNeedsGps); + onWorkoutOpen(workoutNeedsGps, activityKind); return; case WORKOUT_CMD_STATUS: switch (payload[1]) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021WorkoutTrackActivityType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021WorkoutTrackActivityType.java index ce1e085fc..c584af07b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021WorkoutTrackActivityType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021WorkoutTrackActivityType.java @@ -16,6 +16,11 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; + /** * The workout types, used to start / when workout tracking starts on the band. */ @@ -38,6 +43,8 @@ public enum Huami2021WorkoutTrackActivityType { Yoga(0x3c), ; + private static final Logger LOG = LoggerFactory.getLogger(Huami2021WorkoutTrackActivityType.class); + private final byte code; Huami2021WorkoutTrackActivityType(final int code) { @@ -48,6 +55,39 @@ public enum Huami2021WorkoutTrackActivityType { return code; } + public int toActivityKind() { + switch (this) { + case Badminton: + return ActivityKind.TYPE_BADMINTON; + case Elliptical: + return ActivityKind.TYPE_ELLIPTICAL_TRAINER; + case IndoorCycling: + return ActivityKind.TYPE_INDOOR_CYCLING; + case JumpRope: + return ActivityKind.TYPE_JUMP_ROPING; + case OutdoorCycling: + return ActivityKind.TYPE_CYCLING; + case OutdoorRunning: + return ActivityKind.TYPE_RUNNING; + case PoolSwimming: + return ActivityKind.TYPE_SWIMMING; + case Rowing: + return ActivityKind.TYPE_ROWING_MACHINE; + case Soccer: + return ActivityKind.TYPE_SOCCER; + case Treadmill: + return ActivityKind.TYPE_TREADMILL; + case Walking: + return ActivityKind.TYPE_WALKING; + case Yoga: + return ActivityKind.TYPE_YOGA; + } + + LOG.warn("Unmapped workout type {}", this); + + return ActivityKind.TYPE_UNKNOWN; + } + public static Huami2021WorkoutTrackActivityType fromCode(final byte code) { for (final Huami2021WorkoutTrackActivityType type : values()) { if (type.getCode() == code) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index 27efd4710..ecdd1e435 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -110,6 +110,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationManager; import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; @@ -1886,16 +1887,20 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements break; case HuamiDeviceEvent.WORKOUT_STARTING: final HuamiWorkoutTrackActivityType activityType = HuamiWorkoutTrackActivityType.fromCode(value[3]); + final int activityKind; if (activityType == null) { LOG.warn("Unknown workout activity type {}", String.format("0x%02x", value[3])); + activityKind = ActivityKind.TYPE_UNKNOWN; + } else { + activityKind = activityType.toActivityKind(); } final boolean needsGps = value[2] == 1; LOG.info("Workout starting on band: {}, needs gps = {}", activityType, needsGps); - onWorkoutOpen(needsGps); + onWorkoutOpen(needsGps, activityKind); break; default: @@ -1909,13 +1914,19 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements */ private boolean workoutNeedsGps = false; + /** + * Track the {@link nodomain.freeyourgadget.gadgetbridge.model.ActivityKind} that was opened, for the same reasons as {@code workoutNeedsGps}. + */ + private int workoutActivityKind = ActivityKind.TYPE_UNKNOWN; + /** * Track the last time we actually sent a gps location. We need to signal that GPS as re-acquired if the last update was too long ago. */ private long lastPhoneGpsSent = 0; - protected void onWorkoutOpen(final boolean needsGps) { + protected void onWorkoutOpen(final boolean needsGps, final int activityKind) { this.workoutNeedsGps = needsGps; + this.workoutActivityKind = activityKind; final boolean sendGpsToBand = HuamiCoordinator.getWorkoutSendGpsToBand(getDevice().getAddress()); @@ -1936,7 +1947,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements if (workoutNeedsGps && startOnPhone) { LOG.info("Starting OpenTracks recording"); - OpenTracksController.startRecording(getContext()); + OpenTracksController.startRecording(getContext(), workoutActivityKind); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiWorkoutTrackActivityType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiWorkoutTrackActivityType.java index 0757d70c6..184cb2875 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiWorkoutTrackActivityType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiWorkoutTrackActivityType.java @@ -18,6 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami; import java.util.Locale; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; + /** * The workout types, used to start / when workout tracking starts on the band. */ @@ -44,6 +46,33 @@ public enum HuamiWorkoutTrackActivityType { return code; } + public int toActivityKind() { + switch (this) { + case Elliptical: + return ActivityKind.TYPE_ELLIPTICAL_TRAINER; + case IndoorCycling: + return ActivityKind.TYPE_INDOOR_CYCLING; + case JumpRope: + return ActivityKind.TYPE_JUMP_ROPING; + case OutdoorCycling: + return ActivityKind.TYPE_CYCLING; + case OutdoorRunning: + return ActivityKind.TYPE_RUNNING; + case PoolSwimming: + return ActivityKind.TYPE_SWIMMING; + case RowingMachine: + return ActivityKind.TYPE_ROWING_MACHINE; + case Treadmill: + return ActivityKind.TYPE_TREADMILL; + case Walking: + return ActivityKind.TYPE_WALKING; + case Yoga: + return ActivityKind.TYPE_YOGA; + } + + return ActivityKind.TYPE_UNKNOWN; + } + public static HuamiWorkoutTrackActivityType fromCode(final byte code) { for (final HuamiWorkoutTrackActivityType type : values()) { if (type.getCode() == code) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/workout/WorkoutRequestHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/workout/WorkoutRequestHandler.java index 56d419756..23bc2803c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/workout/WorkoutRequestHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/workout/WorkoutRequestHandler.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.QHybridConstants; import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; public class WorkoutRequestHandler { public static void addStateResponse(JSONObject workoutResponse, String type, String msg) throws JSONException { @@ -42,11 +43,15 @@ public class WorkoutRequestHandler { JSONObject workoutResponse = new JSONObject(); if (workoutRequest.optString("state").equals("started") && workoutRequest.optString("gps").equals("on")) { int activityType = workoutRequest.optInt("activity", -1); - String activityCategory = QHybridConstants.WORKOUT_TYPES_TO_OPENTRACKS_CATEGORY.get(activityType); - String activityIcon = QHybridConstants.WORKOUT_TYPES_TO_OPENTRACKS_ICON.get(activityType); - LOG.info("Workout started, activity type is " + activityType + "/" + activityCategory); + final int activityKind; + if (QHybridConstants.WORKOUT_TYPES_TO_ACTIVITY_KIND.containsKey(activityType)) { + activityKind = QHybridConstants.WORKOUT_TYPES_TO_ACTIVITY_KIND.get(activityType); + } else { + activityKind = ActivityKind.TYPE_UNKNOWN; + } + LOG.info("Workout started, activity type is " + activityType + "/" + activityKind); addStateResponse(workoutResponse, "success", ""); - OpenTracksController.startRecording(context, activityCategory, activityIcon); + OpenTracksController.startRecording(context, activityKind); } else if (workoutRequest.optString("type").equals("req_distance")) { long timeSecs = GBApplication.app().getOpenTracksObserver().getTimeMillisChange() / 1000; float distanceCM = GBApplication.app().getOpenTracksObserver().getDistanceMeterChange() * 100;