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

Fix first connect on the Casio GBX100/GBD-200 series

This commit is contained in:
Andreas Böhler 2023-10-09 12:02:37 +02:00 committed by José Rebelo
parent a3f3bb212a
commit 3dd2869283
2 changed files with 28 additions and 13 deletions

View File

@ -90,7 +90,6 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_
public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements SharedPreferences.OnSharedPreferenceChangeListener { public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(CasioGBX100DeviceSupport.class); private static final Logger LOG = LoggerFactory.getLogger(CasioGBX100DeviceSupport.class);
private boolean mGetConfigurationPending = false; private boolean mGetConfigurationPending = false;
private boolean mRingNotificationPending = false; private boolean mRingNotificationPending = false;
private final ArrayList<Integer> mSyncedNotificationIDs = new ArrayList<>(); private final ArrayList<Integer> mSyncedNotificationIDs = new ArrayList<>();
@ -99,6 +98,8 @@ public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements Shared
private final Handler mFindPhoneHandler = new Handler(); private final Handler mFindPhoneHandler = new Handler();
private final Handler mFakeRingDurationHandler = new Handler(); private final Handler mFakeRingDurationHandler = new Handler();
private final Handler mAutoRemoveMessageHandler = new Handler(); private final Handler mAutoRemoveMessageHandler = new Handler();
private final Handler mReconnectHandler = new Handler();
private boolean mNeedsGetConfiguration = false;
public CasioGBX100DeviceSupport() { public CasioGBX100DeviceSupport() {
super(LOG); super(LOG);
@ -113,7 +114,7 @@ public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements Shared
protected TransactionBuilder initializeDevice(TransactionBuilder builder) { protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
try { try {
new InitOperation(this, builder, mFirstConnect).perform(); new InitOperation(this, builder, mFirstConnect, mNeedsGetConfiguration).perform();
} catch (IOException e) { } catch (IOException e) {
GB.toast(getContext(), "Initializing Casio watch failed", Toast.LENGTH_SHORT, GB.ERROR, e); GB.toast(getContext(), "Initializing Casio watch failed", Toast.LENGTH_SHORT, GB.ERROR, e);
} }
@ -538,6 +539,7 @@ public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements Shared
if(config == null) { if(config == null) {
try { try {
mGetConfigurationPending = true; mGetConfigurationPending = true;
mNeedsGetConfiguration = false;
new GetConfigurationOperation(this, true).perform(); new GetConfigurationOperation(this, true).perform();
} catch (IOException e) { } catch (IOException e) {
mGetConfigurationPending = false; mGetConfigurationPending = false;
@ -621,4 +623,15 @@ public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements Shared
LOG.info("Error sending configuration change to watch"); LOG.info("Error sending configuration change to watch");
} }
} }
public void reconnectDelayed() {
setAutoReconnect(true);
mNeedsGetConfiguration = true;
mReconnectHandler.postDelayed(new Runnable() {
@Override
public void run() {
connect();
}
}, CasioConstants.CASIO_FAKE_RING_SLEEP_DURATION);
}
} }

View File

@ -18,6 +18,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.casio.gbx100;
import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattCharacteristic;
import android.os.Handler;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -42,13 +43,15 @@ public class InitOperation extends AbstractBTLEOperation<CasioGBX100DeviceSuppor
private final TransactionBuilder builder; private final TransactionBuilder builder;
private final CasioGBX100DeviceSupport support; private final CasioGBX100DeviceSupport support;
private final boolean mFirstConnect; private final boolean mFirstConnect;
private final boolean mNeedsGetConfiguration;
private boolean mWriteAllFeaturesInitPending = false; private boolean mWriteAllFeaturesInitPending = false;
public InitOperation(CasioGBX100DeviceSupport support, TransactionBuilder builder, boolean firstConnect) { public InitOperation(CasioGBX100DeviceSupport support, TransactionBuilder builder, boolean firstConnect, boolean needsGetConfiguration) {
super(support); super(support);
this.builder = builder; this.builder = builder;
this.support = support; this.support = support;
this.mFirstConnect = firstConnect; this.mFirstConnect = firstConnect;
this.mNeedsGetConfiguration = needsGetConfiguration;
LOG.info("mFirstConnect: " + mFirstConnect); LOG.info("mFirstConnect: " + mFirstConnect);
builder.setCallback(this); builder.setCallback(this);
} }
@ -348,22 +351,21 @@ public class InitOperation extends AbstractBTLEOperation<CasioGBX100DeviceSuppor
LOG.error("Error setting device to initialized: " + e.getMessage()); LOG.error("Error setting device to initialized: " + e.getMessage());
} }
} else if(data[1] == 0x01) { } else if(data[1] == 0x01) {
// The writeAllFeaturesInit request triggers encryption (again). However, the transaction support.setInitialized();
// never completes. Instead, the watch reports with 0x3d and we abort the current
// transaction.
// This write is only required for the first connect, for later reconnections,
// it's not required and the watch does not respond with 0x3d. Thus, we set
// it directly to initialized.
if(mFirstConnect)
writeAllFeaturesInit();
else
support.setInitialized();
} }
} else if(data[0] == 0x3d) { } else if(data[0] == 0x3d) {
LOG.info("Init operation done."); LOG.info("Init operation done.");
// Finally, we set the state to initialized here! // Finally, we set the state to initialized here!
// If it's the first connection attempt, disconnect the watch and
// reconnect delayed. This is required on Android 13 since it's no longer
// possible to cancel a dangling write request.
// Upon first reconnection, a "getConfiguration" request is required. On further
// reconnections, we just sync the profile.
support.setInitialized(); support.setInitialized();
if(mFirstConnect) { if(mFirstConnect) {
support.disconnect();
support.reconnectDelayed();
} else if(mNeedsGetConfiguration) {
support.onReadConfiguration(null); support.onReadConfiguration(null);
} else { } else {
// on first connect, this is called by onReadConfiguration // on first connect, this is called by onReadConfiguration