From 3cc8d887ca1611b74389e8bf4046c51c0a96e150 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 13 Nov 2016 01:42:55 +0100 Subject: [PATCH] Mi2: Initial support for wear location, hr during sleep and date format #323 - wear location from prefs is sent to the band - hr measurement during sleep is sent to the band - date format is sent to the band (date+time or just time) (TODO: needs preference option) --- .../devices/miband/MiBand2Service.java | 19 +++++ .../devices/miband/MiBand2Support.java | 77 +++++++++++-------- .../service/devices/miband2/DateDisplay.java | 6 ++ .../miband2/operations/InitOperation.java | 2 +- .../gadgetbridge/util/.gitignore | 2 + 5 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/DateDisplay.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/.gitignore 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 064ac7b6..6f397364 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 @@ -279,6 +279,25 @@ public class MiBand2Service { */ public static final byte AUTH_BYTE = 0x8; + public static byte COMMAND_DATEFORMAT = 0x06; + + public static final byte[] DATEFORMAT_DATE_TIME = new byte[] { COMMAND_DATEFORMAT, 0x0a, 0x0, 0x03 }; + public static final byte[] DATEFORMAT_TIME = new byte[] { COMMAND_DATEFORMAT, 0x0a, 0x0, 0x0 }; + + public static final byte RESPONSE = 0x10; + + /** + * Received in response to any dateformat configuration request (byte 0 in the byte[] value. + */ + public static final byte[] RESPONSE_DATEFORMAT_SUCCESS = new byte[] { RESPONSE, COMMAND_DATEFORMAT, 0x0a, 0x0, 0x01 }; + + public static final byte[] WEAR_LOCATION_LEFT_WRIST = new byte[] { 0x20, 0x00, 0x00, 0x02 }; + public static final byte[] WEAR_LOCATION_RIGHT_WRIST = new byte[] { 0x20, 0x00, 0x00, (byte) 0x82}; + + public static final byte[] COMMAND_ENABLE_HR_SLEEP_MEASUREMENT = new byte[]{0x15, 0x00, 0x01}; + public static final byte[] COMMAND_DISABLE_HR_SLEEP_MEASUREMENT = new byte[]{0x15, 0x00, 0x00}; + + static { MIBAND_DEBUG = new HashMap<>(); MIBAND_DEBUG.put(UUID_SERVICE_MIBAND_SERVICE, "MiBand Service"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBand2Support.java index 4078fc8b..d8754e80 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBand2Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBand2Support.java @@ -52,11 +52,11 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.AbortTransactionAction; -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.ConditionalWriteAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WriteAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate.HeartRateProfile; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.DateDisplay; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2NotificationStrategy; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.InitOperation; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; @@ -394,28 +394,22 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { /** * Part of device initialization process. Do not call manually. * - * @param transaction + * @param builder * @return */ - private MiBand2Support setWearLocation(TransactionBuilder transaction) { + private MiBand2Support setWearLocation(TransactionBuilder builder) { LOG.info("Attempting to set wear location..."); - BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); + BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC8); if (characteristic != null) { - transaction.add(new ConditionalWriteAction(characteristic) { - @Override - protected byte[] checkCondition() { - if (getDeviceInfo() != null && getDeviceInfo().isAmazFit()) { - return null; - } - int location = MiBandCoordinator.getWearLocation(getDevice().getAddress()); - return new byte[]{ - MiBandService.COMMAND_SET_WEAR_LOCATION, - (byte) location - }; - } - }); - } else { - LOG.info("Unable to set Wear Location"); + int location = MiBandCoordinator.getWearLocation(getDevice().getAddress()); + switch (location) { + case 0: // left hand + builder.write(characteristic, MiBand2Service.WEAR_LOCATION_LEFT_WRIST); + break; + case 1: // write hand + builder.write(characteristic, MiBand2Service.WEAR_LOCATION_RIGHT_WRIST); + break; + } } return this; } @@ -447,20 +441,16 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { * @param builder */ private MiBand2Support setHeartrateSleepSupport(TransactionBuilder builder) { - BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT); - if (characteristic != null) { - builder.add(new ConditionalWriteAction(characteristic) { - @Override - protected byte[] checkCondition() { - if (MiBandCoordinator.getHeartrateSleepSupport(getDevice().getAddress())) { - LOG.info("Enabling heartrate sleep support..."); - return startHeartMeasurementSleep; - } else { - LOG.info("Disabling heartrate sleep support..."); - return stopHeartMeasurementSleep; - } - } - }); + BluetoothGattCharacteristic characteristicHRControlPoint = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT); + final boolean enableHrSleepSupport = MiBandCoordinator.getHeartrateSleepSupport(getDevice().getAddress()); + if (characteristicHRControlPoint != null) { + if (enableHrSleepSupport) { + LOG.info("Enabling heartrate sleep support..."); + builder.write(characteristicHRControlPoint, MiBand2Service.COMMAND_ENABLE_HR_SLEEP_MEASUREMENT); + } else { + LOG.info("Disabling heartrate sleep support..."); + builder.write(characteristicHRControlPoint, MiBand2Service.COMMAND_DISABLE_HR_SLEEP_MEASUREMENT); + } } return this; } @@ -1167,4 +1157,25 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { @Override public void onTestNewFunction() { } + + public MiBand2Support setDateDisplay(DateDisplay displayConfig, TransactionBuilder builder) { + LOG.info("Setting date display to " + displayConfig); + switch (displayConfig) { + case TIME: + builder.write(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3), MiBand2Service.DATEFORMAT_TIME); + break; + case DATE_TIME: + builder.write(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3), MiBand2Service.DATEFORMAT_DATE_TIME); + break; + } + return this; + } + + public void phase2Initialize(TransactionBuilder builder) { + LOG.info("phase2Initialize..."); + enableFurtherNotifications(builder, true); + setDateDisplay(DateDisplay.TIME, builder); + setWearLocation(builder); + setHeartrateSleepSupport(builder); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/DateDisplay.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/DateDisplay.java new file mode 100644 index 00000000..0ac7de53 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/DateDisplay.java @@ -0,0 +1,6 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2; + +public enum DateDisplay { + TIME, + DATE_TIME +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/InitOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/InitOperation.java index ab5f73e9..0d59c4b5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/InitOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/InitOperation.java @@ -101,7 +101,7 @@ public class InitOperation extends AbstractBTLEOperation { TransactionBuilder builder = createTransactionBuilder("Sending the encrypted random key to the band"); builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); getSupport().requestDeviceInfo(builder); - getSupport().enableFurtherNotifications(builder, true); + getSupport().phase2Initialize(builder); getSupport().setInitialized(builder); getSupport().performImmediately(builder); } else { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/.gitignore b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/.gitignore new file mode 100644 index 00000000..8242cf9f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/.gitignore @@ -0,0 +1,2 @@ +small/ +SmallHelper.java