diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index a4fbe772..c5d05183 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -53,6 +53,7 @@ public class DebugActivity extends Activity { private Button setMusicInfoButton; private Button setTimeButton; private Button rebootButton; + private Button HearRateButton; private Button exportDBButton; private Button importDBButton; private Button deleteDBButton; @@ -185,6 +186,13 @@ public class DebugActivity extends Activity { GBApplication.deviceService().onReboot(); } }); + HearRateButton = (Button) findViewById(R.id.HearRateButton); + HearRateButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + GBApplication.deviceService().onHearRateTest(); + } + }); setMusicInfoButton = (Button) findViewById(R.id.setMusicInfoButton); setMusicInfoButton.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java index 6d7bf853..1136f084 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java @@ -40,6 +40,8 @@ public interface EventHandler { void onReboot(); + void onHearRateTest(); + void onFindDevice(boolean start); void onScreenshotReq(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java index 349c0f48..7cf008bf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java @@ -14,6 +14,8 @@ public class MiBandService { public static final UUID UUID_SERVICE_MIBAND_SERVICE = UUID.fromString(String.format(BASE_UUID, "FEE0")); + public static final UUID UUID_SERVICE_HEART_RATE = UUID.fromString(String.format(BASE_UUID, "180D")); + public static final UUID UUID_CHARACTERISTIC_DEVICE_INFO = UUID.fromString(String.format(BASE_UUID, "FF01")); public static final UUID UUID_CHARACTERISTIC_DEVICE_NAME = UUID.fromString(String.format(BASE_UUID, "FF02")); @@ -44,6 +46,11 @@ public class MiBandService { public static final UUID UUID_CHARACTERISTIC_PAIR = UUID.fromString(String.format(BASE_UUID, "FF0F")); + public static final UUID UUID_CHAR_HEART_RATE_CONTROL_POINT = UUID.fromString(String.format(BASE_UUID, "2A39")); + public static final UUID UUID_CHAR_HEART_RATE_MEASUREMENT = UUID.fromString(String.format(BASE_UUID, "2A37")); + + + /* FURTHER UUIDS that were mixed with the other params below. The base UUID for these is unknown */ public static final String UUID_SERVICE_WEIGHT_SERVICE = "00001530-0000-3512-2118-0009af100700"; @@ -153,6 +160,12 @@ public class MiBandService { public static final byte COMMAND_SET_REALTIME_STEP = 0x10; + // Test HR + public static final byte COMMAND_SET_HR_SLEEP = 0x0 ; + public static final byte COMMAND_SET__HR_CONTINUOUS = 0x1 ; + public static final byte COMMAND_SET_HR_MANUAL = 0x2 ; + + /* FURTHER COMMANDS: unchecked therefore left commented @@ -213,6 +226,7 @@ public class MiBandService { static { MIBAND_DEBUG = new HashMap<>(); MIBAND_DEBUG.put(UUID_SERVICE_MIBAND_SERVICE, "MiBand Service"); + MIBAND_DEBUG.put(UUID_SERVICE_HEART_RATE, "MiBand HR Service"); MIBAND_DEBUG.put(UUID_CHARACTERISTIC_DEVICE_INFO, "Device Info"); MIBAND_DEBUG.put(UUID_CHARACTERISTIC_DEVICE_NAME, "Device Name"); @@ -229,6 +243,8 @@ public class MiBandService { MIBAND_DEBUG.put(UUID_CHARACTERISTIC_TEST, "Test"); MIBAND_DEBUG.put(UUID_CHARACTERISTIC_SENSOR_DATA, "Sensor Data"); MIBAND_DEBUG.put(UUID_CHARACTERISTIC_PAIR, "Pair"); + MIBAND_DEBUG.put(UUID_CHAR_HEART_RATE_CONTROL_POINT, "Heart Rate Control Point"); + MIBAND_DEBUG.put(UUID_CHAR_HEART_RATE_MEASUREMENT, "Heart Rate Measure"); } public static String lookup(UUID uuid, String fallback) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index cee7a5e2..54cc6c23 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -171,6 +171,12 @@ public class GBDeviceService implements DeviceService { invokeService(intent); } + @Override + public void onHearRateTest() { + Intent intent = createIntent().setAction(ACTION_HEARTRATE_TEST); + invokeService(intent); + } + @Override public void onFindDevice(boolean start) { Intent intent = createIntent().setAction(ACTION_FIND_DEVICE) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java index af4a6d1b..bd4f33e9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -26,13 +26,13 @@ public interface DeviceService extends EventHandler { String ACTION_DELETEAPP = PREFIX + ".action.deleteapp"; String ACTION_INSTALL = PREFIX + ".action.install"; String ACTION_REBOOT = PREFIX + ".action.reboot"; + String ACTION_HEARTRATE_TEST = PREFIX + ".action.heartrate_test"; String ACTION_FETCH_ACTIVITY_DATA = PREFIX + ".action.fetch_activity_data"; String ACTION_DISCONNECT = PREFIX + ".action.disconnect"; String ACTION_FIND_DEVICE = PREFIX + ".action.find_device"; String ACTION_SET_ALARMS = PREFIX + ".action.set_alarms"; String ACTION_ENABLE_REALTIME_STEPS = PREFIX + ".action.enable_realtime_steps"; String ACTION_REALTIME_STEPS = PREFIX + ".action.realtime_steps"; - String EXTRA_DEVICE_ADDRESS = "device_address"; String EXTRA_NOTIFICATION_BODY = "notification_body"; String EXTRA_NOTIFICATION_FLAGS = "notification_flags"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index d85c1290..15e6f1c6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -47,6 +47,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DI import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ENABLE_REALTIME_STEPS; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FETCH_ACTIVITY_DATA; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FIND_DEVICE; +import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_HEARTRATE_TEST; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_INSTALL; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REBOOT; @@ -251,6 +252,10 @@ public class DeviceCommunicationService extends Service { mDeviceSupport.onReboot(); break; } + case ACTION_HEARTRATE_TEST: { + mDeviceSupport.onHearRateTest(); + break; + } case ACTION_FETCH_ACTIVITY_DATA: { mDeviceSupport.onFetchActivityData(); break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java index b75b1c59..8faf48a9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java @@ -194,6 +194,14 @@ public class ServiceDeviceSupport implements DeviceSupport { delegate.onReboot(); } + @Override + public void onHearRateTest() { + if (checkBusy("heartrate")) { + return; + } + delegate.onHearRateTest(); + } + @Override public void onFindDevice(boolean start) { if (checkBusy("find device")) { 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 43d6c75d..2e839967 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 @@ -89,6 +89,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS); addSupportedService(GattService.UUID_SERVICE_GENERIC_ATTRIBUTE); addSupportedService(MiBandService.UUID_SERVICE_MIBAND_SERVICE); + addSupportedService(MiBandService.UUID_SERVICE_HEART_RATE); addSupportedService(GattService.UUID_SERVICE_IMMEDIATE_ALERT); } @@ -106,7 +107,8 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { .setCurrentTime(builder) .requestBatteryInfo(builder) .setInitialized(builder); - + // heartrate(builder) + // .requestHRInfo(builder); return builder; } @@ -199,6 +201,10 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } static final byte[] reboot = new byte[]{MiBandService.COMMAND_REBOOT}; + +// static final byte[] HeartMode = new byte[]{MiBandService.COMMAND_SET_HR_MANUAL}; + static final byte[] HeartMode = new byte[]{MiBandService.COMMAND_SET_HR_SLEEP}; + static final byte[] startRealTimeStepsNotifications = new byte[]{MiBandService.COMMAND_SET_REALTIME_STEPS_NOTIFICATION, 1}; static final byte[] stopRealTimeStepsNotifications = new byte[]{MiBandService.COMMAND_SET_REALTIME_STEPS_NOTIFICATION, 0}; @@ -245,6 +251,30 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { return this; } + /* private MiBandSupport requestHRInfo(TransactionBuilder builder) { + LOG.debug("Requesting HR Info!"); + BluetoothGattCharacteristic HRInfo = getCharacteristic(MiBandService.UUID_CHAR_HEART_RATE_MEASUREMENT); + builder.read(HRInfo); + BluetoothGattCharacteristic HR_Point = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT); + builder.read(HR_Point); + return this; + } + *//** + * Part of HR test. Do not call manually. + * + * @param transaction + * @return + *//* + private MiBandSupport heartrate(TransactionBuilder transaction) { + LOG.info("Attempting to read HR ..."); + BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHAR_HEART_RATE_MEASUREMENT); + if (characteristic != null) { + transaction.write(characteristic, new byte[]{MiBandService.COMMAND_SET__HR_CONTINUOUS}); + } else { + LOG.info("Unable to read HR from MI device -- characteristic not available"); + } + return this; + }*/ /** * Part of device initialization process. Do not call manually. * @@ -493,7 +523,16 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { LOG.error("Unable to reboot MI", ex); } } - + @Override + public void onHearRateTest() { + try { + TransactionBuilder builder = performInitialized("HeartRateTest"); + builder.write(getCharacteristic(MiBandService.UUID_CHAR_HEART_RATE_CONTROL_POINT), HeartMode); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Unable to read HearRate in MI1S", ex); + } + } @Override public void onFindDevice(boolean start) { isLocatingDevice = start; @@ -613,7 +652,12 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { handleNotificationNotif(characteristic.getValue()); } else if (MiBandService.UUID_CHARACTERISTIC_REALTIME_STEPS.equals(characteristicUUID)) { handleRealtimeSteps(characteristic.getValue()); - } else { + } else if (MiBandService.UUID_CHARACTERISTIC_REALTIME_STEPS.equals(characteristicUUID)) { + handleRealtimeSteps(characteristic.getValue()); + } else if (MiBandService.UUID_CHAR_HEART_RATE_MEASUREMENT.equals(characteristicUUID)) { + logMessageContent(characteristic.getValue()); + } + else { LOG.info("Unhandled characteristic changed: " + characteristicUUID); logMessageContent(characteristic.getValue()); } @@ -631,8 +675,8 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { handleDeviceName(characteristic.getValue(), status); } else if (MiBandService.UUID_CHARACTERISTIC_BATTERY.equals(characteristicUUID)) { handleBatteryInfo(characteristic.getValue(), status); - } else if (MiBandService.UUID_CHARACTERISTIC_REALTIME_STEPS.equals(characteristicUUID)) { - handleRealtimeSteps(characteristic.getValue()); + } else if (MiBandService.UUID_CHAR_HEART_RATE_MEASUREMENT.equals(characteristicUUID)) { + logMessageContent(characteristic.getValue()); } else { LOG.info("Unhandled characteristic read: "+ characteristicUUID); logMessageContent(characteristic.getValue()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java index 590bbb1d..d045789c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java @@ -37,6 +37,11 @@ public class PebbleSupport extends AbstractSerialDeviceSupport { getDeviceIOThread().installApp(uri, 0); } + @Override + public void onHearRateTest() { + + } + @Override public synchronized PebbleIoThread getDeviceIOThread() { return (PebbleIoThread) super.getDeviceIOThread(); diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml index 799b7ab5..9bc0997a 100644 --- a/app/src/main/res/layout/activity_debug.xml +++ b/app/src/main/res/layout/activity_debug.xml @@ -73,7 +73,7 @@ android:layout_column="0" android:layout_columnSpan="3" android:layout_gravity="fill_horizontal" - android:layout_row="9" + android:layout_row="10" android:text="create test notification" />