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 a7adf687..84d1d781 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 @@ -53,6 +53,7 @@ public class MiBand2Service { public static final int ALERT_LEVEL_MESSAGE = 1; public static final int ALERT_LEVEL_PHONE_CALL = 2; public static final int ALERT_LEVEL_VIBRATE_ONLY = 3; + public static final int ALERT_LEVEL_CUSTOM = 0xfa; // followed by another uin8 to select the actual icon // set metric distance // set 12 hour time mode @@ -109,6 +110,41 @@ public class MiBand2Service { public static final byte[] COMMAND_SET_FITNESS_GOAL_START = new byte[] { 0x10, 0x0, 0x0 }; public static final byte[] COMMAND_SET_FITNESS_GOAL_END = new byte[] { 0, 0 }; + public static final byte ICON_CHAT = 0x00; + public static final byte ICON_PENGUIN = 0x01; + public static final byte ICON_CHAT_MI = 0x02; + public static final byte ICON_FB = 0x03; + public static final byte ICON_TWITTER = 0x04; + public static final byte ICON_MIBAND = 0x05; + public static final byte ICON_SNAPCHAT = 0x06; + public static final byte ICON_WHATSAPP = 0x07; + public static final byte ICON_MANTA = 0x08; + public static final byte ICON_XX0 = 0x09; + public static final byte ICON_ALARM = 0x10; + public static final byte ICON_SHATTERED_GLASS = 0x11; + public static final byte ICON_INSTAGRAM = 0x12; + public static final byte ICON_CHAT_GHOST = 0x13; + public static final byte ICON_COW = 0x14; + public static final byte ICON_XX2 = 0x15; + public static final byte ICON_XX3 = 0x16; + public static final byte ICON_XX4 = 0x17; + public static final byte ICON_XX5 = 0x18; + public static final byte ICON_XX6 = 0x19; + public static final byte ICON_EGALE = 0x1a; + public static final byte ICON_CALENDAR = 0x1b; + public static final byte ICON_XX7 = 0x1c; + public static final byte ICON_PHONE_CALL = 0x1d; + public static final byte ICON_CHAT_LINE = 0x1e; + public static final byte ICON_TELEGRAM = 0x1f; + public static final byte ICON_CHAT_TALK = 0x20; + public static final byte ICON_SKYPE = 0x21; + public static final byte ICON_VK = 0x22; + public static final byte ICON_CIRCLES = 0x23; + public static final byte ICON_HANGOUTS = 0x24; + public static final byte ICON_MI = 0x25; + + public static final byte ICON_HIGH_PRIORITY = 0x7; + public static byte ENDPOINT_DISPLAY = 0x06; @@ -119,7 +155,7 @@ public class MiBand2Service { public static final byte[] COMMAND_ENABLE_DISPLAY_ON_LIFT_WRIST = new byte[]{ENDPOINT_DISPLAY, 0x05, 0x00, 0x01}; public static final byte[] COMMAND_DISABLE_DISPLAY_ON_LIFT_WRIST = new byte[]{ENDPOINT_DISPLAY, 0x05, 0x00, 0x00}; 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, 0x0 }; + public static final byte[] DISPLAY_YYY = new byte[] {ENDPOINT_DISPLAY, 0x10, 0x0, 0x1, 0x1 }; public static final byte RESPONSE = 0x10; @@ -148,7 +184,6 @@ public class MiBand2Service { public static final byte[] COMMAND_DISABLE_HR_SLEEP_MEASUREMENT = new byte[]{0x15, 0x00, 0x00}; public static final byte[] COMMAND_TEXT_NOTIFICATION = new byte[] {0x05, 0x01}; - public static final byte COMMAND_ALERT_CATEGORY_CHAT = (byte) 0xfa; static { MIBAND_DEBUG = new HashMap<>(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java index a8741868..3c7e6ae4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java @@ -36,7 +36,8 @@ public enum AlertCategory { InstantMessage(9), // 10-250 reserved for future use // 251-255 defined by service specification - Any(255); + Any(255), + Custom(-1); private final int id; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java index 37f3ddc0..48b11552 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java @@ -56,7 +56,7 @@ public class AlertNotificationProfile exten public void newAlert(TransactionBuilder builder, NewAlert alert, OverflowStrategy strategy) { BluetoothGattCharacteristic characteristic = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_NEW_ALERT); if (characteristic != null) { - String message = alert.getMessage(); + String message = StringUtils.ensureNotNull(alert.getMessage()); if (message.length() > MAX_MSG_LENGTH && strategy == OverflowStrategy.TRUNCATE) { message = StringUtils.truncate(message, MAX_MSG_LENGTH); } @@ -66,42 +66,42 @@ public class AlertNotificationProfile exten numChunks++; } - boolean hasAlerted = false; - for (int i = 0; i < numChunks; i++) { - int offset = i * MAX_MSG_LENGTH; - int restLength = message.length() - offset; - message = message.substring(offset, offset + Math.min(MAX_MSG_LENGTH, restLength)); - if (hasAlerted && message.length() == 0) { - // no need to do it again when there is no text content - break; + try { + boolean hasAlerted = false; + for (int i = 0; i < numChunks; i++) { + int offset = i * MAX_MSG_LENGTH; + int restLength = message.length() - offset; + message = message.substring(offset, offset + Math.min(MAX_MSG_LENGTH, restLength)); + if (hasAlerted && message.length() == 0) { + // no need to do it again when there is no text content + break; + } + builder.write(characteristic, getAlertMessage(alert, message, 1)); + hasAlerted = true; } - writeAlertMessage(builder, characteristic, alert, message, i); - hasAlerted = true; - } - if (!hasAlerted) { - writeAlertMessage(builder, characteristic, alert, "", 1); + if (!hasAlerted) { + builder.write(characteristic, getAlertMessage(alert, "", 1)); + } + } catch (IOException ex) { + // ain't gonna happen + LOG.error("Error writing alert message to ByteArrayOutputStream"); } } else { LOG.warn("NEW_ALERT characteristic not available"); } } - protected void writeAlertMessage(TransactionBuilder builder, BluetoothGattCharacteristic characteristic, NewAlert alert, String message, int chunk) { - try { - ByteArrayOutputStream stream = new ByteArrayOutputStream(100); - stream.write(BLETypeConversions.fromUint8(alert.getCategory().getId())); - stream.write(BLETypeConversions.fromUint8(alert.getNumAlerts())); + protected byte[] getAlertMessage(NewAlert alert, String message, int chunk) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(100); + stream.write(BLETypeConversions.fromUint8(alert.getCategory().getId())); + stream.write(BLETypeConversions.fromUint8(alert.getNumAlerts())); - if (message.length() > 0) { - stream.write(BLETypeConversions.toUtf8s(message)); - } else { - // some write a null byte instead of leaving out this optional value + if (message.length() > 0) { + stream.write(BLETypeConversions.toUtf8s(message)); + } else { + // some write a null byte instead of leaving out this optional value // stream.write(new byte[] {0}); - } - builder.write(characteristic, stream.toByteArray()); - } catch (IOException ex) { - // ain't gonna happen - LOG.error("Error writing alert message to ByteArrayOutputStream"); } + return stream.toByteArray(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java index fcb5e009..2df2fee5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java @@ -22,6 +22,7 @@ import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.content.Intent; import android.net.Uri; +import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.widget.Toast; @@ -72,7 +73,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; -import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; @@ -248,7 +248,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { * @param extraAction an extra action to be executed after every vibration and flash sequence. Allows to abort the repetition, for example. * @param builder */ - private MiBandSupport sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) { + private MiBandSupport sendCustomNotification(VibrationProfile vibrationProfile, @Nullable SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) { getNotificationStrategy().sendCustomNotification(vibrationProfile, simpleNotification, flashTimes, flashColour, originalColour, flashDuration, extraAction, builder); LOG.info("Sending notification to MiBand"); return this; @@ -487,7 +487,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } } - private void performPreferredNotification(String task, SimpleNotification simpleNotification, String notificationOrigin, BtLEAction extraAction) { + private void performPreferredNotification(String task, @Nullable SimpleNotification simpleNotification, String notificationOrigin, BtLEAction extraAction) { try { TransactionBuilder builder = performInitialized(task); Prefs prefs = GBApplication.getPrefs(); @@ -572,11 +572,8 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { return; } - String message = NotificationUtils.getPreferredTextFor(notificationSpec, 40, 40, getContext()).trim(); - SimpleNotification simpleNotification = new SimpleNotification(message, BLETypeConversions.toAlertCategory(notificationSpec.type)); - String origin = notificationSpec.type.getGenericType(); - performPreferredNotification(origin + " received", simpleNotification, origin, null); + performPreferredNotification(origin + " received", null, origin, null); } private void onAlarmClock(NotificationSpec notificationSpec) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NoNotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NoNotificationStrategy.java index 0aa68d25..32054d35 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NoNotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NoNotificationStrategy.java @@ -39,4 +39,9 @@ public class NoNotificationStrategy implements NotificationStrategy { public void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) { LOG.info("dummy notification stragegy: custom notification: " + simpleNotification); } + + @Override + public void stopCurrentNotification(TransactionBuilder builder) { + LOG.info("dummy notification stragegy: stop notification"); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NotificationStrategy.java index 2d23b50f..896b349c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/NotificationStrategy.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband; +import android.support.annotation.Nullable; + import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; @@ -27,7 +29,7 @@ public interface NotificationStrategy { /** * Adds a custom notification to the given transaction builder * @param vibrationProfile specifies how and how often the Band shall vibrate. - * @param simpleNotification + * @param simpleNotification an optional notification containing a type and text message * @param flashTimes * @param flashColour * @param originalColour @@ -35,5 +37,11 @@ public interface NotificationStrategy { * @param extraAction an extra action to be executed after every vibration and flash sequence. Allows to abort the repetition, for example. * @param builder */ - void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder); + void sendCustomNotification(VibrationProfile vibrationProfile, @Nullable SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder); + + /** + * Stops any current notification. + * @param builder + */ + void stopCurrentNotification(TransactionBuilder builder); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V1NotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V1NotificationStrategy.java index 3b58940c..30a4e186 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V1NotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V1NotificationStrategy.java @@ -103,6 +103,12 @@ public class V1NotificationStrategy implements NotificationStrategy { } } + @Override + public void stopCurrentNotification(TransactionBuilder builder) { + BluetoothGattCharacteristic controlPoint = support.getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); + builder.write(controlPoint, stopVibrate); + } + // 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 diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V2NotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V2NotificationStrategy.java index ff72eb21..865b30d2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V2NotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/V2NotificationStrategy.java @@ -17,25 +17,23 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband; import android.bluetooth.BluetoothGattCharacteristic; +import android.support.annotation.Nullable; import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; -import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert; -import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.OverflowStrategy; import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotification; -public class V2NotificationStrategy implements NotificationStrategy { - private final AbstractBTLEDeviceSupport support; +public class V2NotificationStrategy implements NotificationStrategy { + private final T support; - public V2NotificationStrategy(AbstractBTLEDeviceSupport support) { + public V2NotificationStrategy(T support) { this.support = support; } - protected AbstractBTLEDeviceSupport getSupport() { + protected T getSupport() { return support; } @@ -45,7 +43,7 @@ public class V2NotificationStrategy implements NotificationStrategy { sendCustomNotification(profile, simpleNotification, extraAction, builder); } - protected void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, BtLEAction extraAction, TransactionBuilder builder) { + protected void sendCustomNotification(VibrationProfile vibrationProfile, @Nullable SimpleNotification simpleNotification, BtLEAction extraAction, TransactionBuilder builder) { //use the new alert characteristic BluetoothGattCharacteristic alert = support.getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL); for (short i = 0; i < vibrationProfile.getRepeat(); i++) { @@ -69,13 +67,6 @@ public class V2NotificationStrategy implements NotificationStrategy { } } } -// sendAlert(simpleNotification, builder); - } - - protected void sendAlert(SimpleNotification simpleNotification, TransactionBuilder builder) { - AlertNotificationProfile profile = new AlertNotificationProfile<>(getSupport()); - NewAlert alert = new NewAlert(simpleNotification.getAlertCategory(), 1, simpleNotification.getMessage()); - profile.newAlert(builder, alert, OverflowStrategy.MAKE_MULTIPLE); } @Override @@ -83,4 +74,10 @@ public class V2NotificationStrategy implements NotificationStrategy { // all other parameters are unfortunately not supported anymore ;-( sendCustomNotification(vibrationProfile, simpleNotification, extraAction, builder); } + + @Override + public void stopCurrentNotification(TransactionBuilder builder) { + BluetoothGattCharacteristic alert = support.getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL); + builder.write(alert, new byte[]{GattCharacteristic.NO_ALERT}); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2NotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2NotificationStrategy.java index 497bc2f9..4ec7471f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2NotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2NotificationStrategy.java @@ -17,34 +17,34 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2; import android.bluetooth.BluetoothGattCharacteristic; +import android.support.annotation.Nullable; import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; -import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotification; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.V2NotificationStrategy; -public class Mi2NotificationStrategy extends V2NotificationStrategy { +public class Mi2NotificationStrategy extends V2NotificationStrategy { - public Mi2NotificationStrategy(AbstractBTLEDeviceSupport support) { + private final BluetoothGattCharacteristic alertLevelCharacteristic; + + public Mi2NotificationStrategy(MiBand2Support support) { super(support); + alertLevelCharacteristic = support.getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL); } @Override protected void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, BtLEAction extraAction, TransactionBuilder builder) { - //use the new alert characteristic - BluetoothGattCharacteristic alert = getSupport().getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL); for (short i = 0; i < vibrationProfile.getRepeat(); i++) { int[] onOffSequence = vibrationProfile.getOnOffSequence(); for (int j = 0; j < onOffSequence.length; j++) { int on = onOffSequence[j]; on = Math.min(500, on); // longer than 500ms is not possible - builder.write(alert, new byte[]{(byte) vibrationProfile.getAlertLevel()}); + startNotify(builder, vibrationProfile.getAlertLevel(), simpleNotification); builder.wait(on); - builder.write(alert, new byte[]{GattCharacteristic.NO_ALERT}); + stopNotify(builder); if (++j < onOffSequence.length) { int off = Math.max(onOffSequence[j], 25); // wait at least 25ms @@ -56,12 +56,19 @@ public class Mi2NotificationStrategy extends V2NotificationStrategy { } } } + } - sendAlert(simpleNotification, builder); + protected void startNotify(TransactionBuilder builder, int alertLevel, @Nullable SimpleNotification simpleNotification) { + builder.write(alertLevelCharacteristic, new byte[] {(byte) alertLevel}); + + } + + protected void stopNotify(TransactionBuilder builder) { + builder.write(alertLevelCharacteristic, new byte[]{GattCharacteristic.NO_ALERT}); } @Override - public void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) { + public void sendCustomNotification(VibrationProfile vibrationProfile, @Nullable SimpleNotification simpleNotification, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) { // all other parameters are unfortunately not supported anymore ;-( sendCustomNotification(vibrationProfile, simpleNotification, extraAction, builder); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2TextNotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2TextNotificationStrategy.java new file mode 100644 index 00000000..13f03ffb --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2TextNotificationStrategy.java @@ -0,0 +1,74 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2; + +import android.bluetooth.BluetoothGattCharacteristic; +import android.support.annotation.NonNull; +import android.util.Log; + +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; +import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; +import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; +import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.OverflowStrategy; +import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotification; +import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; + +public class Mi2TextNotificationStrategy extends Mi2NotificationStrategy { + private final BluetoothGattCharacteristic newAlertCharacteristic; + + public Mi2TextNotificationStrategy(MiBand2Support support) { + super(support); + newAlertCharacteristic = support.getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_NEW_ALERT); + } + + @Override + protected void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, BtLEAction extraAction, TransactionBuilder builder) { + if (simpleNotification != null && simpleNotification.getAlertCategory() == AlertCategory.IncomingCall) { + // incoming calls are notified solely via NewAlert including caller ID + sendAlert(simpleNotification, builder); + return; + } + + // announce text messages with configured alerts first + super.sendCustomNotification(vibrationProfile, simpleNotification, extraAction, builder); + // and finally send the text message, if any + if (simpleNotification != null && !StringUtils.isEmpty(simpleNotification.getMessage())) { + sendAlert(simpleNotification, builder); + } + } + + @Override + protected void startNotify(TransactionBuilder builder, int alertLevel, SimpleNotification simpleNotification) { + builder.write(newAlertCharacteristic, getNotifyMessage(simpleNotification)); + } + + protected byte[] getNotifyMessage(SimpleNotification simpleNotification) { + int numAlerts = 1; + if (simpleNotification != null) { + switch (simpleNotification.getAlertCategory()) { + case Email: + return new byte[] { BLETypeConversions.fromUint8(MiBand2Service.ALERT_LEVEL_MESSAGE), BLETypeConversions.fromUint8(numAlerts)}; + case InstantMessage: + return new byte[] { BLETypeConversions.fromUint8(MiBand2Service.ALERT_LEVEL_CUSTOM), BLETypeConversions.fromUint8(numAlerts), MiBand2Service.ICON_CHAT}; + case News: + return new byte[] { BLETypeConversions.fromUint8(MiBand2Service.ALERT_LEVEL_CUSTOM), BLETypeConversions.fromUint8(numAlerts), MiBand2Service.ICON_PENGUIN}; + } + } + return new byte[] { BLETypeConversions.fromUint8(AlertCategory.SMS.getId()), BLETypeConversions.fromUint8(numAlerts)}; + } + + protected void sendAlert(@NonNull SimpleNotification simpleNotification, TransactionBuilder builder) { + AlertNotificationProfile profile = new AlertNotificationProfile<>(getSupport()); + // override the alert category, since only SMS and incoming call support text notification + AlertCategory category = AlertCategory.SMS; + if (simpleNotification.getAlertCategory() == AlertCategory.IncomingCall) { + category = simpleNotification.getAlertCategory(); + } + NewAlert alert = new NewAlert(category, 1, simpleNotification.getMessage()); + profile.newAlert(builder, alert, OverflowStrategy.MAKE_MULTIPLE); + } +} 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 8b8a04ce..85e27256 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 @@ -84,6 +84,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.AbortTransactionAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.OverflowStrategy; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate.HeartRateProfile; import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotification; @@ -301,7 +304,8 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { } private NotificationStrategy getNotificationStrategy() { - return new Mi2NotificationStrategy(this); +// return new Mi2NotificationStrategy(this); + return new Mi2TextNotificationStrategy(this); } private static final byte[] startHeartMeasurementManual = new byte[]{0x15, MiBandService.COMMAND_SET_HR_MANUAL, 1}; @@ -440,6 +444,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { int flashDuration = getPreferredFlashDuration(notificationOrigin, prefs); sendCustomNotification(profile, simpleNotification, flashTimes, flashColour, originalColour, flashDuration, extraAction, builder); + // sendCustomNotification(vibrateDuration, vibrateTimes, vibratePause, flashTimes, flashColour, originalColour, flashDuration, builder); builder.queue(getQueue()); } catch (IOException ex) { @@ -563,6 +568,17 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { performPreferredNotification("incoming call", MiBandConst.ORIGIN_INCOMING_CALL, simpleNotification, MiBand2Service.ALERT_LEVEL_PHONE_CALL, abortAction); } else if ((callSpec.command == CallSpec.CALL_START) || (callSpec.command == CallSpec.CALL_END)) { telephoneRinging = false; + stopCurrentNotification(); + } + } + + private void stopCurrentNotification() { + try { + TransactionBuilder builder = performInitialized("stop notification"); + getNotificationStrategy().stopCurrentNotification(builder); + builder.queue(getQueue()); + } catch (IOException e) { + LOG.error("Error stopping notification"); } } @@ -642,7 +658,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { return !isLocatingDevice; } }; - SimpleNotification simpleNotification = new SimpleNotification(getContext().getString(R.string.find_device_you_found_it), AlertCategory.HighPriorityAlert.HighPriorityAlert); + SimpleNotification simpleNotification = new SimpleNotification(getContext().getString(R.string.find_device_you_found_it), AlertCategory.HighPriorityAlert); performDefaultNotification("locating device", simpleNotification, (short) 255, abortAction); } } @@ -1044,11 +1060,12 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { @Override public void onTestNewFunction() { try { - performInitialized("read characteristic 10") - .read(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_10_BUTTON)) - .queue(getQueue()); + TransactionBuilder builder = performInitialized("incoming call from peter"); + NewAlert alert = new NewAlert(AlertCategory.Custom, 1, new String(new byte[] {0x19})); + AlertNotificationProfile profile = new AlertNotificationProfile<>(this); + profile.newAlert(builder, alert, OverflowStrategy.MAKE_MULTIPLE); + builder.queue(getQueue()); } catch (IOException e) { - e.printStackTrace(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java index 8dcc07a0..0a9eaae2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java @@ -81,4 +81,15 @@ public class StringUtils { } return ""; } + + public static boolean isEmpty(String string) { + return string != null && string.length() == 0; + } + + public static String ensureNotNull(String message) { + if (message != null) { + return message; + } + return ""; + } }