1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-08 22:28:20 +02:00

Mi Band 5: Add HR activity monitoring, HR alerts, stress monitoring

This commit is contained in:
José Rebelo 2022-05-16 17:42:02 +01:00
parent 428af7f21e
commit 91e9451a87
10 changed files with 228 additions and 4 deletions

View File

@ -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";

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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()));

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#7E7E7E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM15.5,11c0.83,0 1.5,-0.67 1.5,-1.5S16.33,8 15.5,8 14,8.67 14,9.5s0.67,1.5 1.5,1.5zM8.5,11c0.83,0 1.5,-0.67 1.5,-1.5S9.33,8 8.5,8 7,8.67 7,9.5 7.67,11 8.5,11zM12,14c-2.33,0 -4.31,1.46 -5.11,3.5h10.22c-0.8,-2.04 -2.78,-3.5 -5.11,-3.5z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#7E7E7E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
</vector>

View File

@ -1581,6 +1581,34 @@
<item>3600</item>
</string-array>
<string-array name="prefs_miband_heartrate_alert_threshold">
<item name="100">@string/heartrate_bpm_100</item>
<item name="105">@string/heartrate_bpm_105</item>
<item name="110">@string/heartrate_bpm_110</item>
<item name="112">@string/heartrate_bpm_112</item>
<item name="120">@string/heartrate_bpm_120</item>
<item name="125">@string/heartrate_bpm_125</item>
<item name="130">@string/heartrate_bpm_130</item>
<item name="135">@string/heartrate_bpm_135</item>
<item name="140">@string/heartrate_bpm_140</item>
<item name="145">@string/heartrate_bpm_145</item>
<item name="150">@string/heartrate_bpm_150</item>
</string-array>
<string-array name="prefs_miband_heartrate_alert_threshold_values">
<item>100</item>
<item>105</item>
<item>110</item>
<item>112</item>
<item>120</item>
<item>125</item>
<item>130</item>
<item>135</item>
<item>140</item>
<item>145</item>
<item>150</item>
</string-array>
<string-array name="prefs_zetime_heartrate_measurement_interval">
<item name="0">@string/off</item>
<item name="300">@string/interval_five_minutes</item>

View File

@ -482,6 +482,17 @@
<string name="interval_fifteen_minutes">every 15 minutes</string>
<string name="interval_thirty_minutes">every 30 minutes</string>
<string name="interval_forty_five_minutes">every 45 minutes</string>
<string name="heartrate_bpm_100">100 bpm</string>
<string name="heartrate_bpm_105">105 bpm</string>
<string name="heartrate_bpm_110">110 bpm</string>
<string name="heartrate_bpm_112">112 bpm</string>
<string name="heartrate_bpm_120">120 bpm</string>
<string name="heartrate_bpm_125">125 bpm</string>
<string name="heartrate_bpm_130">130 bpm</string>
<string name="heartrate_bpm_135">135 bpm</string>
<string name="heartrate_bpm_140">140 bpm</string>
<string name="heartrate_bpm_145">145 bpm</string>
<string name="heartrate_bpm_150">150 bpm</string>
<string name="interval_one_hour">once an hour</string>
<string name="stats_title">Speed zones</string>
<string name="stats_x_axis_label">Total minutes</string>
@ -538,6 +549,13 @@
<string name="chart_get_active_and_synchronize">Do some activity and synchronize device.</string>
<string name="user_feedback_miband_activity_data_transfer">About to transfer %1$s of data starting from %2$s</string>
<string name="miband_prefs_fitness_goal">Daily step target</string>
<string name="prefs_heartrate_alert_experimental_title">Heart rate alert (experimental)</string>
<string name="prefs_heartrate_alert_experimental_description">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.</string>
<string name="prefs_heartrate_alert_threshold">Heart rate alert threshold</string>
<string name="prefs_stress_monitoring_title">Stress monitoring</string>
<string name="prefs_stress_monitoring_description">Monitor stress level while resting</string>
<string name="prefs_activity_monitoring_title">Activity monitoring</string>
<string name="prefs_activity_monitoring_description">Automatically increase the heart rate detection frequency when the band detects physical exercise, to increase heart rate capture accuracy.</string>
<string name="dbaccess_error_executing">Error executing \'%1$s\'</string>
<string name="controlcenter_start_activitymonitor">Your activity (ALPHA)</string>
<string name="cannot_connect">Cannot connect: %1$s</string>
@ -685,6 +703,7 @@
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Disable inactivity warnings for a time interval</string>
<string name="mi2_prefs_heart_rate_monitoring">Heart Rate Monitoring</string>
<string name="mi2_prefs_heart_rate_monitoring_summary">Configure heart rate monitoring</string>
<string name="mi2_prefs_heart_rate_monitoring_alerts_summary">Configure heart rate monitoring and alert thresholds</string>
<string name="mi2_prefs_do_not_disturb_start">Start time</string>
<string name="mi2_prefs_do_not_disturb_end">End time</string>
<string name="mi2_prefs_do_not_disturb_lift_wrist">Activate display upon lift during Do Not Disturb</string>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_heartrate"
android:key="heartrate_monitoring_key"
android:persistent="false"
android:summary="@string/mi2_prefs_heart_rate_monitoring_alerts_summary"
android:title="@string/mi2_prefs_heart_rate_monitoring">
<SwitchPreference
android:defaultValue="false"
android:icon="@drawable/ic_activity_sleep"
android:key="heartrate_sleep_detection"
android:title="@string/miband_prefs_hr_sleep_detection" />
<ListPreference
android:defaultValue="0"
android:entries="@array/prefs_heartrate_measurement_interval"
android:entryValues="@array/prefs_heartrate_measurement_interval_values"
android:icon="@drawable/ic_heartrate"
android:key="heartrate_measurement_interval"
android:summary="%s"
android:title="@string/prefs_title_heartrate_measurement_interval" />
<!-- Activity Monitoring -->
<SwitchPreference
android:defaultValue="false"
android:icon="@drawable/ic_activity_unknown_small"
android:key="heartrate_activity_monitoring"
android:summary="@string/prefs_activity_monitoring_description"
android:title="@string/prefs_activity_monitoring_title" />
<!-- Heart Rate Alerts -->
<SwitchPreference
android:defaultValue="false"
android:icon="@drawable/ic_warning_gray"
android:key="heartrate_alert_enabled"
android:summary="@string/prefs_heartrate_alert_experimental_description"
android:title="@string/prefs_heartrate_alert_experimental_title" />
<ListPreference
android:defaultValue="0"
android:dependency="heartrate_alert_enabled"
android:entries="@array/prefs_miband_heartrate_alert_threshold"
android:entryValues="@array/prefs_miband_heartrate_alert_threshold_values"
android:icon="@drawable/ic_heartrate"
android:key="heartrate_alert_threshold"
android:summary="%s"
android:title="@string/prefs_heartrate_alert_threshold" />
<!-- Stress Monitoring -->
<SwitchPreference
android:defaultValue="false"
android:icon="@drawable/ic_mood_bad"
android:key="heartrate_stress_monitoring"
android:summary="@string/prefs_stress_monitoring_description"
android:title="@string/prefs_stress_monitoring_title" />
</PreferenceScreen>
</androidx.preference.PreferenceScreen>