Bluetooth: use composition instead of inheritance.

Part of #1424.
This commit is contained in:
Dennis Guse
2023-11-05 14:15:02 +01:00
parent 3a2a62a6d7
commit 4d54472c93
16 changed files with 185 additions and 163 deletions
@@ -21,7 +21,7 @@ public class BluetoothUtilsTest {
@Test
public void parseHeartRate_uint8() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.HEARTRATE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerHeartRate.HEARTRATE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x02, 0x3C});
// when
@@ -34,7 +34,7 @@ public class BluetoothUtilsTest {
@Test
public void parseHeartRate_uint16() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.HEARTRATE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerHeartRate.HEARTRATE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x01, 0x01, 0x01});
// when
@@ -59,7 +59,7 @@ public class BluetoothUtilsTest {
@Test
public void parseCyclingSpeedCadence_crankOnly() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x02, (byte) 0xC8, 0x00, 0x00, 0x00, 0x06, (byte) 0x99});
// when
@@ -72,7 +72,7 @@ public class BluetoothUtilsTest {
@Test
public void parseCyclingSpeedCadence_wheelOnly() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x01, (byte) 0xFF, (byte) 0xFF, 0, 1, 0x45, (byte) 0x99});
// when
@@ -85,7 +85,7 @@ public class BluetoothUtilsTest {
@Test
public void parseCyclingSpeedCadence_crankWheel() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x03, (byte) 0xC8, 0x00, 0x00, 0x01, 0x06, (byte) 0x99, (byte) 0xE1, 0x00, 0x45, (byte) 0x99});
// when
@@ -98,7 +98,7 @@ public class BluetoothUtilsTest {
@Test
public void parseCyclingPower_power() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_POWER.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingPower.CYCLING_POWER.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0, 0, 40, 0});
// when
@@ -110,7 +110,7 @@ public class BluetoothUtilsTest {
@Test
public void parseCyclingPower_power_with_cadence() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_POWER.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingPower.CYCLING_POWER.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x2C, 0x00, 0x00, 0x00, (byte) 0x9F, 0x00, 0x0C, 0x00, (byte) 0xE5, 0x42});
// when
@@ -125,7 +125,7 @@ public class BluetoothUtilsTest {
@Test
public void parseRunningSpeedAndCadence_with_distance() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.RUNNING_SPEED_CADENCE.serviceUUID(), 0, 0);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionRunningSpeedAndCadence.RUNNING_SPEED_CADENCE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{2, 0, 5, 80, (byte) 0xFF, (byte) 0xFF, 0, 1});
// when
@@ -30,23 +30,23 @@ import android.util.Log;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
/**
* Manages connection to a Bluetooth LE sensor and subscribes for onChange-notifications.
*/
@SuppressLint("MissingPermission")
public abstract class AbstractBluetoothConnectionManager<DataType> {
public class BluetoothConnectionManager {
private static final String TAG = AbstractBluetoothConnectionManager.class.getSimpleName();
private static final String TAG = BluetoothConnectionManager.class.getSimpleName();
private final SensorManager.SensorDataChangedObserver observer;
private final List<ServiceMeasurementUUID> serviceMeasurementUUIDs;
private final SensorHandlerInterface sensorHandler;
private BluetoothGatt bluetoothGatt;
private final BluetoothGattCallback connectCallback = new BluetoothGattCallback() {
@@ -76,7 +76,7 @@ public abstract class AbstractBluetoothConnectionManager<DataType> {
public void onServicesDiscovered(@NonNull BluetoothGatt gatt, int status) {
BluetoothGattService gattService = null;
ServiceMeasurementUUID serviceMeasurement = null;
for (ServiceMeasurementUUID s : serviceMeasurementUUIDs) {
for (ServiceMeasurementUUID s : sensorHandler.getServices()) {
gattService = gatt.getService(s.serviceUUID());
if (gattService != null) {
serviceMeasurement = s;
@@ -112,24 +112,22 @@ public abstract class AbstractBluetoothConnectionManager<DataType> {
public void onCharacteristicChanged(BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic) {
UUID serviceUUID = characteristic.getService().getUuid();
Log.d(TAG, "Received data from " + gatt.getDevice().getAddress() + " with service " + serviceUUID + " and characteristics " + characteristic.getUuid());
Optional<ServiceMeasurementUUID> serviceMeasurementUUID = serviceMeasurementUUIDs.stream()
.filter(s -> s.serviceUUID().equals(characteristic.getService().getUuid())).findFirst();
Optional<ServiceMeasurementUUID> serviceMeasurementUUID = sensorHandler.getServices()
.stream()
.filter(s -> s.serviceUUID().equals(characteristic.getService().getUuid()))
.findFirst();
if (serviceMeasurementUUID.isEmpty()) {
Log.e(TAG, "Unknown service UUID; not supported?");
return;
}
SensorData<DataType> sensorData = parsePayload(serviceMeasurementUUID.get(), gatt.getDevice().getName(), gatt.getDevice().getAddress(), characteristic);
if (sensorData != null) {
Log.d(TAG, "Decoded data from " + gatt.getDevice().getAddress() + ": " + sensorData);
observer.onChange(sensorData);
}
sensorHandler.handlePayload(observer, serviceMeasurementUUID.get(), gatt.getDevice().getName(), gatt.getDevice().getAddress(), characteristic);
}
};
AbstractBluetoothConnectionManager(List<ServiceMeasurementUUID> serviceUUUID, SensorManager.SensorDataChangedObserver observer) {
this.serviceMeasurementUUIDs = serviceUUUID;
BluetoothConnectionManager(SensorManager.SensorDataChangedObserver observer, SensorHandlerInterface sensorHandler) {
this.observer = observer;
this.sensorHandler = sensorHandler;
}
synchronized void connect(Context context, Handler handler, @NonNull BluetoothDevice device) {
@@ -142,12 +140,12 @@ public abstract class AbstractBluetoothConnectionManager<DataType> {
bluetoothGatt = device.connectGatt(context, false, connectCallback, BluetoothDevice.TRANSPORT_AUTO, 0, handler);
SensorData<?> sensorData = createEmptySensorData(bluetoothGatt.getDevice().getAddress());
SensorData<?> sensorData = sensorHandler.createEmptySensorData(bluetoothGatt.getDevice().getAddress());
observer.onChange(sensorData);
}
private synchronized void clearData() {
observer.onDisconnect(createEmptySensorData(bluetoothGatt.getDevice().getAddress()));
observer.onDisconnect(sensorHandler.createEmptySensorData(bluetoothGatt.getDevice().getAddress()));
}
synchronized void disconnect() {
@@ -167,11 +165,4 @@ public abstract class AbstractBluetoothConnectionManager<DataType> {
return address.equals(bluetoothGatt.getDevice().getAddress());
}
protected abstract SensorData<DataType> createEmptySensorData(String address);
/**
* @return null if data could not be parsed.
*/
protected abstract SensorData<DataType> parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, @NonNull BluetoothGattCharacteristic characteristic);
}
@@ -1,47 +0,0 @@
package de.dennisguse.opentracks.sensors;
import android.bluetooth.BluetoothGattCharacteristic;
import android.util.Log;
import de.dennisguse.opentracks.data.models.Cadence;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
public class BluetoothConnectionManagerCyclingCadence extends AbstractBluetoothConnectionManager<Cadence> {
private static final String TAG = BluetoothConnectionManagerCyclingCadence.class.getSimpleName();
BluetoothConnectionManagerCyclingCadence(SensorManager.SensorDataChangedObserver observer) {
super(BluetoothUtils.CYCLING_CADENCE, observer);
}
@Override
protected SensorDataCyclingCadence createEmptySensorData(String address) {
return new SensorDataCyclingCadence(address);
}
@Override
protected SensorDataCyclingCadence parsePayload(ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
//TODO Implement to ServiceMeasurement.parse()?
if (serviceMeasurementUUID.equals(BluetoothUtils.CYCLING_POWER)) {
SensorDataCyclingPower.Data data = BluetoothUtils.parseCyclingPower(address, sensorName, characteristic);
if (data!= null) {
return data.cadence();
}
} else if (serviceMeasurementUUID.equals(BluetoothUtils.CYCLING_SPEED_CADENCE)) {
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = BluetoothUtils.parseCyclingCrankAndWheel(address, sensorName, characteristic);
if (cadenceAndSpeed == null) {
return null;
}
if (cadenceAndSpeed.getCadence() != null) {
return cadenceAndSpeed.getCadence();
}
}
Log.e(TAG, "Don't know how to decode this payload.");
return null;
}
}
@@ -3,32 +3,38 @@ package de.dennisguse.opentracks.sensors;
import android.bluetooth.BluetoothGattCharacteristic;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
public class BluetoothConnectionManagerCyclingDistanceSpeed extends AbstractBluetoothConnectionManager<SensorDataCyclingDistanceSpeed.Data> {
public class BluetoothConnectionManagerCyclingDistanceSpeed implements SensorHandlerInterface {
BluetoothConnectionManagerCyclingDistanceSpeed(SensorManager.SensorDataChangedObserver observer) {
super(List.of(BluetoothUtils.CYCLING_SPEED_CADENCE), observer);
public static final ServiceMeasurementUUID CYCLING_SPEED_CADENCE = new ServiceMeasurementUUID(
new UUID(0x181600001000L, 0x800000805f9b34fbL),
new UUID(0x2A5B00001000L, 0x800000805f9b34fbL)
);
@Override
public List<ServiceMeasurementUUID> getServices() {
return List.of(CYCLING_SPEED_CADENCE);
}
@Override
protected SensorDataCyclingDistanceSpeed createEmptySensorData(String address) {
public SensorDataCyclingDistanceSpeed createEmptySensorData(String address) {
return new SensorDataCyclingDistanceSpeed(address);
}
@Override
protected SensorDataCyclingDistanceSpeed parsePayload(ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = BluetoothUtils.parseCyclingCrankAndWheel(address, sensorName, characteristic);
if (cadenceAndSpeed == null) {
return null;
return;
}
if (cadenceAndSpeed.getDistanceSpeed() != null) {
return cadenceAndSpeed.getDistanceSpeed();
observer.onChange(cadenceAndSpeed.getDistanceSpeed());
}
return null;
}
}
@@ -5,25 +5,34 @@ import android.bluetooth.BluetoothGattCharacteristic;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
public class BluetoothConnectionManagerCyclingPower extends AbstractBluetoothConnectionManager<Power> {
public class BluetoothConnectionManagerCyclingPower implements SensorHandlerInterface {
BluetoothConnectionManagerCyclingPower(@NonNull SensorManager.SensorDataChangedObserver observer) {
super(List.of(BluetoothUtils.CYCLING_POWER), observer);
public static final ServiceMeasurementUUID CYCLING_POWER = new ServiceMeasurementUUID(
new UUID(0x181800001000L, 0x800000805f9b34fbL),
new UUID(0x2A6300001000L, 0x800000805f9b34fbL)
);
@Override
public List<ServiceMeasurementUUID> getServices() {
return List.of(CYCLING_POWER);
}
@Override
protected SensorDataCyclingPower createEmptySensorData(String address) {
public SensorDataCyclingPower createEmptySensorData(String address) {
return new SensorDataCyclingPower(address);
}
@Override
protected SensorDataCyclingPower parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
SensorDataCyclingPower.Data cyclingPower = BluetoothUtils.parseCyclingPower(address, sensorName, characteristic);
return cyclingPower != null ? cyclingPower.power() : null;
if (cyclingPower != null) {
observer.onChange(cyclingPower.power());
}
}
}
@@ -5,25 +5,45 @@ import android.bluetooth.BluetoothGattCharacteristic;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
public class BluetoothConnectionManagerHeartRate extends AbstractBluetoothConnectionManager<HeartRate> {
public class BluetoothConnectionManagerHeartRate implements SensorHandlerInterface {
BluetoothConnectionManagerHeartRate(@NonNull SensorManager.SensorDataChangedObserver observer) {
super(List.of(BluetoothUtils.HEARTRATE), observer);
public static final ServiceMeasurementUUID HEARTRATE = new ServiceMeasurementUUID(
new UUID(0x180D00001000L, 0x800000805f9b34fbL),
new UUID(0x2A3700001000L, 0x800000805f9b34fbL)
);
// Used for device discovery in preferences
public static final List<ServiceMeasurementUUID> HEART_RATE_SUPPORTING_DEVICES = List.of(
HEARTRATE,
//Devices that support HEART_RATE_SERVICE_UUID, but do not announce HEART_RATE_SERVICE_UUID in there BLE announcement messages (during device discovery).
new ServiceMeasurementUUID(
UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb"), //Miband3
HEARTRATE.measurementUUID()
)
);
@Override
public List<ServiceMeasurementUUID> getServices() {
return HEART_RATE_SUPPORTING_DEVICES;
}
@Override
protected SensorDataHeartRate createEmptySensorData(String address) {
public SensorDataHeartRate createEmptySensorData(String address) {
return new SensorDataHeartRate(address);
}
@Override
protected SensorDataHeartRate parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
HeartRate heartRate = BluetoothUtils.parseHeartRate(characteristic);
return heartRate != null ? new SensorDataHeartRate(address, sensorName, heartRate) : null;
if (heartRate != null) {
observer.onChange(new SensorDataHeartRate(address, sensorName, heartRate));
}
}
}
@@ -5,22 +5,31 @@ import android.bluetooth.BluetoothGattCharacteristic;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
public class BluetoothConnectionRunningSpeedAndCadence extends AbstractBluetoothConnectionManager<SensorDataRunning.Data> {
public class BluetoothConnectionRunningSpeedAndCadence implements SensorHandlerInterface {
BluetoothConnectionRunningSpeedAndCadence(@NonNull SensorManager.SensorDataChangedObserver observer) {
super(List.of(BluetoothUtils.RUNNING_SPEED_CADENCE), observer);
public static final ServiceMeasurementUUID RUNNING_SPEED_CADENCE = new ServiceMeasurementUUID(
new UUID(0x181400001000L, 0x800000805f9b34fbL),
new UUID(0x2A5300001000L, 0x800000805f9b34fbL)
);
@Override
public List<ServiceMeasurementUUID> getServices() {
return List.of(RUNNING_SPEED_CADENCE);
}
@Override
protected SensorDataRunning createEmptySensorData(String address) {
public SensorDataRunning createEmptySensorData(String address) {
return new SensorDataRunning(address);
}
@Override
protected SensorDataRunning parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
return BluetoothUtils.parseRunningSpeedAndCadence(address, sensorName, characteristic);
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
observer.onChange(BluetoothUtils.parseRunningSpeedAndCadence(address, sensorName, characteristic));
}
}
@@ -0,0 +1,53 @@
package de.dennisguse.opentracks.sensors;
import android.bluetooth.BluetoothGattCharacteristic;
import android.util.Log;
import java.util.List;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
public class BluetoothHandlerCyclingCadence implements SensorHandlerInterface {
private static final String TAG = BluetoothHandlerCyclingCadence.class.getSimpleName();
public static final List<ServiceMeasurementUUID> CYCLING_CADENCE = List.of(
BluetoothConnectionManagerCyclingPower.CYCLING_POWER,
BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE
);
@Override
public List<ServiceMeasurementUUID> getServices() {
return CYCLING_CADENCE;
}
@Override
public SensorDataCyclingCadence createEmptySensorData(String address) {
return new SensorDataCyclingCadence(address);
}
@Override
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
//TODO Implement to ServiceMeasurement.parse()?
if (serviceMeasurementUUID.equals(BluetoothConnectionManagerCyclingPower.CYCLING_POWER)) {
SensorDataCyclingPower.Data data = BluetoothUtils.parseCyclingPower(address, sensorName, characteristic);
if (data!= null) {
observer.onChange(data.cadence());
}
} else if (serviceMeasurementUUID.equals(BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE)) {
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = BluetoothUtils.parseCyclingCrankAndWheel(address, sensorName, characteristic);
if (cadenceAndSpeed == null) {
return;
}
if (cadenceAndSpeed.getCadence() != null) {
observer.onChange(cadenceAndSpeed.getCadence());
}
}
Log.e(TAG, "Don't know how to decode this payload.");
}
}
@@ -57,22 +57,22 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
private final Handler handler;
private boolean started = false;
private final BluetoothConnectionManagerHeartRate heartRate;
private final BluetoothConnectionManagerCyclingCadence cyclingCadence;
private final BluetoothConnectionManagerCyclingDistanceSpeed cyclingSpeed;
private final BluetoothConnectionManagerCyclingPower cyclingPower;
private final BluetoothConnectionRunningSpeedAndCadence runningSpeedAndCadence;
private final BluetoothConnectionManager heartRate;
private final BluetoothConnectionManager cyclingCadence;
private final BluetoothConnectionManager cyclingSpeed;
private final BluetoothConnectionManager cyclingPower;
private final BluetoothConnectionManager runningSpeedAndCadence;
public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @Nullable SensorManager.SensorDataChangedObserver observer) {
this.context = context;
this.handler = handler;
bluetoothAdapter = BluetoothUtils.getAdapter(context);
this.heartRate = new BluetoothConnectionManagerHeartRate(observer);
this.cyclingCadence = new BluetoothConnectionManagerCyclingCadence(observer);
this.cyclingSpeed = new BluetoothConnectionManagerCyclingDistanceSpeed(observer);
this.cyclingPower = new BluetoothConnectionManagerCyclingPower(observer);
this.runningSpeedAndCadence = new BluetoothConnectionRunningSpeedAndCadence(observer);
this.heartRate = new BluetoothConnectionManager(observer, new BluetoothConnectionManagerHeartRate());
this.cyclingCadence = new BluetoothConnectionManager(observer, new BluetoothConnectionManagerCyclingDistanceSpeed());
this.cyclingSpeed = new BluetoothConnectionManager(observer, new BluetoothConnectionManagerCyclingDistanceSpeed());
this.cyclingPower = new BluetoothConnectionManager(observer, new BluetoothConnectionManagerCyclingPower());
this.runningSpeedAndCadence = new BluetoothConnectionManager(observer, new BluetoothConnectionRunningSpeedAndCadence());
}
@@ -99,7 +99,7 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
}
private synchronized void connect(AbstractBluetoothConnectionManager<?> connectionManager, String address) {
private synchronized void connect(BluetoothConnectionManager connectionManager, String address) {
if (!isEnabled()) {
Log.w(TAG, "Bluetooth not enabled.");
return;
@@ -23,7 +23,6 @@ import android.util.Log;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
@@ -53,47 +52,12 @@ public class BluetoothUtils {
new UUID(0x2A1900001000L, 0x800000805f9b34fbL)
);
public static final ServiceMeasurementUUID HEARTRATE = new ServiceMeasurementUUID(
new UUID(0x180D00001000L, 0x800000805f9b34fbL),
new UUID(0x2A3700001000L, 0x800000805f9b34fbL)
);
// Used for device discovery in preferences
public static final List<ServiceMeasurementUUID> HEART_RATE_SUPPORTING_DEVICES = List.of(
HEARTRATE,
//Devices that support HEART_RATE_SERVICE_UUID, but do not announce HEART_RATE_SERVICE_UUID in there BLE announcement messages (during device discovery).
new ServiceMeasurementUUID(
UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb"), //Miband3
HEARTRATE.measurementUUID()
)
);
private static final UUID ENVIRONMENTAL_SENSING_SERVICE = new UUID(0x181A00001000L, 0x800000805f9b34fbL);
public static final ServiceMeasurementUUID BAROMETRIC_PRESSURE = new ServiceMeasurementUUID(
ENVIRONMENTAL_SENSING_SERVICE,
new UUID(0x2A6D00001000L, 0x800000805f9b34fbL)
);
public static final ServiceMeasurementUUID CYCLING_POWER = new ServiceMeasurementUUID(
new UUID(0x181800001000L, 0x800000805f9b34fbL),
new UUID(0x2A6300001000L, 0x800000805f9b34fbL)
);
public static final ServiceMeasurementUUID CYCLING_SPEED_CADENCE = new ServiceMeasurementUUID(
new UUID(0x181600001000L, 0x800000805f9b34fbL),
new UUID(0x2A5B00001000L, 0x800000805f9b34fbL)
);
public static final List<ServiceMeasurementUUID> CYCLING_CADENCE = List.of(
CYCLING_POWER,
CYCLING_SPEED_CADENCE
);
public static final ServiceMeasurementUUID RUNNING_SPEED_CADENCE = new ServiceMeasurementUUID(
new UUID(0x181400001000L, 0x800000805f9b34fbL),
new UUID(0x2A5300001000L, 0x800000805f9b34fbL)
);
private static final String TAG = BluetoothUtils.class.getSimpleName();
private BluetoothUtils() {
@@ -0,0 +1,17 @@
package de.dennisguse.opentracks.sensors.sensorData;
import android.bluetooth.BluetoothGattCharacteristic;
import java.util.List;
import de.dennisguse.opentracks.sensors.SensorManager;
import de.dennisguse.opentracks.sensors.ServiceMeasurementUUID;
public interface SensorHandlerInterface {
List<ServiceMeasurementUUID> getServices();
SensorData<?> createEmptySensorData(String address);
void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic);
}
@@ -5,7 +5,7 @@ import android.util.AttributeSet;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
public class BluetoothLeCyclingCadencePreference extends BluetoothLeSensorPreference {
@@ -27,6 +27,6 @@ public class BluetoothLeCyclingCadencePreference extends BluetoothLeSensorPrefer
@Override
public PreferenceDialogFragmentCompat createInstance() {
return BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothUtils.CYCLING_CADENCE);
return BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothHandlerCyclingCadence.CYCLING_CADENCE);
}
}
@@ -5,7 +5,7 @@ import android.util.AttributeSet;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.sensors.BluetoothConnectionManagerCyclingPower;
public class BluetoothLeCyclingPowerPreference extends BluetoothLeSensorPreference {
@@ -27,6 +27,6 @@ public class BluetoothLeCyclingPowerPreference extends BluetoothLeSensorPreferen
@Override
public PreferenceDialogFragmentCompat createInstance() {
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothUtils.CYCLING_POWER);
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothConnectionManagerCyclingPower.CYCLING_POWER);
}
}
@@ -5,7 +5,7 @@ import android.util.AttributeSet;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.sensors.BluetoothConnectionManagerCyclingDistanceSpeed;
public class BluetoothLeCyclingSpeedPreference extends BluetoothLeSensorPreference {
@@ -27,6 +27,6 @@ public class BluetoothLeCyclingSpeedPreference extends BluetoothLeSensorPreferen
@Override
public PreferenceDialogFragmentCompat createInstance() {
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothUtils.CYCLING_SPEED_CADENCE);
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothConnectionManagerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE);
}
}
@@ -5,7 +5,7 @@ import android.util.AttributeSet;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.sensors.BluetoothConnectionManagerHeartRate;
public class BluetoothLeHeartRatePreference extends BluetoothLeSensorPreference {
@@ -27,6 +27,6 @@ public class BluetoothLeHeartRatePreference extends BluetoothLeSensorPreference
@Override
public PreferenceDialogFragmentCompat createInstance() {
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothUtils.HEART_RATE_SUPPORTING_DEVICES);
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothConnectionManagerHeartRate.HEART_RATE_SUPPORTING_DEVICES);
}
}
@@ -5,7 +5,7 @@ import android.util.AttributeSet;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.sensors.BluetoothUtils;
import de.dennisguse.opentracks.sensors.BluetoothConnectionRunningSpeedAndCadence;
public class BluetoothLeRunningSpeedAndCadencePreference extends BluetoothLeSensorPreference {
@@ -27,6 +27,6 @@ public class BluetoothLeRunningSpeedAndCadencePreference extends BluetoothLeSens
@Override
public PreferenceDialogFragmentCompat createInstance() {
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothUtils.RUNNING_SPEED_CADENCE);
return BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(getKey(), BluetoothConnectionRunningSpeedAndCadence.RUNNING_SPEED_CADENCE);
}
}