From d1d3e758d9534bc24c0770452a2b914fd29cc538 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 17 May 2015 22:57:37 +0200 Subject: [PATCH] Support configurable notifications. Closes #53 To close #29, we need to have a bit more configuration options than just the number of vibrations. E.g. - duration - pause - LED flashing (again, number of flashes, duration and pause, but also the colour and maybe which LEDs) Also implements reboot-functionality for Mi Band. --- .../gadgetbridge/miband/MiBandConst.java | 64 +++++++++--- .../miband/MiBandPreferencesActivity.java | 23 ++--- .../gadgetbridge/miband/MiBandSupport.java | 98 ++++++++++++++++++- 3 files changed, 160 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java index 08bd389f7..3e7e71c59 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java @@ -1,14 +1,56 @@ package nodomain.freeyourgadget.gadgetbridge.miband; -public interface MiBandConst { - String PREF_USER_ALIAS = "mi_user_alias"; - String PREF_USER_YEAR_OF_BIRTH = "mi_user_year_of_birth"; - String PREF_USER_GENDER = "mi_user_gender"; - String PREF_USER_HEIGHT_CM = "mi_user_height_cm"; - String PREF_USER_WEIGHT_KG = "mi_user_weight_kg"; - String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_ - String PREF_VIBRATION_COUNT_SMS = "mi_vibration_count_sms"; - String PREF_VIBRATION_COUNT_K9MAIL = "mi_vibration_count_k9mail"; - String PREF_VIBRATION_COUNT_PEBBLEMSG = "mi_vibration_count_pebblemsg"; - String PREF_VIBRATION_COUNT_GENERIC = "mi_vibration_count_generic"; +import android.content.SharedPreferences; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class MiBandConst { + private static final Logger LOG = LoggerFactory.getLogger(MiBandConst.class); + + public static final String PREF_USER_ALIAS = "mi_user_alias"; + public static final String PREF_USER_YEAR_OF_BIRTH = "mi_user_year_of_birth"; + public static final String PREF_USER_GENDER = "mi_user_gender"; + public static final String PREF_USER_HEIGHT_CM = "mi_user_height_cm"; + public static final String PREF_USER_WEIGHT_KG = "mi_user_weight_kg"; + public static final String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_ + + public static final String ORIGIN_SMS = "sms"; + public static final String ORIGIN_K9MAIL = "k9mail"; + public static final String ORIGIN_PEBBLEMSG = "pebblemsg"; + public static final String ORIGIN_GENERIC = "generic"; + + public static int getNotificationPrefIntValue(String pref, String origin, SharedPreferences prefs, int defaultValue) { + String key = getNotificationPrefKey(pref, origin); + String value = null; + try { + value = prefs.getString(key, String.valueOf(defaultValue)); + return Integer.valueOf(value).intValue(); + } catch (NumberFormatException ex) { + LOG.error("Error converting preference value to int: " + key + ": " + value); + return defaultValue; + } + } + + public static final String getNotificationPrefKey(String pref, String origin) { + return new StringBuilder(pref).append('_').append(origin).toString(); + } + + public static final String VIBRATION_COUNT = "mi_vibration_count"; + public static final String VIBRATION_DURATION = "mi_vibration_duration"; + public static final String VIBRATION_PAUSE = "mi_vibration_pause"; + public static final String FLASH_COUNT = "mi_flash_count"; + public static final String FLASH_DURATION = "mi_flash_duration"; + public static final String FLASH_PAUSE = "mi_flash_pause"; + public static final String FLASH_COLOUR = "mi_flash_colour"; + public static final String FLASH_ORIGINAL_COLOUR = "mi_flash_original_colour"; + + public static final int DEFAULT_VALUE_VIBRATION_COUNT = 6; + public static final int DEFAULT_VALUE_VIBRATION_DURATION = 500; // ms + public static final int DEFAULT_VALUE_VIBRATION_PAUSE = 500; // ms + public static final int DEFAULT_VALUE_FLASH_COUNT = 10; // ms + public static final int DEFAULT_VALUE_FLASH_DURATION = 500; // ms + public static final int DEFAULT_VALUE_FLASH_PAUSE = 500; // ms + public static final int DEFAULT_VALUE_FLASH_COLOUR = 1; // TODO: colour! + public static final int DEFAULT_VALUE_FLASH_ORIGINAL_COLOUR = 1; // TODO: colour! } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java index 4b79aa0ab..a89ba1341 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java @@ -8,6 +8,7 @@ import android.support.v4.content.LocalBroadcastManager; import nodomain.freeyourgadget.gadgetbridge.ControlCenter; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.*; public class MiBandPreferencesActivity extends AbstractSettingsActivity { @Override @@ -16,7 +17,7 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity { addPreferencesFromResource(R.xml.miband_preferences); - final Preference developmentMiaddr = findPreference(MiBandConst.PREF_MIBAND_ADDRESS); + final Preference developmentMiaddr = findPreference(PREF_MIBAND_ADDRESS); developmentMiaddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { @@ -33,16 +34,16 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity { @Override protected String[] getPreferenceKeysWithSummary() { return new String[]{ - MiBandConst.PREF_USER_ALIAS, - MiBandConst.PREF_USER_YEAR_OF_BIRTH, - MiBandConst.PREF_USER_GENDER, - MiBandConst.PREF_USER_HEIGHT_CM, - MiBandConst.PREF_USER_WEIGHT_KG, - MiBandConst.PREF_MIBAND_ADDRESS, - MiBandConst.PREF_VIBRATION_COUNT_SMS, - MiBandConst.PREF_VIBRATION_COUNT_K9MAIL, - MiBandConst.PREF_VIBRATION_COUNT_PEBBLEMSG, - MiBandConst.PREF_VIBRATION_COUNT_GENERIC, + PREF_USER_ALIAS, + PREF_USER_YEAR_OF_BIRTH, + PREF_USER_GENDER, + PREF_USER_HEIGHT_CM, + PREF_USER_WEIGHT_KG, + PREF_MIBAND_ADDRESS, + getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_SMS), + getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_K9MAIL), + getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_PEBBLEMSG), + getNotificationPrefKey(VIBRATION_COUNT, ORIGIN_GENERIC), }; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java index c559acf09..959dae0c5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.miband; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import java.io.IOException; import java.util.Arrays; @@ -15,6 +17,8 @@ import nodomain.freeyourgadget.gadgetbridge.GBDevice.State; import nodomain.freeyourgadget.gadgetbridge.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.btle.TransactionBuilder; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.*; + public class MiBandSupport extends AbstractBTLEDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(MiBandSupport.class); @@ -60,6 +64,26 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { builder.write(characteristic, getDefaultNotification()).queue(getQueue()); } + private void sendCustomNotification(int vibrateDuration, int vibrateTimes, int pause, int flashTimes, int flashColour, int originalColour, long flashDuration, TransactionBuilder builder) { + BluetoothGattCharacteristic controlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); + int vDuration = Math.min(500, vibrateDuration); // longer than 500ms is not possible + for (int i = 0; i < vibrateTimes; i++) { + builder.write(controlPoint, startVibrate); + builder.wait(vDuration); + builder.write(controlPoint, stopVibrate); + if (pause > 0) { + builder.wait(pause); + } + } + + LOG.info("Sending notification to MiBand: " + controlPoint); + builder.queue(getQueue()); + } + + private static final byte[] startVibrate = new byte[]{ 8, 1 }; + private static final byte[] stopVibrate = new byte[]{ 19 }; + private static final byte[] reboot = new byte[]{ 12 }; + private byte[] getNotification(long vibrateDuration, int vibrateTimes, int flashTimes, int flashColour, int originalColour, long flashDuration) { byte[] vibrate = new byte[]{(byte) 8, (byte) 1}; byte r = 6; @@ -116,19 +140,76 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } } +// private void performCustomNotification(String task, int vibrateDuration, int vibrateTimes, int pause, int flashTimes, int flashColour, int originalColour, long flashDuration) { +// try { +// TransactionBuilder builder = performInitialized(task); +// sendCustomNotification(vibrateDuration, vibrateTimes, pause, flashTimes, flashColour, originalColour, flashDuration, builder); +// } catch (IOException ex) { +// LOG.error("Unable to send notification to MI device", ex); +// } +// } + + private void performPreferredNotification(String task, String notificationOrigin) { + try { + TransactionBuilder builder = performInitialized(task); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + int vibrateDuration = getPreferredVibrateDuration(notificationOrigin, prefs); + int vibrateTimes = getPreferredVibrateCount(notificationOrigin, prefs); + int vibratePause = getPreferredVibratePause(notificationOrigin, prefs); + + int flashTimes = getPreferredFlashCount(notificationOrigin, prefs); + int flashColour = getPreferredFlashColour(notificationOrigin, prefs); + int originalColour = getPreferredOriginalColour(notificationOrigin, prefs); + int flashDuration = getPreferredFlashDuration(notificationOrigin, prefs); + + sendCustomNotification(vibrateDuration, vibrateTimes, vibratePause, flashTimes, flashColour, originalColour, flashDuration, builder); + } catch (IOException ex) { + LOG.error("Unable to send notification to MI device", ex); + } + } + + private int getPreferredFlashDuration(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(FLASH_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_DURATION); + } + + private int getPreferredOriginalColour(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(FLASH_ORIGINAL_COLOUR, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_ORIGINAL_COLOUR); + } + + private int getPreferredFlashColour(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(FLASH_COLOUR, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_COLOUR); + } + + private int getPreferredFlashCount(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(FLASH_COUNT, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_COUNT); + } + + private int getPreferredVibratePause(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(VIBRATION_PAUSE, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_PAUSE); + } + + private int getPreferredVibrateCount(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(VIBRATION_COUNT, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_COUNT); + } + + private int getPreferredVibrateDuration(String notificationOrigin, SharedPreferences prefs) { + return getNotificationPrefIntValue(VIBRATION_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_DURATION); + } + @Override public void onSMS(String from, String body) { - performDefaultNotification("sms received"); +// performCustomNotification("sms received", 500, 3, 2000, 0, 0, 0, 0); + performPreferredNotification("sms received", ORIGIN_SMS); } @Override public void onEmail(String from, String subject, String body) { - performDefaultNotification("email received"); + performPreferredNotification("email received", ORIGIN_K9MAIL); } @Override public void onGenericNotification(String title, String details) { - performDefaultNotification("generic notification received"); + performPreferredNotification("generic notification received", ORIGIN_GENERIC); } @Override @@ -206,6 +287,17 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } } + @Override + public void onReboot() { + try { + TransactionBuilder builder = performInitialized("Reboot"); + builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT), reboot); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Unable to reboot MI", ex); + } + } + @Override public void onAppInfoReq() { // not supported