1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-26 02:25:50 +01:00

FitPro: add MTU based chunking, add more device names, fix #2688

This commit is contained in:
vanous 2022-07-05 18:24:13 +02:00
parent 8c1c7fbe63
commit 49dcb04b62
3 changed files with 35 additions and 18 deletions

View File

@ -37,13 +37,13 @@ public class FitProConstants {
public static final byte[] DATA_TEMPLATE = { public static final byte[] DATA_TEMPLATE = {
(byte) DATA_HEADER, // header (byte) DATA_HEADER, // header
(byte) 0x00, // delimiter or first byte of argument count? (byte) 0x00, // data len hi
(byte) 0, // argument count, calculated (byte) 0, // data len low
(byte) 0, // command 1 (byte) 0, // command 1
(byte) 0x1, // delimiter? (byte) 0x1, // delimiter?
(byte) 0, // command 2 (byte) 0, // command 2
(byte) 0x0, // delimiter or first byte of data length? (byte) 0x0, // data len hi
(byte) 0, // data length calculated (byte) 0, // data len low
// data payload // data payload
}; };

View File

@ -21,6 +21,7 @@ import android.app.Activity;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.ParcelUuid;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -62,9 +63,11 @@ public class FitProDeviceCoordinator extends AbstractDeviceCoordinator {
if (name != null && ( if (name != null && (
name.startsWith("M6") || name.startsWith("M6") ||
name.startsWith("M4") || name.startsWith("M4") ||
name.equals("LH716") || name.equals("LH716") ||
name.equals("Fit1900")) name.equals("Sunset 6") ||
name.equals("Watch7") ||
name.equals("Fit1900"))
) { ) {
return DeviceType.FITPRO; return DeviceType.FITPRO;
} }
@ -178,7 +181,7 @@ public class FitProDeviceCoordinator extends AbstractDeviceCoordinator {
R.xml.devicesettings_donotdisturb_no_auto, R.xml.devicesettings_donotdisturb_no_auto,
R.xml.devicesettings_sleep_time, R.xml.devicesettings_sleep_time,
R.xml.devicesettings_wearlocation, 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_vibrations_enable,
R.xml.devicesettings_notifications_enable, R.xml.devicesettings_notifications_enable,
R.xml.devicesettings_fitpro, R.xml.devicesettings_fitpro,

View File

@ -106,6 +106,7 @@ import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
@ -114,7 +115,6 @@ import java.util.Locale;
import java.util.UUID; import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity; import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; 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.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants; import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.FitProActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.entities.User;
@ -167,6 +166,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport {
public BluetoothGattCharacteristic readCharacteristic; public BluetoothGattCharacteristic readCharacteristic;
public BluetoothGattCharacteristic writeCharacteristic; public BluetoothGattCharacteristic writeCharacteristic;
private static final boolean debugEnabled = false; private static final boolean debugEnabled = false;
private int mtuSize=20;
public FitProDeviceSupport() { public FitProDeviceSupport() {
super(LOG); super(LOG);
@ -276,16 +276,27 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport {
//0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB //0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB
byte[] result = new byte[FitProConstants.DATA_TEMPLATE.length + data.length]; byte[] result = new byte[FitProConstants.DATA_TEMPLATE.length + data.length];
System.arraycopy(FitProConstants.DATA_TEMPLATE, 0, result, 0, FitProConstants.DATA_TEMPLATE.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[3] = command_group;
result[5] = command; 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); System.arraycopy(data, 0, result, 8, data.length);
//debug //debug
debugPrintArray(result, "crafted packet"); debugPrintArray(result, "crafted packet");
return result; 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 @Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, public boolean onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) { BluetoothGattCharacteristic characteristic) {
@ -476,7 +487,9 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport {
LOG.error("error sending call notification: " + e); LOG.error("error sending call notification: " + e);
} }
debugPrintArray(craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray()), "crafted call notify"); 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 { } else {
builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, VALUE_OFF)); 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); byte currentConditionCode = Weather.mapToFitProCondition(weatherSpec.currentConditionCode);
TransactionBuilder builder = new TransactionBuilder("weather"); 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()); builder.queue(getQueue());
} }
@ -708,11 +721,11 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport {
LOG.error("FitPro error sending notification: " + e); LOG.error("FitPro error sending notification: " + e);
} }
String output = outputStream.toString(); String output = outputStream.toString();
if (outputStream.toString().length() > 60) { if (outputStream.toString().length() > 250) {
output = outputStream.toString().substring(0, 60); 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()); 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()); builder.queue(getQueue());
if (anyAlarmEnabled) { if (anyAlarmEnabled) {
GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO); GB.toast(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT, GB.INFO);