Bluetooth LE: implemented cycling cadence and speed sensors.

Cadence is working while speed still requires the wheel size.
This commit is contained in:
Dennis Guse
2020-04-17 07:33:00 +02:00
parent bbe182cf82
commit ddb17f61cb
32 changed files with 1099 additions and 338 deletions
@@ -19,7 +19,7 @@ package de.dennisguse.opentracks;
import android.location.Location;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.content.data.TrackPointSensorDataSet;
/**
* Commons utilities for creating stubs of track, location.
@@ -63,6 +63,6 @@ public class TrackStubUtils {
location.setTime(INITIAL_TIME);
location.setBearing(INITIAL_BEARING);
return new TrackPoint(location, new SensorDataSet(Float.NaN, Float.NaN));
return new TrackPoint(location, new TrackPointSensorDataSet());
}
}
@@ -0,0 +1,79 @@
package de.dennisguse.opentracks.content.sensor;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import de.dennisguse.opentracks.util.UintUtils;
@RunWith(AndroidJUnit4.class)
public class SensorDataCyclingTest {
@Test
public void compute_cadence() {
// given
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence(1, 1024); // 1s
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence(2, 2048); // 2s
// when
current.compute(previous);
// then
Assert.assertEquals(57.2519, current.getCadence_rpm(), 0.01);
}
@Test
public void compute_cadence_sameCount() {
// given
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence(1, 1024);
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence(1, 2048);
// when
current.compute(previous);
// then
Assert.assertEquals(0, current.getCadence_rpm(), 0.01);
}
@Test
public void compute_cadence_sameTime() {
// given
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence(1, 1024);
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence(2, 1024);
// when
current.compute(previous);
// then
Assert.assertFalse(current.hasCadence_rpm());
}
@Test
public void compute_cadence_rollOverTime() {
// given
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence(1, UintUtils.UINT16_MAX - 1024);
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence(2, 0);
// when
current.compute(previous);
// then
Assert.assertEquals(57.2519, current.getCadence_rpm(), 0.01);
}
@Test
public void compute_cadence_rollOverCount() {
// given
SensorDataCycling.Cadence previous = new SensorDataCycling.Cadence(UintUtils.UINT32_MAX - 1, 1024);
SensorDataCycling.Cadence current = new SensorDataCycling.Cadence(0, 2048);
// when
current.compute(previous);
// then
Assert.assertEquals(57.2519, current.getCadence_rpm(), 0.01);
}
}
@@ -33,7 +33,7 @@ import de.dennisguse.opentracks.TrackStubUtils;
import de.dennisguse.opentracks.chart.ChartPoint;
import de.dennisguse.opentracks.chart.ChartView;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.content.data.TrackPointSensorDataSet;
import de.dennisguse.opentracks.util.UnitConversions;
/**
@@ -82,7 +82,7 @@ public class ChartFragmentTest {
// Input incorrect state.
// Creates SensorData.
SensorDataSet sensorDataSet = new SensorDataSet(SensorDataSet.DATA_UNAVAILABLE, SensorDataSet.DATA_UNAVAILABLE);
TrackPointSensorDataSet sensorDataSet = new TrackPointSensorDataSet();
trackPoint.setSensorDataSet(sensorDataSet);
// Test.
point = chartFragment.createPendingPoint(trackPoint);
@@ -104,7 +104,10 @@ public class ChartFragmentTest {
Assert.assertEquals(Float.NaN, point.getPower(), 0.01);
// Creates SensorData.
SensorDataSet sensorDataSet = new SensorDataSet(100, 101, 102);
TrackPointSensorDataSet sensorDataSet = new TrackPointSensorDataSet();
sensorDataSet.setHeartRate_bpm(100f);
sensorDataSet.setCyclingCadence(101);
sensorDataSet.setPower(102f);
// Creates SensorDataSet.
trackPoint.setSensorDataSet(sensorDataSet);
@@ -244,13 +244,8 @@ public class TrackRecordingServiceTestLocation {
}
@Override
public boolean isSensorDataSetValid() {
return true;
}
@Override
public SensorDataSet getSensorDataSet() {
return new SensorDataSet(1, 2);
public SensorDataSet getSensorData() {
return new SensorDataSet();
}
});
@@ -0,0 +1,76 @@
package de.dennisguse.opentracks.util;
import android.bluetooth.BluetoothGattCharacteristic;
import org.junit.Assert;
import org.junit.Test;
import de.dennisguse.opentracks.content.sensor.SensorDataCycling;
public class BluetoothUtilsTest {
@Test
public void parseHeartRate_uint8() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.HEART_RATE_SERVICE_UUID, 0, 0);
characteristic.setValue(new byte[]{0x02, 0x3C});
// when
int heartRate = BluetoothUtils.parseHeartRate(characteristic);
// then
Assert.assertEquals(60, heartRate);
}
@Test
public void parseHeartRate_uint16() {
// given
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.HEART_RATE_SERVICE_UUID, 0, 0);
characteristic.setValue(new byte[]{0x01, 0x01, 0x01});
// when
int heartRate = BluetoothUtils.parseHeartRate(characteristic);
// then
Assert.assertEquals(257, heartRate);
}
@Test
public void parseCyclingSpeedCadence_crankOnly() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE_SERVICE_UUID, 0, 0);
characteristic.setValue(new byte[]{0x01, (byte) 0xC8, 0x00, 0x00, 0x00, 0x06, (byte) 0x99});
// when
SensorDataCycling.CadenceAndSpeed sensor = BluetoothUtils.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
// then
Assert.assertEquals(200, sensor.getCadence().getCrankRevolutionsCount());
Assert.assertNull(sensor.getSpeed());
}
@Test
public void parseCyclingSpeedCadence_wheelOnly() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE_SERVICE_UUID, 0, 0);
characteristic.setValue(new byte[]{0x02, (byte) 0xE1, 0x00, 0x45, (byte) 0x99});
// when
SensorDataCycling.CadenceAndSpeed sensor = BluetoothUtils.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
// then
Assert.assertNull(sensor.getCadence());
Assert.assertEquals(225, sensor.getSpeed().getWheelRevolutionsCount());
}
@Test
public void parseCyclingSpeedCadence_crankWheel() {
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(BluetoothUtils.CYCLING_SPEED_CADENCE_SERVICE_UUID, 0, 0);
characteristic.setValue(new byte[]{0x03, (byte) 0xC8, 0x00, 0x00, 0x00, 0x06, (byte) 0x99, (byte) 0xE1, 0x00, 0x45, (byte) 0x99});
// when
SensorDataCycling.CadenceAndSpeed sensor = BluetoothUtils.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
// then
Assert.assertEquals(200, sensor.getCadence().getCrankRevolutionsCount());
Assert.assertEquals(225, sensor.getSpeed().getWheelRevolutionsCount());
}
}