From 1caa9ba38d09c584f1447f880da9352bc8649939 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Tue, 22 May 2018 15:20:15 +0200 Subject: [PATCH] RSC modified to use BLE Common lib --- .../parser/RSCMeasurementParser.java | 16 ++-- .../android/nrftoolbox/rsc/RSCActivity.java | 37 +++++---- .../android/nrftoolbox/rsc/RSCManager.java | 81 ++++++++----------- .../nrftoolbox/rsc/RSCManagerCallbacks.java | 11 +-- .../android/nrftoolbox/rsc/RSCService.java | 60 ++++++++++---- 5 files changed, 112 insertions(+), 93 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/parser/RSCMeasurementParser.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/parser/RSCMeasurementParser.java index f4bb6dcf..7f7ff96b 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/parser/RSCMeasurementParser.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/parser/RSCMeasurementParser.java @@ -21,18 +21,18 @@ */ package no.nordicsemi.android.nrftoolbox.parser; -import android.bluetooth.BluetoothGattCharacteristic; - import java.util.Locale; +import no.nordicsemi.android.ble.data.Data; + public class RSCMeasurementParser { private static final byte INSTANTANEOUS_STRIDE_LENGTH_PRESENT = 0x01; // 1 bit private static final byte TOTAL_DISTANCE_PRESENT = 0x02; // 1 bit private static final byte WALKING_OR_RUNNING_STATUS_BITS = 0x04; // 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.getValue()[offset]; // 1 byte offset += 1; final boolean islmPresent = (flags & INSTANTANEOUS_STRIDE_LENGTH_PRESENT) > 0; @@ -40,21 +40,21 @@ public class RSCMeasurementParser { final boolean running = (flags & WALKING_OR_RUNNING_STATUS_BITS) > 0; final boolean walking = !running; - final float instantaneousSpeed = (float) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset) / 256.0f; // 1/256 m/s + final float instantaneousSpeed = (float) data.getIntValue(Data.FORMAT_UINT16, offset) / 256.0f; // 1/256 m/s offset += 2; - final int instantaneousCadence = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset); + final int instantaneousCadence = data.getIntValue(Data.FORMAT_UINT8, offset); offset += 1; float instantaneousStrideLength = 0; if (islmPresent) { - instantaneousStrideLength = (float) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset) / 100.0f; // 1/100 m + instantaneousStrideLength = (float) data.getIntValue(Data.FORMAT_UINT16, offset) / 100.0f; // 1/100 m offset += 2; } float totalDistance = 0; if (tdPreset) { - totalDistance = (float) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, offset) / 10.0f; + totalDistance = (float) data.getIntValue(Data.FORMAT_UINT32, offset) / 10.0f; // offset += 4; } diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCActivity.java index 952aea0a..5123ad94 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCActivity.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCActivity.java @@ -53,6 +53,7 @@ public class RSCActivity extends BleProfileServiceReadyActivity { - private static final byte INSTANTANEOUS_STRIDE_LENGTH_PRESENT = 0x01; // 1 bit - private static final byte TOTAL_DISTANCE_PRESENT = 0x02; // 1 bit - private static final byte WALKING_OR_RUNNING_STATUS_BITS = 0x04; // 1 bit - +public class RSCManager extends BatteryManager { /** Running Speed and Cadence Measurement service UUID */ - public final static UUID RUNNING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001814-0000-1000-8000-00805f9b34fb"); + public static final UUID RUNNING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001814-0000-1000-8000-00805f9b34fb"); /** Running Speed and Cadence Measurement characteristic UUID */ private static final UUID RSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A53-0000-1000-8000-00805f9b34fb"); private BluetoothGattCharacteristic mRSCMeasurementCharacteristic; - public RSCManager(final Context context) { + RSCManager(final Context context) { super(context); } + @NonNull @Override - protected BleManagerGattCallback getGattCallback() { + protected BatteryManagerGattCallback getGattCallback() { return mGattCallback; } /** * BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc */ - private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() { + private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() { @Override - protected Deque initGatt(@NonNull final BluetoothGatt gatt) { - final LinkedList requests = new LinkedList<>(); - requests.add(Request.newEnableNotificationsRequest(mRSCMeasurementCharacteristic)); - return requests; + protected void initialize() { + super.initialize(); + setNotificationCallback(mRSCMeasurementCharacteristic) + .with(new RunningSpeedAndCadenceMeasurementDataCallback() { + @Override + public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) { + log(LogContract.Log.Level.APPLICATION, "\"" + RSCMeasurementParser.parse(data) + "\" received"); + super.onDataReceived(device, data); + } + + @Override + public void onRSCMeasurementReceived(@NonNull final BluetoothDevice device, final boolean running, + final float instantaneousSpeed, final int instantaneousCadence, + @Nullable final Integer strideLength, + @Nullable final Long totalDistance) { + mCallbacks.onRSCMeasurementReceived(device, running, instantaneousSpeed, + instantaneousCadence, strideLength, totalDistance); + } + }); + enableNotifications(mRSCMeasurementCharacteristic); } @Override @@ -81,43 +99,8 @@ public class RSCManager extends BleManager { @Override protected void onDeviceDisconnected() { + super.onDeviceDisconnected(); mRSCMeasurementCharacteristic = null; } - - @Override - public void onCharacteristicNotified(@NonNull final BluetoothGatt gatt, @NonNull final BluetoothGattCharacteristic characteristic) { - log(LogContract.Log.Level.APPLICATION, "\"" + RSCMeasurementParser.parse(characteristic) + "\" received"); - - // Decode the new data - int offset = 0; - final int flags = characteristic.getValue()[offset]; // 1 byte - offset += 1; - - final boolean islmPresent = (flags & INSTANTANEOUS_STRIDE_LENGTH_PRESENT) > 0; - final boolean tdPreset = (flags & TOTAL_DISTANCE_PRESENT) > 0; - final boolean running = (flags & WALKING_OR_RUNNING_STATUS_BITS) > 0; - - final float instantaneousSpeed = (float) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset) / 256.0f; // 1/256 m/s in [m/s] - offset += 2; - - final int instantaneousCadence = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset); // [SPM] - offset += 1; - - float instantaneousStrideLength = RSCManagerCallbacks.NOT_AVAILABLE; - if (islmPresent) { - instantaneousStrideLength = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset); // [cm] - offset += 2; - } - - float totalDistance = RSCManagerCallbacks.NOT_AVAILABLE; - if (tdPreset) { - totalDistance = (float) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, offset) / 10.0f; // 1/10 m in [m] - //offset += 4; - } - - // Notify listener about the new measurement - mCallbacks.onMeasurementReceived(gatt.getDevice(), instantaneousSpeed, instantaneousCadence, totalDistance, instantaneousStrideLength, - running ? RSCManagerCallbacks.ACTIVITY_RUNNING : RSCManagerCallbacks.ACTIVITY_WALKING); - } }; } diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCManagerCallbacks.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCManagerCallbacks.java index bafaba0e..1a06cd26 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCManagerCallbacks.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCManagerCallbacks.java @@ -21,14 +21,9 @@ */ package no.nordicsemi.android.nrftoolbox.rsc; -import android.bluetooth.BluetoothDevice; +import no.nordicsemi.android.ble.common.profile.rsc.RunningSpeedAndCadenceMeasurementCallback; +import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks; -import no.nordicsemi.android.ble.BleManagerCallbacks; +interface RSCManagerCallbacks extends BatteryManagerCallbacks, RunningSpeedAndCadenceMeasurementCallback { -public interface RSCManagerCallbacks extends BleManagerCallbacks { - int NOT_AVAILABLE = -1; - int ACTIVITY_WALKING = 0; - int ACTIVITY_RUNNING = 1; - - void onMeasurementReceived(final BluetoothDevice device, float speed, int cadence, float distance, float strideLen, int activity); } diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java index e3347afe..b7441a2b 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java @@ -31,8 +31,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; import no.nordicsemi.android.ble.BleManager; import no.nordicsemi.android.log.Logger; @@ -47,6 +50,7 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks public static final String BROADCAST_RSC_MEASUREMENT = "no.nordicsemi.android.nrftoolbox.rsc.BROADCAST_RSC_MEASUREMENT"; public static final String EXTRA_SPEED = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_SPEED"; public static final String EXTRA_CADENCE = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_CADENCE"; + public static final String EXTRA_STRIDE_LENGTH = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_STRIDE_LENGTH"; public static final String EXTRA_TOTAL_DISTANCE = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_TOTAL_DISTANCE"; public static final String EXTRA_ACTIVITY = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_ACTIVITY"; @@ -54,6 +58,9 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks public static final String EXTRA_STRIDES = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_STRIDES"; public static final String EXTRA_DISTANCE = "no.nordicsemi.android.nrftoolbox.rsc.EXTRA_DISTANCE"; + public static final String BROADCAST_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.BROADCAST_BATTERY_LEVEL"; + public static final String EXTRA_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.EXTRA_BATTERY_LEVEL"; + private final static String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.rsc.ACTION_DISCONNECT"; private RSCManager mManager; @@ -61,9 +68,9 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks /** The last value of a cadence */ private float mCadence; /** Trip distance in cm */ - private float mDistance; + private long mDistance; /** Stride length in cm */ - private float mStrideLength; + private Integer mStrideLength; /** Number of steps in the trip */ private int mStepsNumber; private boolean mTaskInProgress; @@ -76,9 +83,9 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks private final LocalBinder mBinder = new RSCBinder(); /** - * This local binder is an interface for the bound activity to operate with the RSC sensor + * This local binder is an interface for the bound activity to operate with the RSC sensor. */ - public class RSCBinder extends LocalBinder { + class RSCBinder extends LocalBinder { // empty } @@ -114,10 +121,21 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks protected void onRebind() { // when the activity rebinds to the service, remove the notification cancelNotification(); + + if (isConnected()) { + // This method will read the Battery Level value, if possible and then try to enable battery notifications (if it has NOTIFY property). + // If the Battery Level characteristic has only the NOTIFY property, it will only try to enable notifications. + mManager.readBatteryLevelCharacteristic(); + } } @Override protected void onUnbind() { + // When we are connected, but the application is not open, we are not really interested in battery level notifications. + // But we will still be receiving other values, if enabled. + if (isConnected()) + mManager.disableBatteryLevelCharacteristicNotifications(); + // when the activity closes we need to show the notification that user is connected to the sensor createNotification(R.string.rsc_notification_connected_message, 0); } @@ -129,14 +147,14 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks return; mStepsNumber++; - mDistance += mStrideLength; + mDistance += mStrideLength; // [cm] final Intent broadcast = new Intent(BROADCAST_STRIDES_UPDATE); broadcast.putExtra(EXTRA_STRIDES, mStepsNumber); broadcast.putExtra(EXTRA_DISTANCE, mDistance); LocalBroadcastManager.getInstance(RSCService.this).sendBroadcast(broadcast); if (mCadence > 0) { - final long interval = (long) (1000.0f * 65.0f / mCadence); // 60s + 5s for calibration in milliseconds + final long interval = (long) (1000.0f * 60.0f / mCadence); mHandler.postDelayed(mUpdateStridesTask, interval); } else { mTaskInProgress = false; @@ -145,26 +163,40 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks }; @Override - public void onMeasurementReceived(final BluetoothDevice device, final float speed, final int cadence, final float totalDistance, final float strideLen, final int activity) { + public void onRSCMeasurementReceived(@NonNull final BluetoothDevice device, final boolean running, + final float instantaneousSpeed, final int instantaneousCadence, + @Nullable final Integer strideLength, + @Nullable final Long totalDistance) { final Intent broadcast = new Intent(BROADCAST_RSC_MEASUREMENT); broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice()); - broadcast.putExtra(EXTRA_SPEED, speed); - broadcast.putExtra(EXTRA_CADENCE, cadence); + broadcast.putExtra(EXTRA_SPEED, instantaneousSpeed); + broadcast.putExtra(EXTRA_CADENCE, instantaneousCadence); + broadcast.putExtra(EXTRA_STRIDE_LENGTH, strideLength); broadcast.putExtra(EXTRA_TOTAL_DISTANCE, totalDistance); - broadcast.putExtra(EXTRA_ACTIVITY, activity); + broadcast.putExtra(EXTRA_ACTIVITY, running); LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast); // Start strides counter if not in progress - mCadence = cadence; - mStrideLength = strideLen; - if (!mTaskInProgress && cadence > 0) { + mCadence = instantaneousCadence; + if (strideLength != null) { + mStrideLength = strideLength; + } + if (!mTaskInProgress && strideLength != null && instantaneousCadence > 0) { mTaskInProgress = true; - final long interval = (long) (1000.0f * 65.0f / mCadence); // 60s + 5s for calibration in milliseconds + final long interval = (long) (1000.0f * 60.0f / mCadence); mHandler.postDelayed(mUpdateStridesTask, interval); } } + @Override + public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) { + final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL); + broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice()); + broadcast.putExtra(EXTRA_BATTERY_LEVEL, value); + LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast); + } + /** * Creates the notification *