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 f4ba54ea1..a083c1724 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
@@ -85,6 +85,10 @@ public class DeviceSettingsPreferenceConst {
public static final String PREF_HEARTRATE_USE_FOR_SLEEP_DETECTION = "heartrate_sleep_detection";
public static final String PREF_HEARTRATE_MEASUREMENT_INTERVAL = "heartrate_measurement_interval";
+ public static final String PREF_HEARTRATE_ACTIVITY_MONITORING = "heartrate_activity_monitoring";
+ public static final String PREF_HEARTRATE_ALERT_ENABLED = "heartrate_alert_enabled";
+ public static final String PREF_HEARTRATE_ALERT_THRESHOLD = "heartrate_alert_threshold";
+ public static final String PREF_HEARTRATE_STRESS_MONITORING = "heartrate_stress_monitoring";
public static final String PREF_AUTOHEARTRATE_SWITCH = "pref_autoheartrate_switch";
public static final String PREF_AUTOHEARTRATE_SLEEP = "pref_autoheartrate_sleep";
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 31d6290b6..efe23cbca 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
@@ -355,15 +355,43 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
});
}
- final Preference heartrateMeasurementInterval = findPreference(PREF_HEARTRATE_MEASUREMENT_INTERVAL);
+ final ListPreference heartrateMeasurementInterval = findPreference(PREF_HEARTRATE_MEASUREMENT_INTERVAL);
if (heartrateMeasurementInterval != null) {
+ final SwitchPreference activityMonitoring = findPreference(PREF_HEARTRATE_ACTIVITY_MONITORING);
+ final SwitchPreference heartrateAlertEnabled = findPreference(PREF_HEARTRATE_ALERT_ENABLED);
+ final SwitchPreference stressMonitoring = findPreference(PREF_HEARTRATE_STRESS_MONITORING);
+
heartrateMeasurementInterval.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newVal) {
+ public boolean onPreferenceChange(final Preference preference, final Object newVal) {
GBApplication.deviceService().onSetHeartRateMeasurementInterval(Integer.parseInt((String) newVal));
+
+ final boolean isMeasurementIntervalEnabled = !newVal.equals("0");
+
+ if (activityMonitoring != null) {
+ activityMonitoring.setEnabled(isMeasurementIntervalEnabled);
+ }
+ if (heartrateAlertEnabled != null) {
+ heartrateAlertEnabled.setEnabled(isMeasurementIntervalEnabled);
+ }
+ if (stressMonitoring != null) {
+ stressMonitoring.setEnabled(isMeasurementIntervalEnabled);
+ }
+
return true;
}
});
+
+ final boolean isMeasurementIntervalEnabled = !heartrateMeasurementInterval.getValue().equals("0");
+
+ if (activityMonitoring != null) {
+ activityMonitoring.setEnabled(isMeasurementIntervalEnabled);
+ }
+ if (heartrateAlertEnabled != null) {
+ heartrateAlertEnabled.setEnabled(isMeasurementIntervalEnabled);
+ }
+ if (stressMonitoring != null) {
+ stressMonitoring.setEnabled(isMeasurementIntervalEnabled);
+ }
}
addPreferenceHandlerFor(PREF_SWIPE_UNLOCK);
@@ -416,6 +444,10 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_INTERVAL);
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_START);
addPreferenceHandlerFor(PREF_AUTOHEARTRATE_END);
+ addPreferenceHandlerFor(PREF_HEARTRATE_ACTIVITY_MONITORING);
+ addPreferenceHandlerFor(PREF_HEARTRATE_ALERT_THRESHOLD);
+ addPreferenceHandlerFor(PREF_HEARTRATE_ALERT_ENABLED);
+ addPreferenceHandlerFor(PREF_HEARTRATE_STRESS_MONITORING);
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO);
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO_START);
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO_END);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java
index 11a4a0d39..42575cf63 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java
@@ -273,6 +273,26 @@ public abstract class HuamiCoordinator extends AbstractDeviceCoordinator {
return GBApplication.getPrefs().getInt(DeviceSettingsPreferenceConst.PREF_HEARTRATE_MEASUREMENT_INTERVAL, 0) / 60;
}
+ public static boolean getHeartrateActivityMonitoring(String deviceAddress) throws IllegalArgumentException {
+ Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
+ return prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_HEARTRATE_ACTIVITY_MONITORING, false);
+ }
+
+ public static boolean getHeartrateAlert(String deviceAddress) throws IllegalArgumentException {
+ Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
+ return prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_ENABLED, false);
+ }
+
+ public static int getHeartrateAlertThreshold(String deviceAddress) throws IllegalArgumentException {
+ Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
+ return prefs.getInt(DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_THRESHOLD, 150);
+ }
+
+ public static boolean getHeartrateStressMonitoring(String deviceAddress) throws IllegalArgumentException {
+ Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
+ return prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_HEARTRATE_STRESS_MONITORING, false);
+ }
+
public static boolean getBtConnectedAdvertising(String deviceAddress) {
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
return prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_BT_CONNECTED_ADVERTISEMENT, false);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband5/MiBand5Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband5/MiBand5Coordinator.java
index 57d9531af..edf442680 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband5/MiBand5Coordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband5/MiBand5Coordinator.java
@@ -106,7 +106,7 @@ public class MiBand5Coordinator extends HuamiCoordinator {
R.xml.devicesettings_miband5,
R.xml.devicesettings_vibrationpatterns,
R.xml.devicesettings_wearlocation,
- R.xml.devicesettings_heartrate_sleep,
+ R.xml.heartrate_sleep_alert_activity_stress,
R.xml.devicesettings_goal_notification,
R.xml.devicesettings_custom_emoji_font,
R.xml.devicesettings_timeformat,
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java
index 006cf6290..a74f3079d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java
@@ -171,6 +171,10 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_START;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_END;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_LIFT_WRIST;
+import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ACTIVITY_MONITORING;
+import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_ENABLED;
+import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_THRESHOLD;
+import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_STRESS_MONITORING;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_INACTIVITY_ENABLE;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_INACTIVITY_START;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_INACTIVITY_END;
@@ -230,6 +234,7 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.CO
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.COMMAND_GPS_VERSION;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.COMMAND_WORKOUT_ACTIVITY_TYPES;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.DISPLAY_ITEM_BIT_CLOCK;
+import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.ENDPOINT_DISPLAY;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.ENDPOINT_DISPLAY_ITEMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_COUNT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_PROFILE;
@@ -679,6 +684,37 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
return this;
}
+ private HuamiSupport setHeartrateActivityMonitoring(TransactionBuilder builder) {
+ final boolean enableHrActivityMonitoring = HuamiCoordinator.getHeartrateActivityMonitoring(gbDevice.getAddress());
+ final byte[] cmd = {ENDPOINT_DISPLAY, 0x22, 0x00, (byte) (enableHrActivityMonitoring ? 0x01 : 0x00)};
+ writeToConfiguration(builder, cmd);
+ return this;
+ }
+
+ private HuamiSupport setHeartrateAlert(TransactionBuilder builder) {
+ final boolean enableHrAlert = HuamiCoordinator.getHeartrateAlert(gbDevice.getAddress());
+ final int hrAlertThreshold = HuamiCoordinator.getHeartrateAlertThreshold(gbDevice.getAddress());
+
+ final byte[] cmd = {
+ ENDPOINT_DISPLAY,
+ 0x1a,
+ 0x00,
+ (byte) (enableHrAlert ? 0x01 : 0x00),
+ (byte) hrAlertThreshold
+ };
+
+ writeToConfiguration(builder, cmd);
+
+ return this;
+ }
+
+ private HuamiSupport setHeartrateStressMonitoring(TransactionBuilder builder) {
+ final boolean enableHrStressMonitoring = HuamiCoordinator.getHeartrateStressMonitoring(gbDevice.getAddress());
+ final byte[] cmd = new byte[] {(byte) 0xfe, 0x06, 0x00, (byte) (enableHrStressMonitoring ? 0x01 : 0x00)};
+ writeToConfiguration(builder, cmd);
+ return this;
+ }
+
private HuamiSupport setHeartrateMeasurementInterval(TransactionBuilder builder, int minutes) {
if (characteristicHRControlPoint != null) {
builder.notify(characteristicHRControlPoint, true);
@@ -2536,6 +2572,16 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
case PREF_HUAMI_VIBRATION_TRY_FIND_BAND:
setVibrationPattern(builder, config);
break;
+ case PREF_HEARTRATE_ACTIVITY_MONITORING:
+ setHeartrateActivityMonitoring(builder);
+ break;
+ case PREF_HEARTRATE_ALERT_ENABLED:
+ case PREF_HEARTRATE_ALERT_THRESHOLD:
+ setHeartrateAlert(builder);
+ break;
+ case PREF_HEARTRATE_STRESS_MONITORING:
+ setHeartrateStressMonitoring(builder);
+ break;
}
builder.queue(getQueue());
} catch (IOException e) {
@@ -3677,6 +3723,9 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
setGoalNotification(builder);
setInactivityWarnings(builder);
setHeartrateSleepSupport(builder);
+ setHeartrateActivityMonitoring(builder);
+ setHeartrateAlert(builder);
+ setHeartrateStressMonitoring(builder);
setDisconnectNotification(builder);
setExposeHRThridParty(builder);
setHeartrateMeasurementInterval(builder, HuamiCoordinator.getHeartRateMeasurementInterval(getDevice().getAddress()));
diff --git a/app/src/main/res/drawable/ic_mood_bad.xml b/app/src/main/res/drawable/ic_mood_bad.xml
new file mode 100644
index 000000000..7548a5887
--- /dev/null
+++ b/app/src/main/res/drawable/ic_mood_bad.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_warning_gray.xml b/app/src/main/res/drawable/ic_warning_gray.xml
new file mode 100644
index 000000000..98ce89163
--- /dev/null
+++ b/app/src/main/res/drawable/ic_warning_gray.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index aa3c82889..f9d8d1377 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1581,6 +1581,34 @@
- 3600
+
+ - @string/heartrate_bpm_100
+ - @string/heartrate_bpm_105
+ - @string/heartrate_bpm_110
+ - @string/heartrate_bpm_112
+ - @string/heartrate_bpm_120
+ - @string/heartrate_bpm_125
+ - @string/heartrate_bpm_130
+ - @string/heartrate_bpm_135
+ - @string/heartrate_bpm_140
+ - @string/heartrate_bpm_145
+ - @string/heartrate_bpm_150
+
+
+
+ - 100
+ - 105
+ - 110
+ - 112
+ - 120
+ - 125
+ - 130
+ - 135
+ - 140
+ - 145
+ - 150
+
+
- @string/off
- @string/interval_five_minutes
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bd5c99c3c..895419d9c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -482,6 +482,17 @@
every 15 minutes
every 30 minutes
every 45 minutes
+ 100 bpm
+ 105 bpm
+ 110 bpm
+ 112 bpm
+ 120 bpm
+ 125 bpm
+ 130 bpm
+ 135 bpm
+ 140 bpm
+ 145 bpm
+ 150 bpm
once an hour
Speed zones
Total minutes
@@ -538,6 +549,13 @@
Do some activity and synchronize device.
About to transfer %1$s of data starting from %2$s
Daily step target
+ Heart rate alert (experimental)
+ Vibrate the band when the heart rate is over a threshold, without any obvious physical activity in the last 10 minutes. This feature is experimental, and was not extensively tested.
+ Heart rate alert threshold
+ Stress monitoring
+ Monitor stress level while resting
+ Activity monitoring
+ Automatically increase the heart rate detection frequency when the band detects physical exercise, to increase heart rate capture accuracy.
Error executing \'%1$s\'
Your activity (ALPHA)
Cannot connect: %1$s
@@ -685,6 +703,7 @@
Disable inactivity warnings for a time interval
Heart Rate Monitoring
Configure heart rate monitoring
+ Configure heart rate monitoring and alert thresholds
Start time
End time
Activate display upon lift during Do Not Disturb
diff --git a/app/src/main/res/xml/heartrate_sleep_alert_activity_stress.xml b/app/src/main/res/xml/heartrate_sleep_alert_activity_stress.xml
new file mode 100644
index 000000000..7abecfa16
--- /dev/null
+++ b/app/src/main/res/xml/heartrate_sleep_alert_activity_stress.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+