From 49dcb04b62544268ed1885fcc8a07d0279688eec Mon Sep 17 00:00:00 2001 From: vanous Date: Tue, 5 Jul 2022 18:24:13 +0200 Subject: [PATCH] FitPro: add MTU based chunking, add more device names, fix #2688 --- .../devices/fitpro/FitProConstants.java | 8 ++--- .../fitpro/FitProDeviceCoordinator.java | 11 +++--- .../devices/fitpro/FitProDeviceSupport.java | 34 +++++++++++++------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProConstants.java index 3787b811a..d93f461f3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProConstants.java @@ -37,13 +37,13 @@ public class FitProConstants { public static final byte[] DATA_TEMPLATE = { (byte) DATA_HEADER, // header - (byte) 0x00, // delimiter or first byte of argument count? - (byte) 0, // argument count, calculated + (byte) 0x00, // data len hi + (byte) 0, // data len low (byte) 0, // command 1 (byte) 0x1, // delimiter? (byte) 0, // command 2 - (byte) 0x0, // delimiter or first byte of data length? - (byte) 0, // data length calculated + (byte) 0x0, // data len hi + (byte) 0, // data len low // data payload }; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProDeviceCoordinator.java index 29bbdc73b..9f42c5ca5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/fitpro/FitProDeviceCoordinator.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.net.Uri; +import android.os.ParcelUuid; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -62,9 +63,11 @@ public class FitProDeviceCoordinator extends AbstractDeviceCoordinator { if (name != null && ( name.startsWith("M6") || - name.startsWith("M4") || - name.equals("LH716") || - name.equals("Fit1900")) + name.startsWith("M4") || + name.equals("LH716") || + name.equals("Sunset 6") || + name.equals("Watch7") || + name.equals("Fit1900")) ) { return DeviceType.FITPRO; } @@ -178,7 +181,7 @@ public class FitProDeviceCoordinator extends AbstractDeviceCoordinator { R.xml.devicesettings_donotdisturb_no_auto, R.xml.devicesettings_sleep_time, R.xml.devicesettings_wearlocation, - R.xml.devicesettings_autoheartrate, + //R.xml.devicesettings_autoheartrate, //removed, this is most likely not supported by these bands R.xml.devicesettings_vibrations_enable, R.xml.devicesettings_notifications_enable, R.xml.devicesettings_fitpro, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java index 03bef7f05..d1367d403 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java @@ -106,6 +106,7 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -114,7 +115,6 @@ import java.util.Locale; import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; @@ -126,7 +126,6 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicContr import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants; import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProSampleProvider; -import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.User; @@ -167,6 +166,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { public BluetoothGattCharacteristic readCharacteristic; public BluetoothGattCharacteristic writeCharacteristic; private static final boolean debugEnabled = false; + private int mtuSize=20; public FitProDeviceSupport() { super(LOG); @@ -276,16 +276,27 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { //0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB byte[] result = new byte[FitProConstants.DATA_TEMPLATE.length + data.length]; System.arraycopy(FitProConstants.DATA_TEMPLATE, 0, result, 0, FitProConstants.DATA_TEMPLATE.length); - result[2] = (byte) (FitProConstants.DATA_TEMPLATE.length + data.length - 3); + result[1] = (byte) (((FitProConstants.DATA_TEMPLATE.length + data.length - 3) >> 8) & 0xff); + result[2] = (byte) ((FitProConstants.DATA_TEMPLATE.length + data.length - 3) & 0xff); result[3] = command_group; result[5] = command; - result[7] = (byte) data.length; + result[6] = (byte) ((data.length >> 8 ) & 0xff); + result[7] = (byte) (data.length & 0xff); System.arraycopy(data, 0, result, 8, data.length); //debug debugPrintArray(result, "crafted packet"); return result; } + // send chucked up data + public void writeChunckedData(TransactionBuilder builder, byte[] data){ + for (int start = 0; start < data.length; start += mtuSize) { + int end = start + mtuSize; + if (end > data.length) end = data.length; + builder.write(writeCharacteristic, Arrays.copyOfRange(data, start, end)); + } + } + @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { @@ -476,7 +487,9 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { LOG.error("error sending call notification: " + e); } debugPrintArray(craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray()), "crafted call notify"); - builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray())); + + writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray())); + } else { builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, VALUE_OFF)); } @@ -631,7 +644,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { byte currentConditionCode = Weather.mapToFitProCondition(weatherSpec.currentConditionCode); TransactionBuilder builder = new TransactionBuilder("weather"); - builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit})); + writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit})); builder.queue(getQueue()); } @@ -708,11 +721,11 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { LOG.error("FitPro error sending notification: " + e); } String output = outputStream.toString(); - if (outputStream.toString().length() > 60) { - output = outputStream.toString().substring(0, 60); + if (outputStream.toString().length() > 250) { + output = outputStream.toString().substring(0, 250); } - builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_MESSAGE, output.getBytes(StandardCharsets.UTF_8))); + writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_MESSAGE, output.getBytes(StandardCharsets.UTF_8))); builder.queue(getQueue()); } @@ -990,7 +1003,8 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { } } - builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); + writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); + //builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); builder.queue(getQueue()); if (anyAlarmEnabled) { GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO);