From 6974a86b8773750e4f0b82c669a84130656f4847 Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Mon, 5 Oct 2020 14:20:20 -0600 Subject: [PATCH] Lefun: Implement settings --- .../DeviceSettingsPreferenceConst.java | 7 + .../DeviceSpecificSettingsFragment.java | 12 + .../devices/lefun/LefunDeviceCoordinator.java | 13 + .../lefun/commands/SettingsCommand.java | 6 +- .../devices/lefun/LefunDeviceSupport.java | 276 ++++++++++++++++++ .../requests/GetEnabledFeaturesRequest.java | 57 ++++ .../requests/GetGeneralSettingsRequest.java | 60 ++++ .../GetHydrationReminderIntervalRequest.java | 57 ++++ .../GetSedentaryReminderIntervalRequest.java | 57 ++++ .../requests/SetEnabledFeaturesRequest.java | 63 ++++ .../requests/SetGeneralSettingsRequest.java | 78 +++++ .../SetHydrationReminderIntervalRequest.java | 67 +++++ .../lefun/requests/SetLanguageRequest.java | 65 +++++ .../lefun/requests/SetProfileRequest.java | 74 +++++ .../SetSedentaryReminderIntervalRequest.java | 67 +++++ app/src/main/res/values/arrays.xml | 10 + app/src/main/res/values/strings.xml | 8 + app/src/main/res/xml/devicesettings_ampm.xml | 9 + .../main/res/xml/devicesettings_antilost.xml | 9 + .../xml/devicesettings_hydration_reminder.xml | 20 ++ ...evicesettings_lefun_interface_language.xml | 11 + 21 files changed, 1023 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetEnabledFeaturesRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetGeneralSettingsRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetHydrationReminderIntervalRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetSedentaryReminderIntervalRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetEnabledFeaturesRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetGeneralSettingsRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetHydrationReminderIntervalRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetLanguageRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetProfileRequest.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetSedentaryReminderIntervalRequest.java create mode 100644 app/src/main/res/xml/devicesettings_ampm.xml create mode 100644 app/src/main/res/xml/devicesettings_antilost.xml create mode 100644 app/src/main/res/xml/devicesettings_hydration_reminder.xml create mode 100644 app/src/main/res/xml/devicesettings_lefun_interface_language.xml diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java index a81ab8f1f..2e574f94b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java @@ -45,4 +45,11 @@ public class DeviceSettingsPreferenceConst { public static final String PREF_LONGSIT_SWITCH = "pref_longsit_switch"; public static final String PREF_LONGSIT_SWITCH_NOSHED = "screen_longsit_noshed"; public static final String PREF_DO_NOT_DISTURB_NOAUTO = "do_not_disturb_no_auto"; + public static final String PREF_FIND_PHONE_ENABLED = "prefs_find_phone"; + + public static final String PREF_ANTILOST_ENABLED = "pref_antilost_enabled"; + public static final String PREF_HYDRATION_SWITCH = "pref_hydration_switch"; + public static final String PREF_HYDRATION_PERIOD = "pref_hydration_period"; + public static final String PREF_AMPM_ENABLED = "pref_ampm_enabled"; + public static final String PREF_LEFUN_INTERFACE_LANGUAGE = "pref_lefun_interface_language"; } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java index bf753a4e6..0dd9bf6ce 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java @@ -41,6 +41,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.XTimePreference; import nodomain.freeyourgadget.gadgetbridge.util.XTimePreferenceFragment; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALTITUDE_CALIBRATE; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AMPM_ENABLED; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_1_FUNCTION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_2_FUNCTION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_3_FUNCTION; @@ -48,10 +50,14 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DISCONNECTNOTIF_NOSHED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FIND_PHONE_ENABLED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_FORCE_WHITE_COLOR; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYDRATION_PERIOD; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LANGUAGE; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LEFUN_INTERFACE_LANGUAGE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH; @@ -351,6 +357,12 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat { addPreferenceHandlerFor(PREF_LONGSIT_PERIOD); addPreferenceHandlerFor(PREF_LONGSIT_SWITCH); addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO); + addPreferenceHandlerFor(PREF_FIND_PHONE_ENABLED); + addPreferenceHandlerFor(PREF_ANTILOST_ENABLED); + addPreferenceHandlerFor(PREF_HYDRATION_SWITCH); + addPreferenceHandlerFor(PREF_HYDRATION_PERIOD); + addPreferenceHandlerFor(PREF_AMPM_ENABLED); + addPreferenceHandlerFor(PREF_LEFUN_INTERFACE_LANGUAGE); addPreferenceHandlerFor(PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES); addPreferenceHandlerFor(PREF_HYBRID_HR_FORCE_WHITE_COLOR); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/LefunDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/LefunDeviceCoordinator.java index 9e501b765..c8e59bfde 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/LefunDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/LefunDeviceCoordinator.java @@ -26,6 +26,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import nodomain.freeyourgadget.gadgetbridge.GBException; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; @@ -154,4 +155,16 @@ public class LefunDeviceCoordinator extends AbstractDeviceCoordinator { public boolean supportsFindDevice() { return true; } + + @Override + public int[] getSupportedDeviceSpecificSettings(GBDevice device) { + return new int[]{ + R.xml.devicesettings_liftwrist_display_noshed, + R.xml.devicesettings_ampm, + R.xml.devicesettings_antilost, + R.xml.devicesettings_longsit, + R.xml.devicesettings_hydration_reminder, + R.xml.devicesettings_lefun_interface_language, + }; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/SettingsCommand.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/SettingsCommand.java index 0fb40964c..10322ecbc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/SettingsCommand.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/lefun/commands/SettingsCommand.java @@ -50,7 +50,7 @@ public class SettingsCommand extends BaseCommand { } public void setOption1(byte option1) { - if (option1 < 0 || option1 > 24) + if (option1 != (byte)0xff && (option1 < 0 || option1 > 24)) throw new IllegalArgumentException("option1 must be between 0 and 24 inclusive"); this.option1 = option1; } @@ -60,7 +60,7 @@ public class SettingsCommand extends BaseCommand { } public void setAmPmIndicator(byte amPmIndicator) { - if (amPmIndicator != AM_PM_12_HOUR && amPmIndicator != AM_PM_24_HOUR) + if (amPmIndicator != (byte)0xff && (amPmIndicator != AM_PM_12_HOUR && amPmIndicator != AM_PM_24_HOUR)) throw new IllegalArgumentException("Indicator must be 12 or 24 hours"); this.amPmIndicator = amPmIndicator; } @@ -70,7 +70,7 @@ public class SettingsCommand extends BaseCommand { } public void setMeasurementUnit(byte measurementUnit) { - if (measurementUnit != MEASUREMENT_UNIT_METRIC && measurementUnit != MEASUREMENT_UNIT_IMPERIAL) + if (measurementUnit != (byte)0xff && (measurementUnit != MEASUREMENT_UNIT_METRIC && measurementUnit != MEASUREMENT_UNIT_IMPERIAL)) throw new IllegalArgumentException(("Unit must be metric or imperial")); this.measurementUnit = measurementUnit; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java index 960803b9b..9ae87a092 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/LefunDeviceSupport.java @@ -21,6 +21,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.widget.Toast; @@ -40,22 +41,28 @@ import java.util.concurrent.ConcurrentLinkedQueue; import de.greenrobot.dao.query.Query; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity; +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.FeaturesCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.FindPhoneCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.GetActivityDataCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.GetPpgDataCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.GetSleepDataCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.GetStepsDataCommand; import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.PpgResultCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SettingsCommand; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.LefunActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.LefunActivitySampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.LefunBiometricSample; import nodomain.freeyourgadget.gadgetbridge.entities.LefunSleepSample; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; @@ -73,16 +80,27 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateA import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.FindDeviceRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetActivityDataRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetBatteryLevelRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetEnabledFeaturesRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetFirmwareInfoRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetGeneralSettingsRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetHydrationReminderIntervalRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetPpgDataRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetSedentaryReminderIntervalRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.GetSleepDataRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.Request; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SendCallNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SendNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetAlarmRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetEnabledFeaturesRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetGeneralSettingsRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetHydrationReminderIntervalRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetLanguageRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetProfileRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetSedentaryReminderIntervalRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.SetTimeRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.StartPpgRequest; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class LefunDeviceSupport extends AbstractBTLEDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(LefunDeviceSupport.class); @@ -122,6 +140,9 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport { GetBatteryLevelRequest batReq = new GetBatteryLevelRequest(this, builder); batReq.perform(); inProgressRequests.add(batReq); + + sendUnitsSetting(builder); + sendUserProfile(builder); } catch (IOException e) { GB.toast(getContext(), "Failed to initialize Lefun device", Toast.LENGTH_SHORT, GB.ERROR, e); @@ -357,12 +378,266 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onSendConfiguration(String config) { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + switch (config) { + case DeviceSettingsPreferenceConst.PREF_AMPM_ENABLED: { + boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_AMPM_ENABLED, false); + byte ampmValue = enabled ? SettingsCommand.AM_PM_12_HOUR : SettingsCommand.AM_PM_24_HOUR; + sendGeneralSettings(null, ampmValue, (byte) 0xff); + break; + } + case DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED: { + boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED, true); + FeaturesCommand features = getCurrentEnabledFeatures(); + features.setFeature(FeaturesCommand.FEATURE_RAISE_TO_WAKE, enabled); + sendEnabledFeaturesSetting(features); + break; + } + case DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED: { + boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED, true); + FeaturesCommand features = getCurrentEnabledFeatures(); + features.setFeature(FeaturesCommand.FEATURE_ANTI_LOST, enabled); + sendEnabledFeaturesSetting(features); + break; + } + case DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH: { + boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH, false); + FeaturesCommand features = getCurrentEnabledFeatures(); + features.setFeature(FeaturesCommand.FEATURE_SEDENTARY_REMINDER, enabled); + sendEnabledFeaturesSetting(features); + break; + } + case DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD: { + String periodStr = prefs.getString(DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD, "60"); + try { + int period = Integer.parseInt(periodStr); + sendSedentaryReminderIntervalSetting(period); + } catch (NumberFormatException e) { + GB.toast(getContext(), "Invalid sedentary reminder interval value", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + break; + } + case DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH: { + boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH, false); + FeaturesCommand features = getCurrentEnabledFeatures(); + features.setFeature(FeaturesCommand.FEATURE_HYDRATION_REMINDER, enabled); + sendEnabledFeaturesSetting(features); + break; + } + case DeviceSettingsPreferenceConst.PREF_HYDRATION_PERIOD: { + String periodStr = prefs.getString(DeviceSettingsPreferenceConst.PREF_HYDRATION_PERIOD, "60"); + try { + int period = Integer.parseInt(periodStr); + sendHydrationReminderIntervalSetting(period); + } catch (NumberFormatException e) { + GB.toast(getContext(), "Invalid sedentary reminder interval value", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + break; + } + case SettingsActivity.PREF_MEASUREMENT_SYSTEM: { + sendUnitsSetting(null); + break; + } + case DeviceSettingsPreferenceConst.PREF_LEFUN_INTERFACE_LANGUAGE: { + String value = prefs.getString(DeviceSettingsPreferenceConst.PREF_LEFUN_INTERFACE_LANGUAGE, "0"); + int intValue = Integer.parseInt(value); + sendLanguageSetting((byte) intValue); + break; + } + } + } + private void sendUnitsSetting(TransactionBuilder builder) { + Prefs prefs = GBApplication.getPrefs(); + String units = prefs.getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, + getContext().getString(R.string.p_unit_metric)); + + byte lefunUnits; + if (getContext().getString(R.string.p_unit_metric).equals(units)) { + lefunUnits = SettingsCommand.MEASUREMENT_UNIT_METRIC; + } else { + lefunUnits = SettingsCommand.MEASUREMENT_UNIT_IMPERIAL; + } + sendGeneralSettings(builder, (byte) 0xff, lefunUnits); + } + + private FeaturesCommand getCurrentEnabledFeatures() { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + boolean raiseToWakeEnabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED, true); + boolean antilostEnabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED, true); + boolean sedentaryEnabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH, false); + boolean hydrationEnabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH, false); + + FeaturesCommand cmd = new FeaturesCommand(); + cmd.setFeature(FeaturesCommand.FEATURE_RAISE_TO_WAKE, raiseToWakeEnabled); + cmd.setFeature(FeaturesCommand.FEATURE_ANTI_LOST, antilostEnabled); + cmd.setFeature(FeaturesCommand.FEATURE_SEDENTARY_REMINDER, sedentaryEnabled); + cmd.setFeature(FeaturesCommand.FEATURE_HYDRATION_REMINDER, hydrationEnabled); + + return cmd; + } + + private void sendGeneralSettings(TransactionBuilder builder, byte amPm, byte units) { + boolean givenBuilder = builder != null; + try { + if (!givenBuilder) + builder = performInitialized(SetGeneralSettingsRequest.class.getSimpleName()); + SetGeneralSettingsRequest request = new SetGeneralSettingsRequest(this, builder); + request.setAmPm(amPm); + request.setUnits(units); + request.perform(); + inProgressRequests.add(request); + if (!givenBuilder) + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to set settings", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + private void sendUserProfile(TransactionBuilder builder) { + boolean givenBuilder = builder != null; + try { + if (!givenBuilder) + builder = performInitialized(SetProfileRequest.class.getSimpleName()); + SetProfileRequest request = new SetProfileRequest(this, builder); + ActivityUser user = new ActivityUser(); + request.setUser(user); + request.perform(); + inProgressRequests.add(request); + if (!givenBuilder) + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to send profile", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + private void sendEnabledFeaturesSetting(FeaturesCommand cmd) { + try { + TransactionBuilder builder = performInitialized(SetEnabledFeaturesRequest.class.getSimpleName()); + SetEnabledFeaturesRequest request = new SetEnabledFeaturesRequest(this, builder); + request.setCmd(cmd); + request.perform(); + inProgressRequests.add(request); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to set enabled features", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + private void sendSedentaryReminderIntervalSetting(int period) { + try { + TransactionBuilder builder = performInitialized(SetSedentaryReminderIntervalRequest.class.getSimpleName()); + SetSedentaryReminderIntervalRequest request = new SetSedentaryReminderIntervalRequest(this, builder); + request.setInterval(period); + request.perform(); + inProgressRequests.add(request); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to set sedentary reminder interval", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + private void sendHydrationReminderIntervalSetting(int period) { + try { + TransactionBuilder builder = performInitialized(SetHydrationReminderIntervalRequest.class.getSimpleName()); + SetHydrationReminderIntervalRequest request = new SetHydrationReminderIntervalRequest(this, builder); + request.setInterval(period); + request.perform(); + inProgressRequests.add(request); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to set hydration reminder interval", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + private void sendLanguageSetting(byte language) { + try { + TransactionBuilder builder = performInitialized(SetLanguageRequest.class.getSimpleName()); + SetLanguageRequest request = new SetLanguageRequest(this, builder); + request.setLanguage(language); + request.perform(); + inProgressRequests.add(request); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to set language", Toast.LENGTH_SHORT, + GB.ERROR, e); + } + } + + public void receiveGeneralSettings(int amPm, int units) { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + boolean ampmEnabled = amPm == SettingsCommand.AM_PM_12_HOUR; + prefs.edit() + .putBoolean(DeviceSettingsPreferenceConst.PREF_AMPM_ENABLED, ampmEnabled) + .apply(); + } + + public void receiveEnabledFeaturesSetting(FeaturesCommand cmd) { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + prefs.edit() + .putBoolean(DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED, + cmd.getFeature(FeaturesCommand.FEATURE_RAISE_TO_WAKE)) + .putBoolean(DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH, + cmd.getFeature(FeaturesCommand.FEATURE_SEDENTARY_REMINDER)) + .putBoolean(DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH, + cmd.getFeature(FeaturesCommand.FEATURE_HYDRATION_REMINDER)) + .putBoolean(DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED, + cmd.getFeature(FeaturesCommand.FEATURE_ANTI_LOST)) + .apply(); + } + + public void receiveSedentaryReminderIntervalSetting(int period) { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + prefs.edit() + .putString(DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD, String.valueOf(period)) + .apply(); + } + + public void receiveHydrationReminderIntervalSetting(int period) { + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()); + prefs.edit() + .putString(DeviceSettingsPreferenceConst.PREF_HYDRATION_PERIOD, String.valueOf(period)) + .apply(); } @Override public void onReadConfiguration(String config) { + // Just going to read all the settings + try { + TransactionBuilder builder = performInitialized("Read settings"); + GetGeneralSettingsRequest getGeneralSettingsRequest + = new GetGeneralSettingsRequest(this, builder); + getGeneralSettingsRequest.perform(); + inProgressRequests.add(getGeneralSettingsRequest); + + GetEnabledFeaturesRequest getEnabledFeaturesRequest + = new GetEnabledFeaturesRequest(this, builder); + getEnabledFeaturesRequest.perform(); + inProgressRequests.add(getEnabledFeaturesRequest); + + GetSedentaryReminderIntervalRequest getSedentaryReminderIntervalRequest + = new GetSedentaryReminderIntervalRequest(this, builder); + getSedentaryReminderIntervalRequest.perform(); + inProgressRequests.add(getSedentaryReminderIntervalRequest); + + GetHydrationReminderIntervalRequest getHydrationReminderIntervalRequest + = new GetHydrationReminderIntervalRequest(this, builder); + getHydrationReminderIntervalRequest.perform(); + inProgressRequests.add(getHydrationReminderIntervalRequest); + + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Failed to retrieve settings", Toast.LENGTH_SHORT, + GB.ERROR, e); + } } @Override @@ -489,6 +764,7 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport { public void completeInitialization() { gbDevice.setState(GBDevice.State.INITIALIZED); gbDevice.sendDeviceUpdateIntent(getContext()); + onReadConfiguration(""); } private int dateToTimestamp(byte year, byte month, byte day, byte hour, byte minute, byte second) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetEnabledFeaturesRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetEnabledFeaturesRequest.java new file mode 100644 index 000000000..3f7759b02 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetEnabledFeaturesRequest.java @@ -0,0 +1,57 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.FeaturesCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class GetEnabledFeaturesRequest extends Request { + public GetEnabledFeaturesRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + @Override + public byte[] createRequest() { + FeaturesCommand cmd = new FeaturesCommand(); + + cmd.setOp(BaseCommand.OP_GET); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + FeaturesCommand cmd = new FeaturesCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_GET) { + getSupport().receiveEnabledFeaturesSetting(cmd); + } + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_FEATURES; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetGeneralSettingsRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetGeneralSettingsRequest.java new file mode 100644 index 000000000..9efe28fd7 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetGeneralSettingsRequest.java @@ -0,0 +1,60 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SettingsCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class GetGeneralSettingsRequest extends Request { + public GetGeneralSettingsRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + @Override + public byte[] createRequest() { + SettingsCommand cmd = new SettingsCommand(); + + cmd.setOp(BaseCommand.OP_GET); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + SettingsCommand cmd = new SettingsCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_GET) { + getSupport().receiveGeneralSettings( + (int) cmd.getAmPmIndicator() & 0xff, + (int) cmd.getMeasurementUnit() & 0xff + ); + } + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_SETTINGS; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetHydrationReminderIntervalRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetHydrationReminderIntervalRequest.java new file mode 100644 index 000000000..275effa88 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetHydrationReminderIntervalRequest.java @@ -0,0 +1,57 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.HydrationReminderIntervalCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class GetHydrationReminderIntervalRequest extends Request { + public GetHydrationReminderIntervalRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + @Override + public byte[] createRequest() { + HydrationReminderIntervalCommand cmd = new HydrationReminderIntervalCommand(); + + cmd.setOp(BaseCommand.OP_GET); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + HydrationReminderIntervalCommand cmd = new HydrationReminderIntervalCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_GET) { + getSupport().receiveHydrationReminderIntervalSetting((int) cmd.getHydrationReminderInterval() & 0xff); + } + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_HYDRATION_REMINDER_INTERVAL; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetSedentaryReminderIntervalRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetSedentaryReminderIntervalRequest.java new file mode 100644 index 000000000..8b17df11f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/GetSedentaryReminderIntervalRequest.java @@ -0,0 +1,57 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SedentaryReminderIntervalCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class GetSedentaryReminderIntervalRequest extends Request { + public GetSedentaryReminderIntervalRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + @Override + public byte[] createRequest() { + SedentaryReminderIntervalCommand cmd = new SedentaryReminderIntervalCommand(); + + cmd.setOp(BaseCommand.OP_GET); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + SedentaryReminderIntervalCommand cmd = new SedentaryReminderIntervalCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_GET) { + getSupport().receiveSedentaryReminderIntervalSetting((int) cmd.getSedentaryReminderInterval() & 0xff); + } + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_SEDENTARY_REMINDER_INTERVAL; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetEnabledFeaturesRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetEnabledFeaturesRequest.java new file mode 100644 index 000000000..fe0cc289a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetEnabledFeaturesRequest.java @@ -0,0 +1,63 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.FeaturesCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetEnabledFeaturesRequest extends Request { + private FeaturesCommand cmd; + + public SetEnabledFeaturesRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public FeaturesCommand getCmd() { + return cmd; + } + + public void setCmd(FeaturesCommand cmd) { + this.cmd = cmd; + } + + @Override + public byte[] createRequest() { + cmd.setOp(BaseCommand.OP_SET); + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + FeaturesCommand cmd = new FeaturesCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_SET && !cmd.isSetSuccess()) + reportFailure("Could not set enabled features"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_FEATURES; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetGeneralSettingsRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetGeneralSettingsRequest.java new file mode 100644 index 000000000..4848daba1 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetGeneralSettingsRequest.java @@ -0,0 +1,78 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SettingsCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetGeneralSettingsRequest extends Request { + private byte amPm; + private byte units; + + public SetGeneralSettingsRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public byte getAmPm() { + return amPm; + } + + public void setAmPm(byte amPm) { + this.amPm = amPm; + } + + public byte getUnits() { + return units; + } + + public void setUnits(byte units) { + this.units = units; + } + + @Override + public byte[] createRequest() { + SettingsCommand cmd = new SettingsCommand(); + + cmd.setOp(BaseCommand.OP_SET); + cmd.setOption1((byte) 0xff); // Don't set + cmd.setAmPmIndicator(amPm); + cmd.setMeasurementUnit(units); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + SettingsCommand cmd = new SettingsCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_SET && !cmd.isSetSuccess()) + reportFailure("Could not set settings"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_SETTINGS; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetHydrationReminderIntervalRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetHydrationReminderIntervalRequest.java new file mode 100644 index 000000000..85339e189 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetHydrationReminderIntervalRequest.java @@ -0,0 +1,67 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.HydrationReminderIntervalCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetHydrationReminderIntervalRequest extends Request { + private int interval; + + public SetHydrationReminderIntervalRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public int getInterval() { + return interval; + } + + public void setInterval(int interval) { + this.interval = interval; + } + + @Override + public byte[] createRequest() { + HydrationReminderIntervalCommand cmd = new HydrationReminderIntervalCommand(); + + cmd.setOp(BaseCommand.OP_SET); + cmd.setHydrationReminderInterval((byte) interval); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + HydrationReminderIntervalCommand cmd = new HydrationReminderIntervalCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_SET && !cmd.isSetSuccess()) + reportFailure("Could not set hydration reminder interval"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_HYDRATION_REMINDER_INTERVAL; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetLanguageRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetLanguageRequest.java new file mode 100644 index 000000000..db168bf8a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetLanguageRequest.java @@ -0,0 +1,65 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SetLanguageCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetLanguageRequest extends Request { + private byte language; + + public SetLanguageRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public byte getLanguage() { + return language; + } + + public void setLanguage(byte language) { + this.language = language; + } + + @Override + public byte[] createRequest() { + SetLanguageCommand cmd = new SetLanguageCommand(); + + cmd.setLanguage(language); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + SetLanguageCommand cmd = new SetLanguageCommand(); + cmd.deserialize(data); + if (!cmd.isSetSuccess()) + reportFailure("Could not set language"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_LANGUAGE; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetProfileRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetProfileRequest.java new file mode 100644 index 000000000..7b1aa29ac --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetProfileRequest.java @@ -0,0 +1,74 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.ProfileCommand; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetProfileRequest extends Request { + private ActivityUser user; + + public SetProfileRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public ActivityUser getUser() { + return user; + } + + public void setUser(ActivityUser user) { + this.user = user; + } + + @Override + public byte[] createRequest() { + ProfileCommand cmd = new ProfileCommand(); + + cmd.setOp(BaseCommand.OP_SET); + // No "other" option available, only male or female + cmd.setGender(user.getGender() == ActivityUser.GENDER_FEMALE + ? ProfileCommand.GENDER_FEMALE + : ProfileCommand.GENDER_MALE); + cmd.setHeight((byte) user.getHeightCm()); + cmd.setWeight((byte) user.getWeightKg()); + cmd.setAge((byte) user.getAge()); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + ProfileCommand cmd = new ProfileCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_SET && !cmd.isSetSuccess()) + reportFailure("Could not set profile"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_PROFILE; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetSedentaryReminderIntervalRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetSedentaryReminderIntervalRequest.java new file mode 100644 index 000000000..c048c6ccb --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/lefun/requests/SetSedentaryReminderIntervalRequest.java @@ -0,0 +1,67 @@ +/* Copyright (C) 2016-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti + Copyright (C) 2020 Yukai Li + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests; + +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.BaseCommand; +import nodomain.freeyourgadget.gadgetbridge.devices.lefun.commands.SedentaryReminderIntervalCommand; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus; + +public class SetSedentaryReminderIntervalRequest extends Request { + private int interval; + + public SetSedentaryReminderIntervalRequest(LefunDeviceSupport support, TransactionBuilder builder) { + super(support, builder); + } + + public int getInterval() { + return interval; + } + + public void setInterval(int interval) { + this.interval = interval; + } + + @Override + public byte[] createRequest() { + SedentaryReminderIntervalCommand cmd = new SedentaryReminderIntervalCommand(); + + cmd.setOp(BaseCommand.OP_SET); + cmd.setSedentaryReminderInterval((byte) interval); + + return cmd.serialize(); + } + + @Override + public void handleResponse(byte[] data) { + SedentaryReminderIntervalCommand cmd = new SedentaryReminderIntervalCommand(); + cmd.deserialize(data); + if (cmd.getOp() == BaseCommand.OP_SET && !cmd.isSetSuccess()) + reportFailure("Could not set sedentary reminder interval"); + + operationStatus = OperationStatus.FINISHED; + } + + @Override + public int getCommandId() { + return LefunConstants.CMD_SEDENTARY_REMINDER_INTERVAL; + } +} diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 346b118c0..fb85f5c2e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -976,4 +976,14 @@ 7days 30days + + + @string/english + @string/simplified_chinese + + + + 0 + 1 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 489860d61..a06de974a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -547,6 +547,14 @@ Choose the shortcuts on the band screen Force black on white color scheme Useful if you your watch has dark hands + Hydration reminder + The band will vibrate to remind you to drink water + Hydration reminder interval (in minutes) + Anti-loss + The band will vibrate if the Bluetooth connection to your phone disconnects + 12-hour display + Display time in 12-hour format with AM/PM indicator + Interface language Automatic Simplified Chinese Traditional Chinese diff --git a/app/src/main/res/xml/devicesettings_ampm.xml b/app/src/main/res/xml/devicesettings_ampm.xml new file mode 100644 index 000000000..a8e96db05 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_ampm.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/xml/devicesettings_antilost.xml b/app/src/main/res/xml/devicesettings_antilost.xml new file mode 100644 index 000000000..a4c9dc705 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_antilost.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/xml/devicesettings_hydration_reminder.xml b/app/src/main/res/xml/devicesettings_hydration_reminder.xml new file mode 100644 index 000000000..95edf232b --- /dev/null +++ b/app/src/main/res/xml/devicesettings_hydration_reminder.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/app/src/main/res/xml/devicesettings_lefun_interface_language.xml b/app/src/main/res/xml/devicesettings_lefun_interface_language.xml new file mode 100644 index 000000000..a1943847c --- /dev/null +++ b/app/src/main/res/xml/devicesettings_lefun_interface_language.xml @@ -0,0 +1,11 @@ + + + +