Skip to content

Commit

Permalink
Bluetooth: inline BluetoothUtils into Handler classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisguse committed Nov 5, 2023
1 parent deeb447 commit 4c8554b
Show file tree
Hide file tree
Showing 13 changed files with 391 additions and 314 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package de.dennisguse.opentracks.sensors;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import android.bluetooth.BluetoothGattCharacteristic;

import org.junit.Test;

import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;

public class BluetoothConnectionManagerCyclingDistanceSpeedTest {
@Test
public void parseCyclingSpeedCadence_crankOnly() {
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
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothConnectionManagerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);

// then
assertNull(sensor.getDistanceSpeed());
assertEquals(200, sensor.getCadence().getCrankRevolutionsCount());
}

@Test
public void parseCyclingSpeedCadence_wheelOnly() {
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
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothConnectionManagerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);

// then
assertEquals(65535 + 16777216, sensor.getDistanceSpeed().getWheelRevolutionsCount());
assertNull(sensor.getCadence());
}

@Test
public void parseCyclingSpeedCadence_crankWheel() {
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
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothConnectionManagerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);

// then
assertEquals(200 + 16777216, sensor.getDistanceSpeed().getWheelRevolutionsCount());
assertEquals(225, sensor.getCadence().getCrankRevolutionsCount());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package de.dennisguse.opentracks.sensors;

import static org.junit.Assert.assertEquals;

import android.bluetooth.BluetoothGattCharacteristic;

import org.junit.Test;

import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;

public class BluetoothConnectionManagerCyclingPowerTest {

@Test
public void parseCyclingPower_power() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerCyclingPower.CYCLING_POWER.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0, 0, 40, 0});

// when
SensorDataCyclingPower.Data powerCadence = BluetoothConnectionManagerCyclingPower.parseCyclingPower("", "", characteristic);

// then
assertEquals(40, powerCadence.power().getValue().getW(), 0.01);
}

@Test
public void parseCyclingPower_power_with_cadence() {
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
SensorDataCyclingPower.Data powerCadence = BluetoothConnectionManagerCyclingPower.parseCyclingPower("", "", characteristic);

// then
assertEquals(0, powerCadence.power().getValue().getW(), 0.01);

assertEquals(12, powerCadence.cadence().getCrankRevolutionsCount());
assertEquals(17125, powerCadence.cadence().getCrankRevolutionsTime());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package de.dennisguse.opentracks.sensors;

import static org.junit.Assert.assertEquals;

import android.bluetooth.BluetoothGattCharacteristic;

import org.junit.Test;

import de.dennisguse.opentracks.data.models.HeartRate;

public class BluetoothConnectionManagerHeartRateTest {

@Test
public void parseHeartRate_uint8() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerHeartRate.HEARTRATE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x02, 0x3C});

// when
HeartRate heartRate = BluetoothConnectionManagerHeartRate.parseHeartRate(characteristic);

// then
assertEquals(HeartRate.of(60), heartRate);
}

@Test
public void parseHeartRate_uint16() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothConnectionManagerHeartRate.HEARTRATE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{0x01, 0x01, 0x01});

// when
HeartRate heartRate = BluetoothConnectionManagerHeartRate.parseHeartRate(characteristic);

// then
assertEquals(HeartRate.of(257), heartRate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.dennisguse.opentracks.sensors;

import static org.junit.Assert.assertEquals;

import android.bluetooth.BluetoothGattCharacteristic;

import org.junit.Test;

import de.dennisguse.opentracks.data.models.Cadence;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;

public class BluetoothConnectionRunningSpeedAndCadenceTest {

@Test
public void parseRunningSpeedAndCadence_with_distance() {
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
SensorDataRunning sensor = BluetoothConnectionRunningSpeedAndCadence.parseRunningSpeedAndCadence("address", "sensorName", characteristic);

// then
assertEquals(Speed.of(5), sensor.getSpeed());
assertEquals(Cadence.of(80), sensor.getCadence());
assertEquals(Distance.of(6553.5 + 1677721.6), sensor.getTotalDistance());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.dennisguse.opentracks.sensors;

import static org.junit.Assert.assertEquals;

import android.bluetooth.BluetoothGattCharacteristic;

import org.junit.Test;

import de.dennisguse.opentracks.data.models.AtmosphericPressure;

public class BluetoothHandlerBarometricPressureTest {

@Test
public void parseEnvironmentalSensing_Pa() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothHandlerBarometricPressure.BAROMETRIC_PRESSURE.serviceUUID(), 0, 0);
characteristic.setValue(new byte[]{(byte) 0xB2, (byte) 0x48, (byte) 0x0F, (byte) 0x00});

// when
AtmosphericPressure pressure = BluetoothHandlerBarometricPressure.parseEnvironmentalSensing(characteristic);

// then
assertEquals(AtmosphericPressure.ofPA(100165), pressure);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import android.bluetooth.BluetoothGattCharacteristic;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import java.util.List;
import java.util.UUID;

import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
Expand All @@ -28,7 +32,7 @@ public SensorDataCyclingDistanceSpeed createEmptySensorData(String address) {

@Override
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = BluetoothUtils.parseCyclingCrankAndWheel(address, sensorName, characteristic);
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = parseCyclingCrankAndWheel(address, sensorName, characteristic);
if (cadenceAndSpeed == null) {
return;
}
Expand All @@ -37,4 +41,39 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, Serv
observer.onChange(cadenceAndSpeed.getDistanceSpeed());
}
}


@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public static SensorDataCyclingCadenceAndDistanceSpeed parseCyclingCrankAndWheel(String address, String sensorName, @NonNull BluetoothGattCharacteristic characteristic) {
// DOCUMENTATION https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.csc_measurement.xml
int valueLength = characteristic.getValue().length;
if (valueLength == 0) {
return null;
}

int flags = characteristic.getValue()[0];
boolean hasWheel = (flags & 0x01) > 0;
boolean hasCrank = (flags & 0x02) > 0;

int index = 1;
SensorDataCyclingDistanceSpeed speed = null;
if (hasWheel && valueLength - index >= 6) {
int wheelTotalRevolutionCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, index);
index += 4;
int wheelTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index); // 1/1024s
speed = new SensorDataCyclingDistanceSpeed(address, sensorName, wheelTotalRevolutionCount, wheelTime);
index += 2;
}

SensorDataCyclingCadence cadence = null;
if (hasCrank && valueLength - index >= 4) {
long crankCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index);
index += 2;

int crankTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index); // 1/1024s
cadence = new SensorDataCyclingCadence(address, sensorName, crankCount, crankTime);
}

return new SensorDataCyclingCadenceAndDistanceSpeed(address, sensorName, cadence, speed);
}
}
Loading

0 comments on commit 4c8554b

Please sign in to comment.