mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-18 14:31:23 +02:00
do Bluetooth LE scan before connecting to improve connection performance
This commit is contained in:
@@ -8,8 +8,8 @@ android {
|
|||||||
testApplicationId "com.health.openscale.test"
|
testApplicationId "com.health.openscale.test"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 38
|
versionCode 39
|
||||||
versionName "1.9.1"
|
versionName "1.9.2"
|
||||||
|
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions { arguments = ["room.schemaLocation":"$projectDir/schemas".toString()] }
|
annotationProcessorOptions { arguments = ["room.schemaLocation":"$projectDir/schemas".toString()] }
|
||||||
|
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.health.openscale.core.bluetooth;
|
package com.health.openscale.core.bluetooth;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.bluetooth.BluetoothGattService;
|
import android.bluetooth.BluetoothGattService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
import com.health.openscale.core.OpenScale;
|
import com.health.openscale.core.OpenScale;
|
||||||
@@ -28,6 +30,7 @@ import com.polidea.rxandroidble2.RxBleConnection;
|
|||||||
import com.polidea.rxandroidble2.RxBleDevice;
|
import com.polidea.rxandroidble2.RxBleDevice;
|
||||||
import com.polidea.rxandroidble2.RxBleDeviceServices;
|
import com.polidea.rxandroidble2.RxBleDeviceServices;
|
||||||
import com.polidea.rxandroidble2.exceptions.BleException;
|
import com.polidea.rxandroidble2.exceptions.BleException;
|
||||||
|
import com.polidea.rxandroidble2.scan.ScanSettings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
@@ -36,6 +39,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
@@ -74,6 +78,7 @@ public abstract class BluetoothCommunication {
|
|||||||
private RxBleDevice bleDevice;
|
private RxBleDevice bleDevice;
|
||||||
private Observable<RxBleConnection> connectionObservable;
|
private Observable<RxBleConnection> connectionObservable;
|
||||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||||
|
private Disposable scanSubscription;
|
||||||
private PublishSubject<Boolean> disconnectTriggerSubject = PublishSubject.create();
|
private PublishSubject<Boolean> disconnectTriggerSubject = PublishSubject.create();
|
||||||
|
|
||||||
private Handler callbackBtHandler;
|
private Handler callbackBtHandler;
|
||||||
@@ -92,6 +97,7 @@ public abstract class BluetoothCommunication {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
this.bleClient = OpenScale.getInstance().getBleClient();
|
this.bleClient = OpenScale.getInstance().getBleClient();
|
||||||
this.rxBleDeviceServices = null;
|
this.rxBleDeviceServices = null;
|
||||||
|
this.scanSubscription = null;
|
||||||
this.disconnectHandler = new Handler();
|
this.disconnectHandler = new Handler();
|
||||||
|
|
||||||
RxJavaPlugins.setErrorHandler(e -> {
|
RxJavaPlugins.setErrorHandler(e -> {
|
||||||
@@ -466,9 +472,40 @@ public abstract class BluetoothCommunication {
|
|||||||
* @param macAddress the Bluetooth address to connect to
|
* @param macAddress the Bluetooth address to connect to
|
||||||
*/
|
*/
|
||||||
public void connect(String macAddress) {
|
public void connect(String macAddress) {
|
||||||
|
bleDevice = bleClient.getBleDevice(macAddress);
|
||||||
|
|
||||||
|
// Running an LE scan during connect improves connectivity on some phones
|
||||||
|
// (e.g. Sony Xperia Z5 compact, Android 7.1.1). For some scales (e.g. Medisana BS444)
|
||||||
|
// it seems to be a requirement that the scale is discovered before connecting to it.
|
||||||
|
// Otherwise the connection almost never succeeds.
|
||||||
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||||
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Timber.d("Do LE scan before connecting to device");
|
||||||
|
scanSubscription = bleClient.scanBleDevices(
|
||||||
|
new ScanSettings.Builder()
|
||||||
|
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||||
|
//.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(bleScanResult -> {
|
||||||
|
if (bleScanResult.getBleDevice().getMacAddress().equals(macAddress)) {
|
||||||
|
connectToDevice(macAddress);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Timber.d("No coarse location permission, connecting without LE scan");
|
||||||
|
connectToDevice(macAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectToDevice(String macAddress) {
|
||||||
Timber.d("Try to connect to BLE device " + macAddress);
|
Timber.d("Try to connect to BLE device " + macAddress);
|
||||||
|
|
||||||
bleDevice = bleClient.getBleDevice(macAddress);
|
// stop LE scan before connecting to device
|
||||||
|
if (scanSubscription != null) {
|
||||||
|
scanSubscription.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
connectionObservable = bleDevice
|
connectionObservable = bleDevice
|
||||||
.establishConnection(false)
|
.establishConnection(false)
|
||||||
@@ -478,9 +515,9 @@ public abstract class BluetoothCommunication {
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.compose(ReplayingShare.instance());
|
.compose(ReplayingShare.instance());
|
||||||
|
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
disconnect();
|
disconnect();
|
||||||
} else {
|
} else {
|
||||||
final Disposable connectionDisposable = connectionObservable
|
final Disposable connectionDisposable = connectionObservable
|
||||||
.delay(BT_DELAY, TimeUnit.MILLISECONDS)
|
.delay(BT_DELAY, TimeUnit.MILLISECONDS)
|
||||||
.flatMapSingle(RxBleConnection::discoverServices)
|
.flatMapSingle(RxBleConnection::discoverServices)
|
||||||
@@ -550,7 +587,7 @@ public abstract class BluetoothCommunication {
|
|||||||
disconnectHandler.postDelayed(new Runnable() {
|
disconnectHandler.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Timber.d("Timeout disconnect");
|
Timber.d("Timeout Bluetooth disconnect");
|
||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
}, 60000); // 60s timeout
|
}, 60000); // 60s timeout
|
||||||
@@ -565,6 +602,9 @@ public abstract class BluetoothCommunication {
|
|||||||
disconnectHandler.removeCallbacksAndMessages(null);
|
disconnectHandler.removeCallbacksAndMessages(null);
|
||||||
disconnectTriggerSubject.onNext(true);
|
disconnectTriggerSubject.onNext(true);
|
||||||
compositeDisposable.clear();
|
compositeDisposable.clear();
|
||||||
|
if (scanSubscription != null) {
|
||||||
|
scanSubscription.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -590,6 +630,7 @@ public abstract class BluetoothCommunication {
|
|||||||
cleanupStepNr++;
|
cleanupStepNr++;
|
||||||
Timber.d("CLEANUP STATE: %d", cleanupStepNr);
|
Timber.d("CLEANUP STATE: %d", cleanupStepNr);
|
||||||
if (!nextCleanUpCmd(cleanupStepNr)) {
|
if (!nextCleanUpCmd(cleanupStepNr)) {
|
||||||
|
Timber.d("Cleanup Bluetooth disconnect");
|
||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -60,18 +60,15 @@ public class BluetoothMedisanaBS44x extends BluetoothCommunication {
|
|||||||
switch (stateNr) {
|
switch (stateNr) {
|
||||||
case 0:
|
case 0:
|
||||||
// set indication on for feature characteristic
|
// set indication on for feature characteristic
|
||||||
setIndicationOn(FEATURE_MEASUREMENT_CHARACTERISTIC
|
setIndicationOn(FEATURE_MEASUREMENT_CHARACTERISTIC);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// set indication on for weight measurement
|
// set indication on for weight measurement
|
||||||
setIndicationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC
|
setIndicationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// set indication on for custom5 measurement
|
// set indication on for custom5 measurement
|
||||||
setIndicationOn(CUSTOM5_MEASUREMENT_CHARACTERISTIC
|
setIndicationOn(CUSTOM5_MEASUREMENT_CHARACTERISTIC);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// send magic number to receive weight data
|
// send magic number to receive weight data
|
||||||
|
Reference in New Issue
Block a user