From 1087a532160037c4decf4ac247ee9dd3856a8818 Mon Sep 17 00:00:00 2001 From: Sophanimus Date: Wed, 3 Apr 2019 23:59:14 +0200 Subject: [PATCH] some functions do now work Signed-off-by: Sophanimus --- .../devices/bfh16/BFH16Constants.java | 101 ++++++++++++----- .../devices/bfh16/BFH16DeviceCoordinator.java | 6 +- .../devices/bfh16/BFH16DeviceSupport.java | 106 +++++++++++++++--- 3 files changed, 171 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16Constants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16Constants.java index ffa240279..dc37e5c02 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16Constants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16Constants.java @@ -6,49 +6,98 @@ import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDevi public final class BFH16Constants { - //public static final UUID BFH16_IDENTIFICATION_SERVICE1 = UUID.fromString(String.format(BASE_UUID, "FEF5") ); + //Known Services + public static final UUID BFH16_GENERIC_ACCESS_SERVICE = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_GENERIC_ARTTRIBUTE_SERVICE = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_IDENTIFICATION_SERVICE1 = UUID.fromString("0000fef5-0000-1000-8000-00805f9b34fb"); - //public static final UUID BFH16_IDENTIFICATION_SERVICE2 = UUID.fromString(String.format(BASE_UUID, "FEE7") ); public static final UUID BFH16_IDENTIFICATION_SERVICE2 = UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"); - public static final UUID BFH16_MAIN_SERVICE = UUID.fromString(String.format(BASE_UUID, "33F4") ); + + public static final UUID BFH16_SERVICE1 = UUID.fromString("000056ff-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_SERVICE1_WRITE = UUID.fromString("000033f3-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_SERVICE1_NOTIFY = UUID.fromString("000033f4-0000-1000-8000-00805f9b34fb"); + + public static final UUID BFH16_SERVICE2 = UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_SERVICE2_WRITE = UUID.fromString("0000fec7-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_SERVICE2_INDICATE= UUID.fromString("0000fec8-0000-1000-8000-00805f9b34fb"); + public static final UUID BFH16_SERVICE2_READ = UUID.fromString("0000fec9-0000-1000-8000-00805f9b34fb"); - //Known Services - public static final UUID BFH16_SERVICE_1 = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); - public static final UUID BFH16_SERVICE_2 = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); //Attribute - public static final UUID BFH16_SERVICE_3 = UUID.fromString("000056ff-0000-1000-8000-00805f9b34fb"); //Service - public static final UUID BFH16_SERVICE_4 = UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"); //Service - - - - //I Think i discovered that this device (BFH16) uses communication similar to JYOU - //Therefore i copied the following vars: - public static final UUID UUID_CHARACTERISTIC_CONTROL = UUID.fromString("000033f3-0000-1000-8000-00805f9b34fb"); - public static final UUID UUID_CHARACTERISTIC_MEASURE = UUID.fromString("000033f4-0000-1000-8000-00805f9b34fb"); - public static final UUID UUID_SERVICE_JYOU = UUID.fromString("000056ff-0000-1000-8000-00805f9b34fb"); + //Verified command bytes + public static final byte CMD_SET_ALARM_1 = (byte)0x09; + public static final byte CMD_SET_ALARM_2 = (byte)0x22; + public static final byte CMD_SET_ALARM_3 = (byte)0x23; public static final byte CMD_SET_DATE_AND_TIME = 0x08; + + + public static final byte CMD_MEASURE_HEART = (byte)0x0D; //param1: 0, param2: 0 -> STOP | 1 -> START + public static final byte CMD_VIBRATE = (byte)0x07; //param1: 0, param2: 1 + + + public static final byte CMD_SWITCH_PHOTO_MODE = (byte)0x25; //param1: 0, param2: 0 -> OFF | 1 -> ON + + public static final byte CMD_SWITCH_12HOUR_MODE = (byte)0x3E; //byte1: 1 -> 12HourMode | 0 -> 24HourMode + public static final byte CMD_SWITCH_METRIC_IMPERIAL = (byte)0x3A; //param1: 0, param2: 0 -> METRIC | 1 -> IMPERIAL //Also requests walked steps + + + //Verified receive bytes + public static final byte RECEIVE_BATTERY_LEVEL = (byte)0xF7; + public static final byte RECEIVE_STEPS_DATA = (byte)0xF9; + public static final byte RECEIVE_HEART_DATA = (byte)0xE8; + public static final byte RECEIVE_PHOTO_TRIGGER = (byte)0xF3; + + + + //Most probably correct command bytes + public static final byte CMD_SET_STEPLENGTH = (byte)0x3F; //param1: 0, param2: STEPLENGTH + + + //Probably correct command bytes + public static final byte CMD_SET_INACTIVITY_WARNING_TIME = (byte)0x24; //param1: 0, param2: time + + public static final byte CMD_SET_HEART_TARGET = (byte)0x01; //param1: 0, param2: HEART TARGET + public static final byte CMD_SET_STEP_TARGET = (byte)0x03; //param1: 0, param2: STEP TARGET + + public static final byte CMD_FIND_DEVICE = (byte)0x36; //param1: 0, param2: 1 + public static final byte CMD_SET_DISCONNECT_REMIND = (byte)0x37; //param1: 0, param2: 0 -> ??? | 1 -> ??? + public static final byte CMD_SET_AUTODETECT_HEART = (byte)0x38; //param1: 0, param2: 0 -> ??? | 1 -> ??? + + public static final byte CMD_READ_HISTORY_SLEEP_COUNT = (byte)0x32; //param1: 0, param2: 0 + + public static final byte CMD_SET_NOON_TIME = (byte)0x26; //param1: start time, param2: end time + public static final byte CMD_SET_SLEEP_TIME = (byte)0x27; //param1: start time, param2: end time + + + //Could be correct command bytes + //Send PhoneName 0x17 and 0x18 + //Send PhoneNumber 0x19 and 0x20 + //Weather 0x3B + //Power Management 0x39 + //User Id 0x35 + // + + + + //______________________________________________________________________________________________ + //It may be that BFH16 uses the same communication protocol as JYOU + //copied the following JYOU vars: + public static final byte CMD_SET_HEARTRATE_AUTO = 0x38; public static final byte CMD_SET_HEARTRATE_WARNING_VALUE = 0x01; public static final byte CMD_SET_TARGET_STEPS = 0x03; - public static final byte CMD_SET_ALARM_1 = 0x09; - public static final byte CMD_SET_ALARM_2 = 0x22; - public static final byte CMD_SET_ALARM_3 = 0x23; - public static final byte CMD_GET_STEP_COUNT = 0x1D; + //public static final byte CMD_GET_STEP_COUNT = 0x1D; public static final byte CMD_GET_SLEEP_TIME = 0x32; - public static final byte CMD_SET_NOON_TIME = 0x26; - public static final byte CMD_SET_SLEEP_TIME = 0x27; public static final byte CMD_SET_DND_SETTINGS = 0x39; - public static final byte CMD_SET_INACTIVITY_WARNING_TIME = 0x24; + public static final byte CMD_ACTION_HEARTRATE_SWITCH = 0x0D; public static final byte CMD_ACTION_SHOW_NOTIFICATION = 0x2C; public static final byte CMD_ACTION_REBOOT_DEVICE = 0x0E; - public static final byte RECEIVE_BATTERY_LEVEL = (byte)0xF7; + public static final byte RECEIVE_DEVICE_INFO = (byte)0xF6; - public static final byte RECEIVE_STEPS_DATA = (byte)0xF9; - public static final byte RECEIVE_HEARTRATE = (byte)0xE8; + public static final byte ICON_CALL = 0; public static final byte ICON_SMS = 1; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16DeviceCoordinator.java index 474344728..2a26ab887 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/bfh16/BFH16DeviceCoordinator.java @@ -42,11 +42,11 @@ public class BFH16DeviceCoordinator extends AbstractDeviceCoordinator @Override public Collection createBLEScanFilters() { - ParcelUuid bfhService = new ParcelUuid(BFH16Constants.BFH16_IDENTIFICATION_SERVICE1); + ParcelUuid bfhService1 = new ParcelUuid(BFH16Constants.BFH16_IDENTIFICATION_SERVICE1); ParcelUuid bfhService2 = new ParcelUuid(BFH16Constants.BFH16_IDENTIFICATION_SERVICE2); ScanFilter filter = new ScanFilter.Builder() - .setServiceUuid(bfhService) + .setServiceUuid(bfhService1) .setServiceUuid(bfhService2) .build(); @@ -134,7 +134,7 @@ public class BFH16DeviceCoordinator extends AbstractDeviceCoordinator @Override public boolean supportsFindDevice() { - return false; + return true; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/bfh16/BFH16DeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/bfh16/BFH16DeviceSupport.java index 08528f761..82921f810 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/bfh16/BFH16DeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/bfh16/BFH16DeviceSupport.java @@ -44,18 +44,19 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { public BFH16DeviceSupport() { super(LOG); - addSupportedService(BFH16Constants.UUID_SERVICE_JYOU); + addSupportedService(BFH16Constants.BFH16_SERVICE1); + addSupportedService(BFH16Constants.BFH16_SERVICE2); } @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { - LOG.info("Initializing"); + LOG.info("Initializing BFH16"); gbDevice.setState(GBDevice.State.INITIALIZING); gbDevice.sendDeviceUpdateIntent(getContext()); - measureCharacteristic = getCharacteristic(BFH16Constants.UUID_CHARACTERISTIC_MEASURE); - ctrlCharacteristic = getCharacteristic(BFH16Constants.UUID_CHARACTERISTIC_CONTROL); + measureCharacteristic = getCharacteristic(BFH16Constants.BFH16_SERVICE1_NOTIFY); + ctrlCharacteristic = getCharacteristic(BFH16Constants.BFH16_SERVICE1_WRITE); builder.setGattCallback(this); builder.notify(measureCharacteristic, true); @@ -65,7 +66,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { gbDevice.setState(GBDevice.State.INITIALIZED); gbDevice.sendDeviceUpdateIntent(getContext()); - LOG.info("Initialization Done"); + LOG.info("Initialization BFH16 Done"); return builder; } @@ -98,10 +99,13 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { int steps = ByteBuffer.wrap(data, 5, 4).getInt(); LOG.info("Number of walked steps: " + steps); return true; - case BFH16Constants.RECEIVE_HEARTRATE: - LOG.info("Current heart rate: " + data[1]); - LOG.info("Current blood presure: " + data[3] + "/" + data[2]); - LOG.info("Current satiation: " + data[4]); + case BFH16Constants.RECEIVE_HEART_DATA: + LOG.info("Current heart rate: " + data[1]); + LOG.info("Current blood pressure: " + data[2] + "/" + data[3]); + LOG.info("Current satiation: " + data[4]); + return true; + case BFH16Constants.RECEIVE_PHOTO_TRIGGER: + LOG.info("Received photo trigger: " + data[8]); return true; default: LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + String.format("0x%1x ...", data[0])); @@ -109,6 +113,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } } + //Fully working private void syncDateAndTime(TransactionBuilder builder) { Calendar cal = Calendar.getInstance(); String strYear = String.valueOf(cal.get(Calendar.YEAR)); @@ -128,6 +133,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { )); } + //TODO: not checked yet private void syncSettings(TransactionBuilder builder) { syncDateAndTime(builder); @@ -139,7 +145,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { BFH16Constants.CMD_SET_TARGET_STEPS, 0, 10000 )); builder.write(ctrlCharacteristic, commandWithChecksum( - BFH16Constants.CMD_GET_STEP_COUNT, 0, 0 + BFH16Constants.CMD_SWITCH_METRIC_IMPERIAL, 0, 0 )); builder.write(ctrlCharacteristic, commandWithChecksum( BFH16Constants.CMD_GET_SLEEP_TIME, 0, 0 @@ -169,6 +175,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { )); } + //TODO: not checked yet + needs rework private void showNotification(byte icon, String title, String message) { try { TransactionBuilder builder = performInitialized("ShowNotification"); @@ -212,6 +219,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { return true; } + //TODO: not checked yet + needs rework @Override public void onNotification(NotificationSpec notificationSpec) { String notificationTitle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title); @@ -242,6 +250,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } + //fully working @Override public void onSetAlarms(ArrayList alarms) { try { @@ -288,6 +297,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } } + //TODO: not checked yet @Override public void onSetCallState(CallSpec callSpec) { switch (callSpec.command) { @@ -370,7 +380,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { try { TransactionBuilder builder = performInitialized("HeartRateTest"); builder.write(ctrlCharacteristic, commandWithChecksum( - BFH16Constants.CMD_ACTION_HEARTRATE_SWITCH, 0, 1 + BFH16Constants.CMD_MEASURE_HEART, 0, 1 )); builder.queue(getQueue()); } catch(Exception e) { @@ -384,7 +394,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { try { TransactionBuilder builder = performInitialized("RealTimeHeartMeasurement"); builder.write(ctrlCharacteristic, commandWithChecksum( - BFH16Constants.CMD_SET_HEARTRATE_AUTO, 0, enable ? 1 : 0 + BFH16Constants.CMD_MEASURE_HEART, 0, enable ? 1 : 0 )); builder.queue(getQueue()); } catch(Exception e) { @@ -392,6 +402,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } } + //working @Override public void onFindDevice(boolean start) { if (start) { @@ -402,7 +413,15 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onSetConstantVibration(int integer) { - + try { + TransactionBuilder builder = performInitialized("Vibrate"); + builder.write(ctrlCharacteristic, commandWithChecksum( + BFH16Constants.CMD_VIBRATE, 0, 1 + )); + builder.queue(getQueue()); + } catch(Exception e) { + LOG.warn(e.getMessage()); + } } @Override @@ -443,6 +462,34 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onTestNewFunction() { + try { + TransactionBuilder builder = performInitialized("TestNewFunction"); + + //byte cmd = BFH16Constants.CMD_GET_STEP_COUNT; + + //Wakeup? Photo? + //builder.write(ctrlCharacteristic, commandWithChecksum((byte) 0x25, 0, 0)); + //builder.write(ctrlCharacteristic, commandWithChecksum((byte) 0x25, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00)); + + builder.write(ctrlCharacteristic, commandWithChecksum( (byte)1, 0, 200)); + +// builder.write(ctrlCharacteristic, commandWithChecksum((byte) 0xF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00)); + + +// builder.write(ctrlCharacteristic, commandWithChecksum( +// (byte) 39, (byte) 0, (byte) 0, +// (byte) 189, (byte) 216, (byte) 0, +// (byte) 0, (byte) 196, (byte) 224)); + + + builder.queue(getQueue()); + + GB.toast(getContext(), "TestNewFunction executed!", Toast.LENGTH_LONG, GB.INFO); + + } catch(IOException e) { + LOG.warn(e.getMessage()); + } + } @Override @@ -450,6 +497,38 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } + /** + * Checksum is calculated by the sum of bytes 0 to 8 and send as byte 9 + */ + private byte[] commandWithChecksum(byte s0, byte s1, byte s2, byte s3, byte s4, byte s5, byte s6, byte s7, byte s8) + { + ByteBuffer buf = ByteBuffer.allocate(10); + buf.put(s0); + buf.put(s1); + buf.put(s2); + buf.put(s3); + buf.put(s4); + buf.put(s5); + buf.put(s6); + buf.put(s7); + buf.put(s8); + + byte[] bytesToWrite = buf.array(); + + byte checksum = 0; + for (byte b : bytesToWrite) { + checksum += b; + } + + //checksum = (byte) ((byte) checksum & (byte) 0xFF); //TODO EXPERIMENTAL + + LOG.debug("Checksum = " + checksum); + + bytesToWrite[9] = checksum; + + return bytesToWrite; + } + private byte[] commandWithChecksum(byte cmd, int argSlot1, int argSlot2) { ByteBuffer buf = ByteBuffer.allocate(10); @@ -493,4 +572,5 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport { } return null; } + }