From 01e7f3152213b504fac764d344b05a684f0ff79e Mon Sep 17 00:00:00 2001 From: Me7c7 Date: Fri, 2 May 2025 15:00:55 +0300 Subject: [PATCH] Huawei: Configuration of goal reminders --- .../devices/huawei/HuaweiConstants.java | 13 +- .../devices/huawei/HuaweiCoordinator.java | 5 +- .../huawei/HuaweiSettingsCustomizer.java | 7 + .../devices/huawei/HuaweiSupportProvider.java | 64 +++++++-- .../huawei/datasync/HuaweiDataSyncGoals.java | 121 +++++++++++++----- app/src/main/res/values/strings.xml | 7 + ...vicesettings_huawei_activity_reminders.xml | 28 ++++ 7 files changed, 194 insertions(+), 51 deletions(-) create mode 100644 app/src/main/res/xml/devicesettings_huawei_activity_reminders.xml diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java index d2c637407d..73d106c696 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiConstants.java @@ -100,11 +100,14 @@ public final class HuaweiConstants { public static final String PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT = "continuous_skin_temperature_measurement"; public static final String PREF_HUAWEI_HEART_RATE_REALTIME_MODE = "pref_huawei_heart_rate_realtime_mode"; public static final String PREF_HUAWEI_HEART_RATE_LOW_ALERT = "pref_huawei_heart_rate_low_alert"; - public static final String PREF_HUAWEI_HEART_RATE_HIGH_ALERT= "pref_huawei_heart_rate_high_alert"; - public static final String PREF_HUAWEI_SPO_LOW_ALERT= "pref_huawei_spo_low_alert"; - public static final String PREF_HUAWEI_STRESS_SWITCH= "pref_huawei_stress_switch"; - public static final String PREF_HUAWEI_STRESS_CALIBRATE= "pref_huawei_stress_calibrate"; - public static final String PREF_HUAWEI_STRESS_LAST_DATA= "huawei_stress_last_data"; + public static final String PREF_HUAWEI_HEART_RATE_HIGH_ALERT = "pref_huawei_heart_rate_high_alert"; + public static final String PREF_HUAWEI_SPO_LOW_ALERT = "pref_huawei_spo_low_alert"; + public static final String PREF_HUAWEI_STRESS_SWITCH = "pref_huawei_stress_switch"; + public static final String PREF_HUAWEI_STRESS_CALIBRATE = "pref_huawei_stress_calibrate"; + public static final String PREF_HUAWEI_STRESS_LAST_DATA = "huawei_stress_last_data"; + public static final String PREF_HUAWEI_ACTIVITY_REMINDER_STAND = "pref_huawei_activity_reminder_stand"; + public static final String PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS = "pref_huawei_activity_reminder_progress"; + public static final String PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED = "pref_huawei_activity_reminder_goal_reached"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index 67eadb4134..ee0f9f77dc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -305,10 +305,12 @@ public class HuaweiCoordinator { if(supportsTemperature()) { deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_temperature_automatic_enable); } - if(supportsAutoStress()) { deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_stress); } + if(supportsThreeCircle() || supportsThreeCircleLite()) { + deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_activity_reminders); + } // Notifications final List notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS); @@ -327,7 +329,6 @@ public class HuaweiCoordinator { notifications.add(R.xml.devicesettings_upload_notifications_app_icon); } - // Workout if (supportsSendingGps()) deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT, R.xml.devicesettings_workout_send_gps_to_band); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java index a8b1faf435..746dab16f9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSettingsCustomizer.java @@ -39,6 +39,9 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.XTimePreference; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_STAND; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_DEBUG_REQUEST; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT; import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_HEART_RATE_HIGH_ALERT; @@ -121,6 +124,10 @@ public class HuaweiSettingsCustomizer implements DeviceSpecificSettingsCustomize handler.addPreferenceHandlerFor(PREF_HUAWEI_STRESS_SWITCH); handler.addPreferenceHandlerFor(PREF_HUAWEI_STRESS_CALIBRATE); + handler.addPreferenceHandlerFor(PREF_HUAWEI_ACTIVITY_REMINDER_STAND); + handler.addPreferenceHandlerFor(PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS); + handler.addPreferenceHandlerFor(PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED); + final Preference forceOptions = handler.findPreference(PREF_FORCE_OPTIONS); if (forceOptions != null) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index 5577510422..88927f99d3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -16,6 +16,9 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS; +import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_STAND; import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS; import android.bluetooth.BluetoothGattCharacteristic; @@ -1185,6 +1188,15 @@ public class HuaweiSupportProvider { case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS: setStandingTime(); break; + case PREF_HUAWEI_ACTIVITY_REMINDER_STAND: + setActivityReminderStand(); + break; + case PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS: + setActivityReminderProgress(); + break; + case PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED: + setActivityReminderGoalReached(); + break; case DeviceSettingsPreferenceConst.PREF_CAMERA_REMOTE: if (GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_CAMERA_REMOTE, false)) { SendCameraRemoteSetupEvent sendCameraRemoteSetupEvent = new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA); @@ -1229,7 +1241,9 @@ public class HuaweiSupportProvider { public void setStepsGoal() { if(huaweiDataSyncTreeCircleGoals != null) { int stepGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal); - huaweiDataSyncTreeCircleGoals.sendStepsGoal(stepGoal); + if(! huaweiDataSyncTreeCircleGoals.sendStepsGoal(stepGoal)) { + LOG.error("Error to set stand goal"); + } } else { try { new SendFitnessGoalRequest(this).doPerform(); @@ -1242,7 +1256,9 @@ public class HuaweiSupportProvider { public void setCaloriesBurntGoal() { if(huaweiDataSyncTreeCircleGoals != null) { int caloriesBurntGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_CALORIES_BURNT, ActivityUser.defaultUserCaloriesBurntGoal); - huaweiDataSyncTreeCircleGoals.sendCaloriesBurntGoal(caloriesBurntGoal); + if(!huaweiDataSyncTreeCircleGoals.sendCaloriesBurntGoal(caloriesBurntGoal)) { + LOG.error("Error to set calories burnt goal"); + } } else { try { new SendFitnessGoalRequest(this).doPerform(); @@ -1255,7 +1271,9 @@ public class HuaweiSupportProvider { public void setFatBurnTime() { if(huaweiDataSyncTreeCircleGoals != null) { int fatBurnTimeGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, ActivityUser.defaultUserFatBurnTimeMinutes); - huaweiDataSyncTreeCircleGoals.sendExerciseGoal(fatBurnTimeGoal); + if(!huaweiDataSyncTreeCircleGoals.sendExerciseGoal(fatBurnTimeGoal)) { + LOG.error("Error to set exercise goal"); + } } else { try { new SendFitnessGoalRequest(this).doPerform(); @@ -1268,7 +1286,9 @@ public class HuaweiSupportProvider { public void setStandingTime() { if(huaweiDataSyncTreeCircleGoals != null) { int standingTimeGoal = GBApplication.getPrefs().getInt(PREF_USER_GOAL_STANDING_TIME_HOURS, ActivityUser.defaultUserGoalStandingTimeHours); - huaweiDataSyncTreeCircleGoals.sendStandGoal(standingTimeGoal); + if(!huaweiDataSyncTreeCircleGoals.sendStandGoal(standingTimeGoal)) { + LOG.error("Error to set stand goal"); + } } else { try { new SendFitnessGoalRequest(this).doPerform(); @@ -1278,6 +1298,33 @@ public class HuaweiSupportProvider { } } + public void setActivityReminderStand() { + if(huaweiDataSyncTreeCircleGoals != null) { + boolean state = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(PREF_HUAWEI_ACTIVITY_REMINDER_STAND, true); + if(!huaweiDataSyncTreeCircleGoals.sendRemindersStand(state)) { + LOG.error("Error to set stand reminder"); + } + } + } + + public void setActivityReminderProgress() { + if(huaweiDataSyncTreeCircleGoals != null) { + boolean state = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS, true); + if(!huaweiDataSyncTreeCircleGoals.sendRemindersProgress(state)) { + LOG.error("Error to set progress reminder"); + } + } + } + + public void setActivityReminderGoalReached() { + if(huaweiDataSyncTreeCircleGoals != null) { + boolean state = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED, true); + if(!huaweiDataSyncTreeCircleGoals.sendRemindersGoalReached(state)) { + LOG.error("Error to set goal reached reminder"); + } + } + } + public void startUploadNotificationsAppIcons() { SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()); HashSet iconsToUpload = (HashSet) prefs.getStringSet(DeviceSettingsPreferenceConst.PREF_UPLOAD_NOTIFICATIONS_APP_ICON, null); @@ -1451,12 +1498,9 @@ public class HuaweiSupportProvider { List list = P2PSyncService.checkSupported(this.getHuaweiCoordinator(), Arrays.asList(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS, HuaweiDictTypes.BLOOD_PRESSURE_CLASS)); if(!list.isEmpty()) { syncState.setP2pSync(true); - P2PSyncService.startSync(list, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() { - @Override - public void onComplete(boolean complete) { - LOG.info("Sync P2P Data complete"); - syncState.setP2pSync(false); - } + P2PSyncService.startSync(list, complete -> { + LOG.info("Sync P2P Data complete"); + syncState.setP2pSync(false); }); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/datasync/HuaweiDataSyncGoals.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/datasync/HuaweiDataSyncGoals.java index 8bd295480e..12a798979d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/datasync/HuaweiDataSyncGoals.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/datasync/HuaweiDataSyncGoals.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; @@ -40,6 +41,10 @@ public class HuaweiDataSyncGoals implements HuaweiDataSyncCommon.DataCallback { public static final int EXERCISES_GOAL = 900200008; public static final int STAND_GOAL = 900200009; + public static final int REMINDER_STAND = 900200004; + public static final int REMINDER_PROGRESS = 900200010; + public static final int REMINDER_GOAL_REACHED = 900200011; + public static final String SRC_PKG_NAME = "hw.sport.config"; public static final String PKG_NAME = "in.huawei.motion"; @@ -48,7 +53,7 @@ public class HuaweiDataSyncGoals implements HuaweiDataSyncCommon.DataCallback { this.support.getHuaweiDataSyncManager().registerCallback(PKG_NAME, this); } - private boolean sendCommonGoal(int configId, int goal) { + private boolean sendCommonData(int configId, int goal) { int time = (int) (System.currentTimeMillis() / 1000); HuaweiTLV tlv = new HuaweiTLV().put(0x01, time).put(0x02, goal); HuaweiDataSyncCommon.ConfigCommandData data = new HuaweiDataSyncCommon.ConfigCommandData(); @@ -62,6 +67,14 @@ public class HuaweiDataSyncGoals implements HuaweiDataSyncCommon.DataCallback { return this.support.getHuaweiDataSyncManager().sendConfigCommand(SRC_PKG_NAME, PKG_NAME, data); } + private boolean sendCommonGoal(int configId, int goal) { + return sendCommonData(configId, goal); + } + + private boolean sendCommonReminder(int configId, boolean state) { + return sendCommonData(configId, state ? 1 : 0); + } + public boolean sendStepsGoal(int stepsGoal) { return sendCommonGoal(STEPS_GOAL, stepsGoal); } @@ -78,52 +91,92 @@ public class HuaweiDataSyncGoals implements HuaweiDataSyncCommon.DataCallback { return sendCommonGoal(STAND_GOAL, standGoal); } + public boolean sendRemindersStand(boolean state) { + return sendCommonReminder(REMINDER_STAND, state); + } + + public boolean sendRemindersProgress(boolean state) { + return sendCommonReminder(REMINDER_PROGRESS, state); + } + + public boolean sendRemindersGoalReached(boolean state) { + return sendCommonReminder(REMINDER_GOAL_REACHED, state); + } + @Override public void onConfigCommand(HuaweiDataSyncCommon.ConfigCommandData data) { - if(data.getCode() != HuaweiDataSyncCommon.REPLY_OK) { + if (data.getCode() != HuaweiDataSyncCommon.REPLY_OK) { return; } List list = data.getConfigDataList(); - if(list.isEmpty()) { + if (list.isEmpty()) { return; } HuaweiDataSyncCommon.ConfigData config = list.get(0); HuaweiTLV tlv = new HuaweiTLV(); tlv.parse(config.configData); - if(!tlv.contains(0x02)) { + if (!tlv.contains(0x02)) { return; } try { - switch(config.configId) { - case STEPS_GOAL: { - int goal = tlv.getInteger(0x02); - SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(ActivityUser.PREF_USER_STEPS_GOAL, String.valueOf(goal)); - editor.apply(); - } break; - case CALORIES_GOAL: { - int goal = tlv.getInteger(0x02); - SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(ActivityUser.PREF_USER_CALORIES_BURNT, String.valueOf(goal / 1000)); - editor.apply(); - } break; - case EXERCISES_GOAL: { - int goal = tlv.getInteger(0x02); - SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, String.valueOf(goal)); - editor.apply(); - } break; - case STAND_GOAL: { - int goal = tlv.getInteger(0x02); - SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS, String.valueOf(goal)); - editor.apply(); - } break; - } + switch (config.configId) { + case STEPS_GOAL: { + int goal = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(ActivityUser.PREF_USER_STEPS_GOAL, String.valueOf(goal)); + editor.apply(); + } + break; + case CALORIES_GOAL: { + int goal = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(ActivityUser.PREF_USER_CALORIES_BURNT, String.valueOf(goal / 1000)); + editor.apply(); + } + break; + case EXERCISES_GOAL: { + int goal = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, String.valueOf(goal)); + editor.apply(); + } + break; + case STAND_GOAL: { + int goal = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getPrefs().getPreferences(); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS, String.valueOf(goal)); + editor.apply(); + } + break; + case REMINDER_STAND: { + int state = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(support.getDevice().getAddress()); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_STAND, state != 0); + editor.apply(); + } + break; + case REMINDER_PROGRESS: { + int state = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(support.getDevice().getAddress()); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS, state != 0); + editor.apply(); + } + break; + case REMINDER_GOAL_REACHED: { + int state = tlv.getInteger(0x02); + SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(support.getDevice().getAddress()); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(HuaweiConstants.PREF_HUAWEI_ACTIVITY_REMINDER_GOAL_REACHED, state != 0); + editor.apply(); + } + break; + } } catch (HuaweiPacket.MissingTagException e) { LOG.error("Failed to handle data sync goals config command", e); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 32d9a51b76..b0bdf697dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3930,4 +3930,11 @@ Are you sure you want to upload %1$d app icons? Upload notification app icons Upload notification app icons to device + Activity reminders + Stand + Get a reminder to get up if you haven\'t gotten up in 1 hour + Progress + Get reminders about Activity Ring progress + Goal Reached + Get a reminder when you complete rings diff --git a/app/src/main/res/xml/devicesettings_huawei_activity_reminders.xml b/app/src/main/res/xml/devicesettings_huawei_activity_reminders.xml new file mode 100644 index 0000000000..22864b0615 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_huawei_activity_reminders.xml @@ -0,0 +1,28 @@ + + + + + + + + + \ No newline at end of file