mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 19:49:30 +01:00
Improve BLE gatt handling
- close() the gatt instance when explicitly disconnecting - create a new gatt instance when explicitly connecting Unfortunately I still appear to get spontaneous disconnects after some notifications.
This commit is contained in:
parent
f54927624b
commit
880dc7b3a4
@ -49,6 +49,7 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
|
|||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (mQueue != null) {
|
if (mQueue != null) {
|
||||||
mQueue.dispose();
|
mQueue.dispose();
|
||||||
|
mQueue = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBDevice.State;
|
|||||||
public final class BtLEQueue {
|
public final class BtLEQueue {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BtLEQueue.class);
|
private static final Logger LOG = LoggerFactory.getLogger(BtLEQueue.class);
|
||||||
|
|
||||||
|
private Object mGattMonitor = new Object();
|
||||||
private GBDevice mGbDevice;
|
private GBDevice mGbDevice;
|
||||||
private BluetoothAdapter mBluetoothAdapter;
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
private BluetoothGatt mBluetoothGatt;
|
private BluetoothGatt mBluetoothGatt;
|
||||||
@ -127,10 +128,21 @@ public final class BtLEQueue {
|
|||||||
LOG.warn("Ingoring connect() because already connected.");
|
LOG.warn("Ingoring connect() because already connected.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
synchronized (mGattMonitor) {
|
||||||
|
if (mBluetoothGatt != null) {
|
||||||
|
// Tribal knowledge says you're better off not reusing existing BlueoothGatt connections,
|
||||||
|
// so create a new one.
|
||||||
|
LOG.info("connect() requested -- disconnecting previous connection: " + mGbDevice.getName());
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
LOG.info("Attempting to connect to " + mGbDevice.getName());
|
LOG.info("Attempting to connect to " + mGbDevice.getName());
|
||||||
BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(mGbDevice.getAddress());
|
BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(mGbDevice.getAddress());
|
||||||
mBluetoothGatt = remoteDevice.connectGatt(mContext, false, internalGattCallback);
|
boolean result = false;
|
||||||
boolean result = mBluetoothGatt.connect();
|
synchronized (mGattMonitor) {
|
||||||
|
mBluetoothGatt = remoteDevice.connectGatt(mContext, false, internalGattCallback);
|
||||||
|
result = mBluetoothGatt.connect();
|
||||||
|
}
|
||||||
setDeviceConnectionState(result ? State.CONNECTING : State.NOT_CONNECTED);
|
setDeviceConnectionState(result ? State.CONNECTING : State.NOT_CONNECTED);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -144,11 +156,13 @@ public final class BtLEQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
if (mBluetoothGatt != null) {
|
synchronized (mGattMonitor) {
|
||||||
LOG.info("Disconnecting BtLEQueue from GATT device");
|
if (mBluetoothGatt != null) {
|
||||||
mBluetoothGatt.disconnect();
|
LOG.info("Disconnecting BtLEQueue from GATT device");
|
||||||
mBluetoothGatt.close();
|
mBluetoothGatt.disconnect();
|
||||||
mBluetoothGatt = null;
|
mBluetoothGatt.close();
|
||||||
|
mBluetoothGatt = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +172,10 @@ public final class BtLEQueue {
|
|||||||
mWaitForActionResultLatch.countDown();
|
mWaitForActionResultLatch.countDown();
|
||||||
}
|
}
|
||||||
setDeviceConnectionState(State.NOT_CONNECTED);
|
setDeviceConnectionState(State.NOT_CONNECTED);
|
||||||
|
// either we've been disconnected because the device is out of range
|
||||||
|
// or because of an explicit @{link #disconnect())
|
||||||
|
// To support automatic reconnection, we keep the mBluetoothGatt instance
|
||||||
|
// alive (we do not close() it).
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
@ -206,11 +224,23 @@ public final class BtLEQueue {
|
|||||||
return mBluetoothGatt.getServices();
|
return mBluetoothGatt.getServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkCorrectGattInstance(BluetoothGatt gatt, String where) {
|
||||||
|
if (gatt != mBluetoothGatt) {
|
||||||
|
LOG.info("Ignoring event from wrong BluetoothGatt instance: " + where);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Implements callback methods for GATT events that the app cares about. For example,
|
// Implements callback methods for GATT events that the app cares about. For example,
|
||||||
// connection change and services discovered.
|
// connection change and services discovered.
|
||||||
private final BluetoothGattCallback internalGattCallback = new BluetoothGattCallback() {
|
private final BluetoothGattCallback internalGattCallback = new BluetoothGattCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "connection state event")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
case BluetoothProfile.STATE_CONNECTED:
|
case BluetoothProfile.STATE_CONNECTED:
|
||||||
LOG.info("Connected to GATT server.");
|
LOG.info("Connected to GATT server.");
|
||||||
@ -232,6 +262,10 @@ public final class BtLEQueue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "services discovered")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
if (mExternalGattCallback != null) {
|
if (mExternalGattCallback != null) {
|
||||||
// only propagate the successful event
|
// only propagate the successful event
|
||||||
@ -244,10 +278,13 @@ public final class BtLEQueue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "characteristic write")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
LOG.info("Writing characteristic " + characteristic.getUuid() + " succeeded.");
|
LOG.debug("Writing characteristic " + characteristic.getUuid() + " succeeded.");
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Writing characteristic " + characteristic.getUuid() + " failed: " + status);
|
LOG.debug("Writing characteristic " + characteristic.getUuid() + " failed: " + status);
|
||||||
}
|
}
|
||||||
if (mExternalGattCallback != null) {
|
if (mExternalGattCallback != null) {
|
||||||
mExternalGattCallback.onCharacteristicWrite(gatt, characteristic, status);
|
mExternalGattCallback.onCharacteristicWrite(gatt, characteristic, status);
|
||||||
@ -259,6 +296,9 @@ public final class BtLEQueue {
|
|||||||
public void onCharacteristicRead(BluetoothGatt gatt,
|
public void onCharacteristicRead(BluetoothGatt gatt,
|
||||||
BluetoothGattCharacteristic characteristic,
|
BluetoothGattCharacteristic characteristic,
|
||||||
int status) {
|
int status) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "characteristic read")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (status != BluetoothGatt.GATT_SUCCESS) {
|
if (status != BluetoothGatt.GATT_SUCCESS) {
|
||||||
LOG.error("Reading characteristic " + characteristic.getUuid() + " failed: " + status);
|
LOG.error("Reading characteristic " + characteristic.getUuid() + " failed: " + status);
|
||||||
}
|
}
|
||||||
@ -271,6 +311,13 @@ public final class BtLEQueue {
|
|||||||
@Override
|
@Override
|
||||||
public void onCharacteristicChanged(BluetoothGatt gatt,
|
public void onCharacteristicChanged(BluetoothGatt gatt,
|
||||||
BluetoothGattCharacteristic characteristic) {
|
BluetoothGattCharacteristic characteristic) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "characteristic changed")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gatt != mBluetoothGatt) {
|
||||||
|
LOG.info("Ignoring characteristic change event from wrong BluetoothGatt instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mExternalGattCallback != null) {
|
if (mExternalGattCallback != null) {
|
||||||
mExternalGattCallback.onCharacteristicChanged(gatt, characteristic);
|
mExternalGattCallback.onCharacteristicChanged(gatt, characteristic);
|
||||||
}
|
}
|
||||||
@ -278,6 +325,13 @@ public final class BtLEQueue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
|
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
|
||||||
|
if (!checkCorrectGattInstance(gatt, "remote rssi")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gatt != mBluetoothGatt) {
|
||||||
|
LOG.info("Ignoring remote rssi event from wrong BluetoothGatt instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mExternalGattCallback != null) {
|
if (mExternalGattCallback != null) {
|
||||||
mExternalGattCallback.onReadRemoteRssi(gatt, rssi, status);
|
mExternalGattCallback.onReadRemoteRssi(gatt, rssi, status);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user