1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2025-02-14 19:36:48 +01:00

Moyoung: Support starting phone GPS tracker from watch

This commit is contained in:
Arjan Schrijver 2025-02-06 20:27:07 +01:00
parent b889addc0a
commit be62909db5
4 changed files with 66 additions and 51 deletions

View File

@ -217,6 +217,7 @@ public abstract class AbstractMoyoungDeviceCoordinator extends AbstractBLEDevice
final List<Integer> health = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH);
health.add(R.xml.devicesettings_heartrate_interval);
health.add(R.xml.devicesettings_inactivity_with_steps);
health.add(R.xml.devicesettings_workout_start_on_phone);
return deviceSpecificSettings;
}

View File

@ -19,9 +19,12 @@ package nodomain.freeyourgadget.gadgetbridge.devices.moyoung;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
@ -320,6 +323,39 @@ public class MoyoungConstants {
public static final byte TRAINING_TYPE_TENNIS = 9;
public static final byte TRAINING_TYPE_RUGBY = 10;
public static final byte TRAINING_TYPE_GOLF = 11;
public static final byte TRAINING_TYPE_YOGA = 12;
public static final byte TRAINING_TYPE_FITNESS = 13;
public static final byte TRAINING_TYPE_DANCING = 14;
public static final byte TRAINING_TYPE_BASEBALL = 15;
public static final byte TRAINING_TYPE_ELLIPTICAL = 16;
public static final byte TRAINING_TYPE_INDOOR_CYCLING = 17;
public static final byte TRAINING_TYPE_FREE_EXERCISE = 18;
public static final byte TRAINING_TYPE_ROWING_MACHINE = 19;
public static Map<Byte, ActivityKind> WORKOUT_TYPES_TO_ACTIVITY_KIND = new HashMap<Byte, ActivityKind>() {
{
put(TRAINING_TYPE_WALK, ActivityKind.WALKING);
put(TRAINING_TYPE_RUN, ActivityKind.RUNNING);
put(TRAINING_TYPE_BIKING, ActivityKind.CYCLING);
put(TRAINING_TYPE_ROPE, ActivityKind.JUMP_ROPING);
put(TRAINING_TYPE_BADMINTON, ActivityKind.BADMINTON);
put(TRAINING_TYPE_BASKETBALL, ActivityKind.BASKETBALL);
put(TRAINING_TYPE_FOOTBALL, ActivityKind.SOCCER);
put(TRAINING_TYPE_SWIM, ActivityKind.SWIMMING);
put(TRAINING_TYPE_MOUNTAINEERING, ActivityKind.MOUNTAINEERING);
put(TRAINING_TYPE_TENNIS, ActivityKind.TENNIS);
put(TRAINING_TYPE_RUGBY, ActivityKind.RUGBY);
put(TRAINING_TYPE_GOLF, ActivityKind.GOLF);
put(TRAINING_TYPE_YOGA, ActivityKind.YOGA);
put(TRAINING_TYPE_FITNESS, ActivityKind.FITNESS_EXERCISES);
put(TRAINING_TYPE_DANCING, ActivityKind.DANCE);
put(TRAINING_TYPE_BASEBALL, ActivityKind.BASEBALL);
put(TRAINING_TYPE_ELLIPTICAL, ActivityKind.ELLIPTICAL_TRAINER);
put(TRAINING_TYPE_INDOOR_CYCLING, ActivityKind.INDOOR_CYCLING);
put(TRAINING_TYPE_FREE_EXERCISE, ActivityKind.FREE_TRAINING);
put(TRAINING_TYPE_ROWING_MACHINE, ActivityKind.ROWING_MACHINE);
}
};
// The watch stores all dates in GMT+8 time zone with seconds resolution
// These helper functions convert between the watch time representation and local system representation

View File

@ -60,18 +60,6 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
public static final int SOURCE_BATTERY = 7; // battery report
public static final int ACTIVITY_NOT_MEASURED = -1;
public static final int ACTIVITY_TRAINING_WALK = MoyoungConstants.TRAINING_TYPE_WALK;
public static final int ACTIVITY_TRAINING_RUN = MoyoungConstants.TRAINING_TYPE_RUN;
public static final int ACTIVITY_TRAINING_BIKING = MoyoungConstants.TRAINING_TYPE_BIKING;
public static final int ACTIVITY_TRAINING_ROPE = MoyoungConstants.TRAINING_TYPE_ROPE;
public static final int ACTIVITY_TRAINING_BADMINTON = MoyoungConstants.TRAINING_TYPE_BADMINTON;
public static final int ACTIVITY_TRAINING_BASKETBALL = MoyoungConstants.TRAINING_TYPE_BASKETBALL;
public static final int ACTIVITY_TRAINING_FOOTBALL = MoyoungConstants.TRAINING_TYPE_FOOTBALL;
public static final int ACTIVITY_TRAINING_SWIM = MoyoungConstants.TRAINING_TYPE_SWIM;
public static final int ACTIVITY_TRAINING_MOUNTAINEERING = MoyoungConstants.TRAINING_TYPE_MOUNTAINEERING;
public static final int ACTIVITY_TRAINING_TENNIS = MoyoungConstants.TRAINING_TYPE_TENNIS;
public static final int ACTIVITY_TRAINING_RUGBY = MoyoungConstants.TRAINING_TYPE_RUGBY;
public static final int ACTIVITY_TRAINING_GOLF = MoyoungConstants.TRAINING_TYPE_GOLF;
public static final int ACTIVITY_SLEEP_LIGHT = 16;
public static final int ACTIVITY_SLEEP_RESTFUL = 17;
public static final int ACTIVITY_SLEEP_START = 18;
@ -122,21 +110,8 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
return ActivityKind.REM_SLEEP;
else if (rawType == ACTIVITY_SLEEP_START || rawType == ACTIVITY_SLEEP_END)
return ActivityKind.NOT_MEASURED;
else if (rawType == ACTIVITY_TRAINING_WALK)
return ActivityKind.WALKING;
else if (rawType == ACTIVITY_TRAINING_RUN)
return ActivityKind.RUNNING;
else if (rawType == ACTIVITY_TRAINING_BIKING)
return ActivityKind.CYCLING;
else if (rawType == ACTIVITY_TRAINING_SWIM)
return ActivityKind.SWIMMING;
else if (rawType == ACTIVITY_TRAINING_ROPE || rawType == ACTIVITY_TRAINING_BADMINTON ||
rawType == ACTIVITY_TRAINING_BASKETBALL || rawType == ACTIVITY_TRAINING_FOOTBALL ||
rawType == ACTIVITY_TRAINING_MOUNTAINEERING || rawType == ACTIVITY_TRAINING_TENNIS ||
rawType == ACTIVITY_TRAINING_RUGBY || rawType == ACTIVITY_TRAINING_GOLF)
return ActivityKind.EXERCISE;
else
return ActivityKind.ACTIVITY;
return MoyoungConstants.WORKOUT_TYPES_TO_ACTIVITY_KIND.getOrDefault((byte) rawType, ActivityKind.ACTIVITY);
}
@Override

View File

@ -83,6 +83,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSett
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingEnum;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingRemindersToMove;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingTimeRange;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.QHybridConstants;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
@ -92,6 +93,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungHeartRateSample;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSample;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSpo2Sample;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
@ -276,7 +278,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE)
{
int heartRate = payload[0];
int heartRate = payload[0] & 0xff;
LOG.info("Measure heart rate finished: " + heartRate + " BPM");
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -303,7 +305,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_OXYGEN)
{
int percent = payload[0];
int percent = payload[0] & 0xff;
LOG.info("Measure blood oxygen finished: " + percent + "%");
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -327,9 +329,9 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_PRESSURE)
{
int dataUnknown = payload[0];
int data1 = payload[1];
int data2 = payload[2];
int dataUnknown = payload[0] & 0xff;
int data1 = payload[1] & 0xff;
int data2 = payload[2] & 0xff;
LOG.info("Measure blood pressure finished: " + data1 + "/" + data2 + " (" + dataUnknown + ")");
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -353,6 +355,25 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_START_STOP_MEASURE_DYNAMIC_RATE) {
final boolean startOnPhone = getDevicePrefs().getBoolean(DeviceSettingsPreferenceConst.PREF_WORKOUT_START_ON_PHONE, false);
// Training on the watch started or finished
int type = payload[0] & 0xff;
if (type == 0xff) {
LOG.info("Training on the watch stopped");
if (startOnPhone) {
OpenTracksController.stopRecording(getContext());
}
} else {
final ActivityKind activityKind = MoyoungConstants.WORKOUT_TYPES_TO_ACTIVITY_KIND.getOrDefault(payload[0], ActivityKind.ACTIVITY);
LOG.info("Training on the watch started (type {} = {})", type, getContext().getString(activityKind.getLabel()));
if (startOnPhone) {
OpenTracksController.startRecording(getContext(), activityKind);
}
}
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_LAST_DYNAMIC_RATE)
{
// Training on the watch just finished and it wants us to fetch the details
@ -362,6 +383,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
} catch (IOException e) {
LOG.error("TrainingFinishedDataOperation failed: ", e);
}
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1)
@ -1309,26 +1331,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
summary.setUser(user);
ActivityKind gbType = provider.normalizeType(type);
String name;
if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_ROPE)
name = "Rope";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_BADMINTON)
name = "Badminton";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_BASKETBALL)
name = "Basketball";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_FOOTBALL)
name = "Football";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_MOUNTAINEERING)
name = "Mountaineering";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_TENNIS)
name = "Tennis";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_RUGBY)
name = "Rugby";
else if (type == MoyoungActivitySampleProvider.ACTIVITY_TRAINING_GOLF)
name = "Golf";
else
name = gbType.name();
summary.setName(name);
summary.setName(gbType.name());
summary.setActivityKind(gbType.getCode());
summary.setStartTime(startTime);