Adjusting CSC to changes in BLE library

This commit is contained in:
Aleksander Nowakowski
2018-04-13 17:03:04 +02:00
parent 0627f29ec9
commit 1c16898c15
5 changed files with 80 additions and 142 deletions

View File

@@ -226,8 +226,8 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
if (CSCService.BROADCAST_WHEEL_DATA.equals(action)) {
final float speed = intent.getFloatExtra(CSCService.EXTRA_SPEED, 0.0f); // [m/s]
final float distance = intent.getFloatExtra(CSCService.EXTRA_DISTANCE, CSCManagerCallbacks.NOT_AVAILABLE);
final float totalDistance = intent.getFloatExtra(CSCService.EXTRA_TOTAL_DISTANCE, CSCManagerCallbacks.NOT_AVAILABLE);
final float distance = intent.getFloatExtra(CSCService.EXTRA_DISTANCE, 0);
final float totalDistance = intent.getFloatExtra(CSCService.EXTRA_TOTAL_DISTANCE, 0);
// Update GUI
onMeasurementReceived(speed, distance, totalDistance);
} else if (CSCService.BROADCAST_CRANK_DATA.equals(action)) {

View File

@@ -22,33 +22,40 @@
package no.nordicsemi.android.nrftoolbox.csc;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import java.util.Deque;
import java.util.LinkedList;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.Request;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.ble.callback.Data;
import no.nordicsemi.android.ble.callback.profile.CyclingSpeedAndCadenceCallback;
import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.nrftoolbox.csc.settings.SettingsFragment;
import no.nordicsemi.android.nrftoolbox.parser.CSCMeasurementParser;
public class CSCManager extends BleManager<CSCManagerCallbacks> {
/** Cycling Speed and Cadence service UUID */
/**
* Cycling Speed and Cadence service UUID
*/
public final static UUID CYCLING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001816-0000-1000-8000-00805f9b34fb");
/** Cycling Speed and Cadence Measurement characteristic UUID */
/**
* Cycling Speed and Cadence Measurement characteristic UUID
*/
private static final UUID CSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A5B-0000-1000-8000-00805f9b34fb");
private static final byte WHEEL_REVOLUTIONS_DATA_PRESENT = 0x01; // 1 bit
private static final byte CRANK_REVOLUTION_DATA_PRESENT = 0x02; // 1 bit
private final SharedPreferences preferences;
private BluetoothGattCharacteristic mCSCMeasurementCharacteristic;
public CSCManager(final Context context) {
CSCManager(final Context context) {
super(context);
preferences = PreferenceManager.getDefaultSharedPreferences(context);
}
@Override
@@ -62,10 +69,35 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mCSCMeasurementCharacteristic));
return requests;
protected void initialize(final BluetoothDevice device) {
enableNotifications(mCSCMeasurementCharacteristic)
.with(new CyclingSpeedAndCadenceCallback() {
@Override
public void onDataReceived(@NonNull final Data data) {
log(LogContract.Log.Level.APPLICATION, "\"" + CSCMeasurementParser.parse(data) + "\" received");
super.onDataReceived(data);
}
@Override
protected float getWheelCircumference() {
return Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_WHEEL_SIZE, String.valueOf(SettingsFragment.SETTINGS_WHEEL_SIZE_DEFAULT)));
}
@Override
protected void onDistanceChanged(final float totalDistance, final float distance, final float speed) {
mCallbacks.onDistanceChanged(device, totalDistance, distance, speed);
}
@Override
protected void onCrankDataChanged(final float crankCadence, final float gearRatio) {
mCallbacks.onCrankDataChanged(device, crankCadence, gearRatio);
}
@Override
public void onInvalidDataReceived(@NonNull final Data data) {
log(LogContract.Log.Level.WARNING, "Invalid data received: " + data);
}
});
}
@Override
@@ -81,40 +113,5 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
protected void onDeviceDisconnected() {
mCSCMeasurementCharacteristic = null;
}
@Override
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
Logger.a(mLogSession, "\"" + CSCMeasurementParser.parse(characteristic) + "\" received");
// Decode the new data
int offset = 0;
final int flags = characteristic.getValue()[offset]; // 1 byte
offset += 1;
final boolean wheelRevPresent = (flags & WHEEL_REVOLUTIONS_DATA_PRESENT) > 0;
final boolean crankRevPreset = (flags & CRANK_REVOLUTION_DATA_PRESENT) > 0;
if (wheelRevPresent) {
final int wheelRevolutions = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, offset);
offset += 4;
final int lastWheelEventTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset); // 1/1024 s
offset += 2;
// Notify listener about the new measurement
mCallbacks.onWheelMeasurementReceived(gatt.getDevice(), wheelRevolutions, lastWheelEventTime);
}
if (crankRevPreset) {
final int crankRevolutions = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
offset += 2;
final int lastCrankEventTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
// offset += 2;
// Notify listener about the new measurement
mCallbacks.onCrankMeasurementReceived(gatt.getDevice(), crankRevolutions, lastCrankEventTime);
}
}
};
}

View File

@@ -26,9 +26,7 @@ import android.bluetooth.BluetoothDevice;
import no.nordicsemi.android.ble.BleManagerCallbacks;
public interface CSCManagerCallbacks extends BleManagerCallbacks {
int NOT_AVAILABLE = -1;
void onDistanceChanged(final BluetoothDevice device, final float totalDistance, final float distance, final float speed);
void onWheelMeasurementReceived(final BluetoothDevice device, final int wheelRevolutions, final int wheelCrankEventTime);
void onCrankMeasurementReceived(final BluetoothDevice device, final int crankRevolutions, final int lastCrankEventTime);
void onCrankDataChanged(final BluetoothDevice device, final float crankCadence, final float gearRatio);
}

View File

@@ -30,8 +30,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
@@ -40,10 +38,10 @@ import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
import no.nordicsemi.android.nrftoolbox.R;
import no.nordicsemi.android.nrftoolbox.ToolboxApplication;
import no.nordicsemi.android.nrftoolbox.csc.settings.SettingsFragment;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
public class CSCService extends BleProfileService implements CSCManagerCallbacks {
@SuppressWarnings("unused")
private static final String TAG = "CSCService";
public static final String BROADCAST_WHEEL_DATA = "no.nordicsemi.android.nrftoolbox.csc.BROADCAST_WHEEL_DATA";
@@ -59,15 +57,6 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
private static final String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.csc.ACTION_DISCONNECT";
private CSCManager mManager;
private int mFirstWheelRevolutions = -1;
private int mLastWheelRevolutions = -1;
private int mLastWheelEventTime = -1;
private float mWheelCadence = -1;
private int mLastCrankRevolutions = -1;
private int mLastCrankEventTime = -1;
private final static int NOTIFICATION_ID = 200;
private final static int OPEN_ACTIVITY_REQ = 0;
private final static int DISCONNECT_REQ = 1;
@@ -77,7 +66,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
/**
* This local binder is an interface for the bonded activity to operate with the RSC sensor
*/
public class CSCBinder extends LocalBinder {
class CSCBinder extends LocalBinder {
// empty
}
@@ -88,7 +77,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
@Override
protected BleManager<CSCManagerCallbacks> initializeManager() {
return mManager = new CSCManager(this);
return new CSCManager(this);
}
@Override
@@ -122,68 +111,22 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
}
@Override
public void onWheelMeasurementReceived(final BluetoothDevice device, final int wheelRevolutions, final int lastWheelEventTime) {
Logger.a(getLogSession(), "Wheel rev: " + wheelRevolutions + "\nLast wheel event time: " + lastWheelEventTime + " ms");
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final int circumference = Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_WHEEL_SIZE, String.valueOf(SettingsFragment.SETTINGS_WHEEL_SIZE_DEFAULT))); // [mm]
if (mFirstWheelRevolutions < 0)
mFirstWheelRevolutions = wheelRevolutions;
if (mLastWheelEventTime == lastWheelEventTime)
return;
if (mLastWheelRevolutions >= 0) {
float timeDifference;
if (lastWheelEventTime < mLastWheelEventTime)
timeDifference = (65535 + lastWheelEventTime - mLastWheelEventTime) / 1024.0f; // [s]
else
timeDifference = (lastWheelEventTime - mLastWheelEventTime) / 1024.0f; // [s]
final float distanceDifference = (wheelRevolutions - mLastWheelRevolutions) * circumference / 1000.0f; // [m]
final float totalDistance = (float) wheelRevolutions * (float) circumference / 1000.0f; // [m]
final float distance = (float) (wheelRevolutions - mFirstWheelRevolutions) * (float) circumference / 1000.0f; // [m]
final float speed = distanceDifference / timeDifference;
mWheelCadence = (wheelRevolutions - mLastWheelRevolutions) * 60.0f / timeDifference;
final Intent broadcast = new Intent(BROADCAST_WHEEL_DATA);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
broadcast.putExtra(EXTRA_SPEED, speed);
broadcast.putExtra(EXTRA_DISTANCE, distance);
broadcast.putExtra(EXTRA_TOTAL_DISTANCE, totalDistance);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
mLastWheelRevolutions = wheelRevolutions;
mLastWheelEventTime = lastWheelEventTime;
public void onDistanceChanged(final BluetoothDevice device, final float totalDistance, final float distance, final float speed) {
final Intent broadcast = new Intent(BROADCAST_WHEEL_DATA);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
broadcast.putExtra(EXTRA_SPEED, speed);
broadcast.putExtra(EXTRA_DISTANCE, distance);
broadcast.putExtra(EXTRA_TOTAL_DISTANCE, totalDistance);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onCrankMeasurementReceived(final BluetoothDevice device, int crankRevolutions, int lastCrankEventTime) {
Logger.a(getLogSession(), "Crank rev: " + crankRevolutions + "\nLast crank event time: " + lastCrankEventTime + " ms");
if (mLastCrankEventTime == lastCrankEventTime)
return;
if (mLastCrankRevolutions >= 0) {
float timeDifference;
if (lastCrankEventTime < mLastCrankEventTime)
timeDifference = (65535 + lastCrankEventTime - mLastCrankEventTime) / 1024.0f; // [s]
else
timeDifference = (lastCrankEventTime - mLastCrankEventTime) / 1024.0f; // [s]
final float crankCadence = (crankRevolutions - mLastCrankRevolutions) * 60.0f / timeDifference;
if (crankCadence > 0) {
final float gearRatio = mWheelCadence / crankCadence;
final Intent broadcast = new Intent(BROADCAST_CRANK_DATA);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
broadcast.putExtra(EXTRA_GEAR_RATIO, gearRatio);
broadcast.putExtra(EXTRA_CADENCE, (int) crankCadence);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
}
mLastCrankRevolutions = crankRevolutions;
mLastCrankEventTime = lastCrankEventTime;
public void onCrankDataChanged(final BluetoothDevice device, final float crankCadence, final float gearRatio) {
final Intent broadcast = new Intent(BROADCAST_CRANK_DATA);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
broadcast.putExtra(EXTRA_GEAR_RATIO, gearRatio);
broadcast.putExtra(EXTRA_CADENCE, (int) crankCadence);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
/**
@@ -238,5 +181,4 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
stopSelf();
}
};
}

View File

@@ -21,17 +21,15 @@
*/
package no.nordicsemi.android.nrftoolbox.parser;
import android.bluetooth.BluetoothGattCharacteristic;
import java.util.Locale;
import no.nordicsemi.android.ble.callback.Data;
public class CSCMeasurementParser {
private static final byte WHEEL_REV_DATA_PRESENT = 0x01; // 1 bit
private static final byte CRANK_REV_DATA_PRESENT = 0x02; // 1 bit
public static String parse(final BluetoothGattCharacteristic characteristic) {
public static String parse(final Data data) {
int offset = 0;
final int flags = characteristic.getValue()[offset]; // 1 byte
final int flags = data.getByte(offset); // 1 byte
offset += 1;
final boolean wheelRevPresent = (flags & WHEEL_REV_DATA_PRESENT) > 0;
@@ -40,31 +38,34 @@ public class CSCMeasurementParser {
int wheelRevolutions = 0;
int lastWheelEventTime = 0;
if (wheelRevPresent) {
wheelRevolutions = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, offset);
wheelRevolutions = data.getIntValue(Data.FORMAT_UINT32, offset);
offset += 4;
lastWheelEventTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset); // 1/1024 s
lastWheelEventTime = data.getIntValue(Data.FORMAT_UINT16, offset); // 1/1024 s
offset += 2;
}
int crankRevolutions = 0;
int lastCrankEventTime = 0;
if (crankRevPreset) {
crankRevolutions = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
crankRevolutions = data.getIntValue(Data.FORMAT_UINT16, offset);
offset += 2;
lastCrankEventTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
lastCrankEventTime = data.getIntValue(Data.FORMAT_UINT16, offset);
//offset += 2;
}
final StringBuilder builder = new StringBuilder();
if (wheelRevPresent) {
builder.append(String.format(Locale.US, "Wheel rev: %d,\n", wheelRevolutions));
builder.append(String.format(Locale.US, "Last wheel event time: %d ms,\n", lastWheelEventTime));
builder.append("Wheel rev: ").append(wheelRevolutions).append(",\n");
builder.append("Last wheel event time: ").append(lastWheelEventTime).append(",\n");
}
if (crankRevPreset) {
builder.append(String.format(Locale.US, "Crank rev: %d,\n", crankRevolutions));
builder.append(String.format(Locale.US, "Last crank event time: %d ms,\n", lastCrankEventTime));
builder.append("Crank rev: ").append(crankRevolutions).append(",\n");
builder.append("Last crank event time: ").append(lastCrankEventTime).append(",\n");
}
if (!wheelRevPresent && !crankRevPreset) {
builder.append("No wheel or crank data");
}
builder.setLength(builder.length() - 2);
return builder.toString();