1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-19 19:40:22 +02:00

Huami/Zepp OS: Improve reconnection

- Remove notification on unneeded characteristics for Zepp OS devices
- Reset MTU before initializing device, since the support class is
  reused when reconnecting, and keeping the previous high MTU before
  renegotiating again can make the initialization fail sometimes
  (band will never reply)
- If any of the chunked characteristics is null during initialization,
  mark the device as waiting for reconnect, which will make it retry the
  connection later with a backoff delay.
This commit is contained in:
José Rebelo 2023-07-22 20:31:26 +01:00
parent aa87c5abeb
commit 247a954920
3 changed files with 42 additions and 12 deletions

View File

@ -23,9 +23,9 @@ import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.location.Location;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
@ -38,8 +38,6 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.CheckInitializedAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
@ -56,6 +54,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBlePro
* @see BtLEQueue
*/
public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport implements GattCallback, GattServerCallback {
private static final Logger LOG = LoggerFactory.getLogger(AbstractBTLEDeviceSupport.class);
private BtLEQueue mQueue;
private Map<UUID, BluetoothGattCharacteristic> mAvailableCharacteristics;
private final Set<UUID> mSupportedServices = new HashSet<>(4);
@ -136,11 +136,13 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
*/
public TransactionBuilder performInitialized(String taskName) throws IOException {
if (!isConnected()) {
LOG.debug("Connecting to device for {}", taskName);
if (!connect()) {
throw new IOException("1: Unable to connect to device: " + getDevice());
}
}
if (!isInitialized()) {
LOG.debug("Initializing device for {}", taskName);
// first, add a transaction that performs device initialization
TransactionBuilder builder = createTransactionBuilder("Initialize device");
builder.add(new CheckInitializedAction(gbDevice));

View File

@ -720,11 +720,16 @@ public abstract class Huami2021Support extends HuamiSupport implements ZeppOsFil
return this;
}
@Override
public HuamiSupport enableNotifications(final TransactionBuilder builder, final boolean enable) {
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ), enable);
return this;
}
@Override
public Huami2021Support enableFurtherNotifications(final TransactionBuilder builder,
final boolean enable) {
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ), enable);
// Nothing to do here, they are already enabled from enableNotifications
return this;
}

View File

@ -333,7 +333,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
protected boolean isMusicAppStarted = false;
protected MediaManager mediaManager;
private boolean heartRateNotifyEnabled;
private int mMTU = 23;
private static final int MIN_MTU = 23;
private int mMTU = MIN_MTU;
// Keep track of the previous MTU before reconnection, so that we can request it after reconnection
private int previousMtu = -1;
protected int mActivitySampleSize = 4;
protected Huami2021ChunkedEncoder huami2021ChunkedEncoder;
@ -371,6 +374,12 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
@Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
if (getMTU() != MIN_MTU) {
// Reset the MTU before re-initializing the device, otherwise initialization will sometimes fail
previousMtu = getMTU();
setMtu(MIN_MTU);
}
try {
byte authFlags = getAuthFlags();
byte cryptFlags = getCryptFlags();
@ -385,8 +394,13 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
if (characteristicChunked2021Write != null && huami2021ChunkedEncoder == null) {
huami2021ChunkedEncoder = new Huami2021ChunkedEncoder(characteristicChunked2021Write, force2021Protocol(), mMTU);
}
if (characteristicChunked2021Write != null && force2021Protocol()) {
new InitOperation2021(authenticate, authFlags, cryptFlags, this, builder, huami2021ChunkedEncoder, huami2021ChunkedDecoder).perform();
if (force2021Protocol()) {
if (characteristicChunked2021Write != null && characteristicChunked2021Read != null) {
new InitOperation2021(authenticate, authFlags, cryptFlags, this, builder, huami2021ChunkedEncoder, huami2021ChunkedDecoder).perform();
} else {
LOG.warn("Chunked 2021 characteristics are null, will attempt to reconnect");
builder.add(new SetDeviceStateAction(getDevice(), State.WAITING_FOR_RECONNECT, getContext()));
}
} else {
new InitOperation(authenticate, authFlags, cryptFlags, this, builder).perform();
}
@ -510,7 +524,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
// TODO: tear down the notifications on quit
public HuamiSupport enableNotifications(TransactionBuilder builder, boolean enable) {
builder.notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_NOTIFICATION), enable);
builder.notify(getCharacteristic(GattService.UUID_SERVICE_CURRENT_TIME), enable);
// Notify CHARACTERISTIC9 to receive random auth code
builder.notify(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_AUTH), enable);
if (characteristicChunked2021Read != null) {
@ -4116,6 +4129,13 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
public void phase2Initialize(TransactionBuilder builder) {
LOG.info("phase2Initialize...");
if (previousMtu > MIN_MTU) {
// We're reconnecting - request the previously set MTU
builder.requestMtu(previousMtu);
previousMtu = -1;
}
requestBatteryInfo(builder);
}
@ -4171,13 +4191,12 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
}
protected void setMtu(final int mtu) {
final Prefs prefs = getDevicePrefs();
if (!prefs.getBoolean(PREF_ALLOW_HIGH_MTU, true)) {
if (mtu > MIN_MTU && !allowHighMtu()) {
LOG.warn("High MTU is not allowed, ignoring");
return;
}
if (mtu < 23) {
if (mtu < MIN_MTU) {
LOG.error("Device announced unreasonable low MTU of {}, ignoring", mtu);
return;
}
@ -4188,6 +4207,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
}
}
protected boolean allowHighMtu() {
return getDevicePrefs().getBoolean(PREF_ALLOW_HIGH_MTU, true);
}
public int getActivitySampleSize() {
return mActivitySampleSize;
}