diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Coordinator.java
index 535da565..7cc26721 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Coordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Coordinator.java
@@ -47,9 +47,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
-import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DO_NOT_DISTURB_END;
-import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DO_NOT_DISTURB_START;
-
public class MiBand2Coordinator extends MiBandCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MiBand2Coordinator.class);
@@ -139,27 +136,54 @@ public class MiBand2Coordinator extends MiBandCoordinator {
return prefs.getBoolean(MiBandConst.PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO, false);
}
- public static Date getDoNotDisturbStart() {
+ public static boolean getInactivityWarnings() {
Prefs prefs = GBApplication.getPrefs();
- String time = prefs.getString(PREF_MI2_DO_NOT_DISTURB_START, "01:00");
+ return prefs.getBoolean(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS, false);
+ }
- DateFormat df = new SimpleDateFormat("HH:mm");
- try {
- return df.parse(time);
- } catch(Exception e) {
- }
+ public static int getInactivityWarningsThreshold() {
+ Prefs prefs = GBApplication.getPrefs();
+ return prefs.getInt(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD, 60);
+ }
- return new Date();
+ public static boolean getInactivityWarningsDnd() {
+ Prefs prefs = GBApplication.getPrefs();
+ return prefs.getBoolean(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND, false);
+ }
+
+ public static Date getInactivityWarningsStart() {
+ return getTimePreference(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_START, "06:00");
+ }
+
+ public static Date getInactivityWarningsEnd() {
+ return getTimePreference(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_END, "22:00");
+ }
+
+ public static Date getInactivityWarningsDndStart() {
+ return getTimePreference(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_START, "12:00");
+ }
+
+ public static Date getInactivityWarningsDndEnd() {
+ return getTimePreference(MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_END, "14:00");
+ }
+
+ public static Date getDoNotDisturbStart() {
+ return getTimePreference(MiBandConst.PREF_MI2_DO_NOT_DISTURB_START, "01:00");
}
public static Date getDoNotDisturbEnd() {
+ return getTimePreference(MiBandConst.PREF_MI2_DO_NOT_DISTURB_END, "06:00");
+ }
+
+ public static Date getTimePreference(String key, String defaultValue) {
Prefs prefs = GBApplication.getPrefs();
- String time = prefs.getString(PREF_MI2_DO_NOT_DISTURB_END, "06:00");
+ String time = prefs.getString(key, defaultValue);
DateFormat df = new SimpleDateFormat("HH:mm");
try {
return df.parse(time);
} catch(Exception e) {
+ LOG.error("Unexpected exception in MiBand2Coordinator.getTime: " + e.getMessage());
}
return new Date();
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java
index 3442cecb..90fb9c7b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java
@@ -174,6 +174,22 @@ public class MiBand2Service {
public static final byte[] DISPLAY_XXX = new byte[] {ENDPOINT_DISPLAY, 0x03, 0x0, 0x0 };
public static final byte[] DISPLAY_YYY = new byte[] {ENDPOINT_DISPLAY, 0x10, 0x0, 0x1, 0x1 };
+ // The third byte controls the threshold, in minutes
+ // The last 8 bytes represent 2 separate time intervals for the inactivity warnings
+ // If there is no do not disturb interval, the last 4 bytes (the second interval) are 0
+ // and only the first interval of the command is used
+ public static int INACTIVITY_WARNINGS_THRESHOLD = 2;
+ public static int INACTIVITY_WARNINGS_INTERVAL_1_START_HOURS = 4;
+ public static int INACTIVITY_WARNINGS_INTERVAL_1_START_MINUTES = 5;
+ public static int INACTIVITY_WARNINGS_INTERVAL_1_END_HOURS = 6;
+ public static int INACTIVITY_WARNINGS_INTERVAL_1_END_MINUTES = 7;
+ public static int INACTIVITY_WARNINGS_INTERVAL_2_START_HOURS = 8;
+ public static int INACTIVITY_WARNINGS_INTERVAL_2_START_MINUTES = 9;
+ public static int INACTIVITY_WARNINGS_INTERVAL_2_END_HOURS = 10;
+ public static int INACTIVITY_WARNINGS_INTERVAL_2_END_MINUTES = 11;
+ public static final byte[] COMMAND_ENABLE_INACTIVITY_WARNINGS = new byte[] { 0x08, 0x01, 0x3c, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ public static final byte[] COMMAND_DISABLE_INACTIVITY_WARNINGS = new byte[] { 0x08, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
public static byte ENDPOINT_DND = 0x09;
public static final byte[] COMMAND_DO_NOT_DISTURB_AUTOMATIC = new byte[] { ENDPOINT_DND, (byte) 0x83 };
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java
index a9bffb2c..cba053df 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java
@@ -52,6 +52,13 @@ public final class MiBandConst {
public static final String PREF_MI2_DO_NOT_DISTURB_SCHEDULED = "scheduled";
public static final String PREF_MI2_DO_NOT_DISTURB_START = "mi2_do_not_disturb_start";
public static final String PREF_MI2_DO_NOT_DISTURB_END = "mi2_do_not_disturb_end";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS = "mi2_inactivity_warnings";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD = "mi2_inactivity_warnings_threshold";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_START = "mi2_inactivity_warnings_start";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_END = "mi2_inactivity_warnings_end";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_DND = "mi2_inactivity_warnings_dnd";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_DND_START = "mi2_inactivity_warnings_dnd_start";
+ public static final String PREF_MI2_INACTIVITY_WARNINGS_DND_END = "mi2_inactivity_warnings_dnd_end";
public static final String PREF_MIBAND_SETUP_BT_PAIRING = "mi_setup_bt_pairing";
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPreferencesActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPreferencesActivity.java
index 124608a2..9aabf77e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPreferencesActivity.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPreferencesActivity.java
@@ -48,6 +48,13 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PR
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DO_NOT_DISTURB_START;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_ENABLE_TEXT_NOTIFICATIONS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_GOAL_NOTIFICATION;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_END;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_START;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_END;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_START;
+import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ADDRESS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS;
@@ -147,6 +154,104 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity {
}
});
+ final Preference inactivityWarnings = findPreference(PREF_MI2_INACTIVITY_WARNINGS);
+ inactivityWarnings.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsThreshold = findPreference(PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD);
+ inactivityWarningsThreshold.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsStart = findPreference(PREF_MI2_INACTIVITY_WARNINGS_START);
+ inactivityWarningsStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_START);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsEnd = findPreference(PREF_MI2_INACTIVITY_WARNINGS_END);
+ inactivityWarningsEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_END);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsDnd = findPreference(PREF_MI2_INACTIVITY_WARNINGS_DND);
+ inactivityWarningsDnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_DND);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsDndStart = findPreference(PREF_MI2_INACTIVITY_WARNINGS_DND_START);
+ inactivityWarningsDndStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_DND_START);
+ }
+ });
+ return true;
+ }
+ });
+
+ final Preference inactivityWarningsDndEnd = findPreference(PREF_MI2_INACTIVITY_WARNINGS_DND_END);
+ inactivityWarningsDndEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newVal) {
+ invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ GBApplication.deviceService().onSendConfiguration(PREF_MI2_INACTIVITY_WARNINGS_DND_END);
+ }
+ });
+ return true;
+ }
+ });
+
String doNotDisturbState = prefs.getString(MiBandConst.PREF_MI2_DO_NOT_DISTURB, PREF_MI2_DO_NOT_DISTURB_OFF);
boolean doNotDisturbScheduled = doNotDisturbState.equals(PREF_MI2_DO_NOT_DISTURB_SCHEDULED);
@@ -270,6 +375,7 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity {
prefKeys.add(PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR);
prefKeys.add(PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS);
prefKeys.add(PREF_MI2_ENABLE_TEXT_NOTIFICATIONS);
+ prefKeys.add(PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD);
prefKeys.add(getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_ALARM_CLOCK));
prefKeys.add(getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_INCOMING_CALL));
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
index 13878293..3307e766 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
@@ -1097,6 +1097,16 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
case MiBandConst.PREF_MI2_DO_NOT_DISTURB_START:
case MiBandConst.PREF_MI2_DO_NOT_DISTURB_END:
setDoNotDisturb(builder);
+ break;
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_THRESHOLD:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_START:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_END:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_START:
+ case MiBandConst.PREF_MI2_INACTIVITY_WARNINGS_DND_END:
+ setInactivityWarnings(builder);
+ break;
}
builder.queue(getQueue());
} catch (IOException e) {
@@ -1238,6 +1248,60 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
return this;
}
+ private MiBand2Support setInactivityWarnings(TransactionBuilder builder) {
+ boolean enable = MiBand2Coordinator.getInactivityWarnings();
+ LOG.info("Setting inactivity warnings to " + enable);
+
+ if (enable) {
+ byte[] data = MiBand2Service.COMMAND_ENABLE_INACTIVITY_WARNINGS.clone();
+
+ int threshold = MiBand2Coordinator.getInactivityWarningsThreshold();
+ data[MiBand2Service.INACTIVITY_WARNINGS_THRESHOLD] = (byte) threshold;
+
+ Calendar calendar = GregorianCalendar.getInstance();
+
+ boolean enableDnd = MiBand2Coordinator.getInactivityWarningsDnd();
+
+ Date intervalStart = MiBand2Coordinator.getInactivityWarningsStart();
+ Date intervalEnd = MiBand2Coordinator.getInactivityWarningsEnd();
+ Date dndStart = MiBand2Coordinator.getInactivityWarningsDndStart();
+ Date dndEnd = MiBand2Coordinator.getInactivityWarningsDndEnd();
+
+ // The first interval always starts when the warnings interval starts
+ calendar.setTime(intervalStart);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_START_HOURS] = (byte) calendar.get(Calendar.HOUR_OF_DAY);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_START_MINUTES] = (byte) calendar.get(Calendar.MINUTE);
+
+ if(enableDnd) {
+ // The first interval ends when the dnd interval starts
+ calendar.setTime(dndStart);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_END_HOURS] = (byte) calendar.get(Calendar.HOUR_OF_DAY);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_END_MINUTES] = (byte) calendar.get(Calendar.MINUTE);
+
+ // The second interval starts when the dnd interval ends
+ calendar.setTime(dndEnd);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_2_START_HOURS] = (byte) calendar.get(Calendar.HOUR_OF_DAY);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_2_START_MINUTES] = (byte) calendar.get(Calendar.MINUTE);
+
+ // ... and it ends when the warnings interval ends
+ calendar.setTime(intervalEnd);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_2_END_HOURS] = (byte) calendar.get(Calendar.HOUR_OF_DAY);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_2_END_MINUTES] = (byte) calendar.get(Calendar.MINUTE);
+ } else {
+ // No Dnd, use the first interval
+ calendar.setTime(intervalEnd);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_END_HOURS] = (byte) calendar.get(Calendar.HOUR_OF_DAY);
+ data[MiBand2Service.INACTIVITY_WARNINGS_INTERVAL_1_END_MINUTES] = (byte) calendar.get(Calendar.MINUTE);
+ }
+
+ builder.write(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_3_CONFIGURATION), data);
+ } else {
+ builder.write(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_3_CONFIGURATION), MiBand2Service.COMMAND_DISABLE_INACTIVITY_WARNINGS);
+ }
+
+ return this;
+ }
+
public void phase2Initialize(TransactionBuilder builder) {
LOG.info("phase2Initialize...");
enableFurtherNotifications(builder, true);
@@ -1251,6 +1315,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
setRotateWristToSwitchInfo(builder);
setActivateDisplayOnLiftWrist(builder);
setGoalNotification(builder);
+ setInactivityWarnings(builder);
setHeartrateSleepSupport(builder);
}
}
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 3516f7d2..fa52294b 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -310,6 +310,10 @@
A pulseira não recebe notificações enquanto activo
Hora de início
Hora de fim
+ Avisos de inactividade
+ A pulseira irá vibrar quando estiver inactivo durante algum tempo
+ Limite de inactividade (em minutos)
+ Desactivar os avisos de inactividade durante um intervalo de tempo
Prestes a transferir dados desde %1$s
aguarde para tornar a ligar
Sobre você
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4bc1ccf0..5989ccd6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -354,6 +354,10 @@
Rotate wrist to switch info
Do Not Disturb
The band won\'t receive notifications while active
+ Inactivity warnings
+ The band will vibrate when you have been inactive for a while
+ Inactivity threshold (in minutes)
+ Disable the inactivity warnings for a time interval
Start time
End time
About to transfer data since %1$s
diff --git a/app/src/main/res/xml/miband_preferences.xml b/app/src/main/res/xml/miband_preferences.xml
index e7338045..8419ab9f 100644
--- a/app/src/main/res/xml/miband_preferences.xml
+++ b/app/src/main/res/xml/miband_preferences.xml
@@ -84,6 +84,63 @@
android:title="@string/miband2_prefs_dateformat"
android:summary="%s" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+