From 487afa6814c618dac64746b6f4ec8948b745f824 Mon Sep 17 00:00:00 2001 From: Arjan Schrijver Date: Fri, 30 Aug 2024 21:50:17 +0200 Subject: [PATCH] Moyoung: Code and settings improvements --- .../AbstractMoyoungDeviceCoordinator.java | 59 +++++++++---- .../devices/moyoung/MoyoungConstants.java | 6 ++ .../moyoung/settings/MoyoungSettingEnum.java | 4 +- .../settings/MoyoungSettingLanguage.java | 12 ++- .../service/btle/BLETypeConversions.java | 8 ++ .../devices/moyoung/MoyoungDeviceSupport.java | 82 ++++--------------- .../moyoung/QuerySettingsOperation.java | 8 +- 7 files changed, 91 insertions(+), 88 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/AbstractMoyoungDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/AbstractMoyoungDeviceCoordinator.java index 6fe272d6e..d0d5abd05 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/AbstractMoyoungDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/AbstractMoyoungDeviceCoordinator.java @@ -23,13 +23,18 @@ import android.os.ParcelUuid; import androidx.annotation.NonNull; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; import de.greenrobot.dao.query.QueryBuilder; import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.R; -import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings; +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen; +import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungActivitySampleProvider; @@ -58,7 +63,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample; import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.moyoung.MoyoungDeviceSupport; -public abstract class AbstractMoyoungDeviceCoordinator extends AbstractDeviceCoordinator { +public abstract class AbstractMoyoungDeviceCoordinator extends AbstractBLEDeviceCoordinator { @NonNull @Override @@ -160,11 +165,12 @@ public abstract class AbstractMoyoungDeviceCoordinator extends AbstractDeviceCoo return true; } - private static final MoyoungSetting[] MOYOUNG_SETTINGS = new MoyoungSetting[] { + private static final MoyoungSetting[] MOYOUNG_SETTINGS = { new MoyoungSettingUserInfo("USER_INFO", MoyoungConstants.CMD_SET_USER_INFO), new MoyoungSettingByte("STEP_LENGTH", (byte)-1, MoyoungConstants.CMD_SET_STEP_LENGTH), // (*) new MoyoungSettingEnum<>("DOMINANT_HAND", MoyoungConstants.CMD_QUERY_DOMINANT_HAND, MoyoungConstants.CMD_SET_DOMINANT_HAND, MoyoungEnumDominantHand.class), new MoyoungSettingInt("GOAL_STEP", MoyoungConstants.CMD_QUERY_GOAL_STEP, MoyoungConstants.CMD_SET_GOAL_STEP), + new MoyoungSettingByte("HR_AUTO_INTERVAL", MoyoungConstants.CMD_QUERY_TIMING_MEASURE_HEART_RATE, MoyoungConstants.CMD_SET_TIMING_MEASURE_HEART_RATE), new MoyoungSettingEnum<>("DEVICE_VERSION", MoyoungConstants.CMD_QUERY_DEVICE_VERSION, MoyoungConstants.CMD_SET_DEVICE_VERSION, MoyoungEnumDeviceVersion.class), new MoyoungSettingLanguage("DEVICE_LANGUAGE", MoyoungConstants.CMD_QUERY_DEVICE_LANGUAGE, MoyoungConstants.CMD_SET_DEVICE_LANGUAGE), @@ -187,24 +193,43 @@ public abstract class AbstractMoyoungDeviceCoordinator extends AbstractDeviceCoo new MoyoungSettingBool("BREATHING_LIGHT", MoyoungConstants.CMD_QUERY_BREATHING_LIGHT, MoyoungConstants.CMD_SET_BREATHING_LIGHT) }; + @Override - public int[] getSupportedDeviceSpecificSettings(GBDevice device) { - return new int[]{ - //R.xml.devicesettings_steplength, // TODO is this needed? does it work? write-only so hard to tell - R.xml.devicesettings_moyoung_device_version, - R.xml.devicesettings_moyoung_language, - R.xml.devicesettings_timeformat, - R.xml.devicesettings_measurementsystem, - R.xml.devicesettings_moyoung_watchface, - //R.xml.devicesettings_moyoung_othermessage, // not implemented because this doesn't really do anything on the watch side, only enables/disables sending of "other" notifications in the app (no idea why they store the setting on the watch) - R.xml.devicesettings_liftwrist_display, - R.xml.devicesettings_moyoung_sedentary_reminder, - R.xml.devicesettings_donotdisturb_no_auto, - //R.xml.devicesettings_moyoung_breathinglight, // No idea what this does but it doesn't seem to change anything - R.xml.devicesettings_world_clocks, + public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) { + final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings(); + final List generic = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.GENERIC); + generic.add(R.xml.devicesettings_moyoung_device_version); + generic.add(R.xml.devicesettings_colmi_r0x); + generic.add(R.xml.devicesettings_timeformat); + generic.add(R.xml.devicesettings_measurementsystem); + generic.add(R.xml.devicesettings_moyoung_watchface); + generic.add(R.xml.devicesettings_liftwrist_display); + generic.add(R.xml.devicesettings_moyoung_sedentary_reminder); + generic.add(R.xml.devicesettings_donotdisturb_no_auto); + generic.add(R.xml.devicesettings_world_clocks); + generic.add(R.xml.devicesettings_sync_calendar); + return deviceSpecificSettings; + } + + @Override + public String[] getSupportedLanguageSettings(GBDevice device) { + return new String[]{ + "en_US", + "nl_NL", }; } + @Override + public List getHeartRateMeasurementIntervals() { + return Arrays.asList( + HeartRateCapability.MeasurementInterval.OFF, + HeartRateCapability.MeasurementInterval.MINUTES_5, + HeartRateCapability.MeasurementInterval.MINUTES_10, + HeartRateCapability.MeasurementInterval.MINUTES_15, + HeartRateCapability.MeasurementInterval.MINUTES_30 + ); + } + public MoyoungSetting[] getSupportedSettings() { return MOYOUNG_SETTINGS; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java index 3cfeaee05..6032532a2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java @@ -145,6 +145,12 @@ public class MoyoungConstants { public static final byte CMD_SET_TIMING_MEASURE_HEART_RATE = 31; // (*) {i}, i >= 0, 0 is disabled public static final byte CMD_START_STOP_MEASURE_DYNAMIC_RATE = 104; // (*) {enabled ? 0 : -1} + public static final byte HR_INTERVAL_OFF = 0; + public static final byte HR_INTERVAL_5MIN = 1; + public static final byte HR_INTERVAL_10MIN = 2; + public static final byte HR_INTERVAL_20MIN = 4; + public static final byte HR_INTERVAL_30MIN = 6; + public static final byte CMD_TRIGGER_MEASURE_BLOOD_PRESSURE = 105; // (?) {0, 0, 0} to start, {-1, -1, -1} to stop -> {unused?, num1, num2} public static final byte CMD_TRIGGER_MEASURE_BLOOD_OXYGEN = 107; // (?) {start ? 0 : -1} -> {num} public static final byte CMD_TRIGGER_MEASURE_HEARTRATE = 109; // {start ? 0 : -1} -> {bpm} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingEnum.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingEnum.java index 60e8d5dbf..8e551b9cd 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingEnum.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingEnum.java @@ -42,8 +42,8 @@ public class MoyoungSettingEnum & MoyoungEnum> extends Moyoun @Override public T decode(byte[] data) { - if (data.length != 1) - throw new IllegalArgumentException("Wrong data length, should be 1, was " + data.length); + if (data.length < 1) + throw new IllegalArgumentException("Wrong data length, should be at least 1, was " + data.length); return findByValue(data[0]); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingLanguage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingLanguage.java index 99bbee686..a43b33d10 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingLanguage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/settings/MoyoungSettingLanguage.java @@ -18,18 +18,25 @@ package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings; import android.util.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import nodomain.freeyourgadget.gadgetbridge.service.devices.moyoung.QuerySettingsOperation; + public class MoyoungSettingLanguage extends MoyoungSettingEnum { + private static final Logger LOG = LoggerFactory.getLogger(MoyoungSettingLanguage.class); + public MoyoungSettingLanguage(String name, byte cmdQuery, byte cmdSet) { super(name, cmdQuery, cmdSet, MoyoungEnumLanguage.class); } private Pair decodeData(byte[] data) { - if (data.length != 5) - throw new IllegalArgumentException("Wrong data length, should be 5, was " + data.length); + if (data.length < 5) + throw new IllegalArgumentException("Wrong data length, should be at least 5, was " + data.length); byte[] current = new byte[] { data[0] }; byte[] supported = new byte[] { data[1], data[2], data[3], data[4] }; @@ -48,6 +55,7 @@ public class MoyoungSettingLanguage extends MoyoungSettingEnum heartRateProfile; private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo(); private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo(); - private final IntentListener mListener = new IntentListener() { - @Override - public void notify(Intent intent) { - String s = intent.getAction(); - if (Objects.equals(s, DeviceInfoProfile.ACTION_DEVICE_INFO)) { - handleDeviceInfo((DeviceInfo) intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO)); - } - if (Objects.equals(s, BatteryInfoProfile.ACTION_BATTERY_INFO)) { - handleBatteryInfo((BatteryInfo) intent.getParcelableExtra(BatteryInfoProfile.EXTRA_BATTERY_INFO)); - } + private final IntentListener mListener = intent -> { + String s = intent.getAction(); + if (Objects.equals(s, DeviceInfoProfile.ACTION_DEVICE_INFO)) { + handleDeviceInfo(intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO)); + } + if (Objects.equals(s, BatteryInfoProfile.ACTION_BATTERY_INFO)) { + handleBatteryInfo(intent.getParcelableExtra(BatteryInfoProfile.EXTRA_BATTERY_INFO)); } }; - private Handler idleUpdateHandler = new Handler(); + private final Handler idleUpdateHandler = new Handler(); private int mtu = 20; private MoyoungPacketIn packetIn = new MoyoungPacketIn(); @@ -437,30 +435,6 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { return false; } - private void addGBActivitySample(MoyoungActivitySample sample) { - addGBActivitySamples(new MoyoungActivitySample[] { sample }); - } - - private void addGBActivitySamples(MoyoungActivitySample[] samples) { - try (DBHandler dbHandler = GBApplication.acquireDB()) { - User user = DBHelper.getUser(dbHandler.getDaoSession()); - Device device = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()); - - MoyoungActivitySampleProvider provider = new MoyoungActivitySampleProvider(getDevice(), dbHandler.getDaoSession()); - - for (MoyoungActivitySample sample : samples) { - sample.setDevice(device); - sample.setUser(user); - sample.setProvider(provider); - provider.addGBActivitySample(sample); - } - } catch (Exception ex) { - LOG.error("Error saving samples: ", ex); - GB.toast(getContext(), "Error saving samples: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext()); - } - } - private void broadcastSample(MoyoungActivitySample sample) { Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES) .putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample) @@ -659,12 +633,6 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { } } - private static int BytesToInt24(byte[] bArr) { - if (bArr.length != 3) - throw new IllegalArgumentException(); - return ((bArr[2] << 24) >>> 8) | ((bArr[1] << 8) & 0xFF00) | (bArr[0] & 0xFF); - } - private Runnable updateIdleStepsRunnable = new Runnable() { @Override public void run() { @@ -777,13 +745,13 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { byte[] bArr2 = new byte[3]; System.arraycopy(data, 0, bArr2, 0, 3); - int steps = BytesToInt24(bArr2); + int steps = BLETypeConversions.toUint24(bArr2); System.arraycopy(data, 3, bArr2, 0, 3); - int distance = BytesToInt24(bArr2); + int distance = BLETypeConversions.toUint24(bArr2); System.arraycopy(data, 6, bArr2, 0, 3); - int calories = BytesToInt24(bArr2); + int calories = BLETypeConversions.toUint24(bArr2); - LOG.info("steps[" + daysAgo + "] steps=" + steps + ", distance=" + distance + ", calories=" + calories); + LOG.info("steps[{}] steps={}, distance={}, calories={}", daysAgo, steps, distance, calories); try (DBHandler dbHandler = GBApplication.acquireDB()) { User user = DBHelper.getUser(dbHandler.getDaoSession()); @@ -833,7 +801,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { if (newSteps < 0 || newDistance < 0 || newCalories < 0) { - LOG.warn("Ignoring a sample that would generate negative values: steps += " + newSteps + ", distance +=" + newDistance + ", calories += " + newCalories); + LOG.warn("Ignoring a sample that would generate negative values: steps += {}, distance +={}, calories += {}", newSteps, newDistance, newCalories); } else if (newSteps != 0 || newDistance != 0 || newCalories != 0 || daysAgo == 0) { @@ -857,7 +825,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { broadcastSample(sample); } - LOG.info("Adding a sample: " + sample.toString()); + LOG.info("Adding a sample: {}", sample); } } catch (Exception ex) { LOG.error("Error saving samples: ", ex); @@ -1084,22 +1052,6 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { } } - private void addGBActivitySampleIfNotExists(MoyoungActivitySampleProvider provider, MoyoungActivitySample sample) - { - boolean alreadyHaveThisSample = false; - for (MoyoungActivitySample sample2 : provider.getAllActivitySamples(sample.getTimestamp() - 1, sample.getTimestamp() + 1)) - { - if (sample2.getTimestamp() == sample2.getTimestamp() && sample2.getRawKind() == sample.getRawKind()) - alreadyHaveThisSample = true; - } - - if (!alreadyHaveThisSample) - { - provider.addGBActivitySample(sample); - LOG.info("Adding a sample: " + sample.toString()); - } - } - @Override public void onReset(int flags) { // TODO: this shuts down the watch, rather than rebooting it - perhaps add a new operation type? @@ -1231,7 +1183,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { public void onSendConfiguration(String config) { LOG.info("Send configuration: " + config); - Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())); + Prefs prefs = getDevicePrefs(); switch (config) { case ActivityUser.PREF_USER_HEIGHT_CM: case ActivityUser.PREF_USER_WEIGHT_KG: @@ -1433,7 +1385,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { public void onReadConfigurationDone(MoyoungSetting setting, Object value, byte[] data) { LOG.info("CONFIG " + setting.name + " = " + value); - Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())); + Prefs prefs = getDevicePrefs(); Map changedProperties = new ArrayMap<>(); SharedPreferences.Editor prefsEditor = prefs.getPreferences().edit(); switch (setting.name) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/QuerySettingsOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/QuerySettingsOperation.java index ea670d448..bd99d2a30 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/QuerySettingsOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/QuerySettingsOperation.java @@ -111,8 +111,12 @@ public class QuerySettingsOperation extends AbstractBTLEOperation