diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java index 7de4aed26..79566f3bf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java @@ -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 mAvailableCharacteristics; private final Set 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)); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java index 41cd4b51c..9a4fba27b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java @@ -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; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index 139c8d2fd..5005a2a28 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -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; }