mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2025-12-21 16:34:23 +01:00
Migrating HRS to use new BleManager API
This commit is contained in:
@@ -28,11 +28,13 @@ import android.graphics.Point;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.achartengine.GraphicalView;
|
import org.achartengine.GraphicalView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import no.nordicsemi.android.ble.BleManager;
|
import no.nordicsemi.android.ble.BleManager;
|
||||||
@@ -53,8 +55,6 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
private final static String GRAPH_COUNTER = "graph_counter";
|
private final static String GRAPH_COUNTER = "graph_counter";
|
||||||
private final static String HR_VALUE = "hr_value";
|
private final static String HR_VALUE = "hr_value";
|
||||||
|
|
||||||
private final static int MAX_HR_VALUE = 65535;
|
|
||||||
private final static int MIN_POSITIVE_VALUE = 0;
|
|
||||||
private final static int REFRESH_INTERVAL = 1000; // 1 second interval
|
private final static int REFRESH_INTERVAL = 1000; // 1 second interval
|
||||||
|
|
||||||
private Handler mHandler = new Handler();
|
private Handler mHandler = new Handler();
|
||||||
@@ -64,6 +64,7 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
private GraphicalView mGraphView;
|
private GraphicalView mGraphView;
|
||||||
private LineGraphView mLineGraph;
|
private LineGraphView mLineGraph;
|
||||||
private TextView mHRSValue, mHRSPosition;
|
private TextView mHRSValue, mHRSPosition;
|
||||||
|
private TextView mBatteryLevelView;
|
||||||
|
|
||||||
private int mHrmValue = 0;
|
private int mHrmValue = 0;
|
||||||
private int mCounter = 0;
|
private int mCounter = 0;
|
||||||
@@ -78,6 +79,7 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
mLineGraph = LineGraphView.getLineGraphView();
|
mLineGraph = LineGraphView.getLineGraphView();
|
||||||
mHRSValue = findViewById(R.id.text_hrs_value);
|
mHRSValue = findViewById(R.id.text_hrs_value);
|
||||||
mHRSPosition = findViewById(R.id.text_hrs_position);
|
mHRSPosition = findViewById(R.id.text_hrs_position);
|
||||||
|
mBatteryLevelView = findViewById(R.id.battery);
|
||||||
showGraph();
|
showGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,26 +185,6 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHRSValueOnView(final int value) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
if (value >= MIN_POSITIVE_VALUE && value <= MAX_HR_VALUE) {
|
|
||||||
mHRSValue.setText(Integer.toString(value));
|
|
||||||
} else {
|
|
||||||
mHRSValue.setText(R.string.not_available_value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setHRSPositionOnView(final String position) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
if (position != null) {
|
|
||||||
mHRSPosition.setText(position);
|
|
||||||
} else {
|
|
||||||
mHRSPosition.setText(R.string.not_available);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||||
// this may notify user or show some views
|
// this may notify user or show some views
|
||||||
@@ -214,14 +196,28 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onHRSensorPositionFound(final BluetoothDevice device, final String position) {
|
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||||
setHRSPositionOnView(position);
|
runOnUiThread(() -> mBatteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onHRValueReceived(final BluetoothDevice device, int value) {
|
public void onBodySensorLocationReceived(@NonNull final BluetoothDevice device, final int sensorLocation) {
|
||||||
mHrmValue = value;
|
runOnUiThread(() -> {
|
||||||
setHRSValueOnView(mHrmValue);
|
if (sensorLocation >= SENSOR_LOCATION_FIRST && sensorLocation <= SENSOR_LOCATION_LAST) {
|
||||||
|
mHRSPosition.setText(getResources().getStringArray(R.array.hrs_locations)[sensorLocation]);
|
||||||
|
} else {
|
||||||
|
mHRSPosition.setText(R.string.hrs_location_other);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHeartRateMeasurementReceived(@NonNull final BluetoothDevice device, final int heartRate,
|
||||||
|
@Nullable final Boolean contactDetected,
|
||||||
|
@Nullable final Integer energyExpanded,
|
||||||
|
@Nullable final List<Integer> rrIntervals) {
|
||||||
|
mHrmValue = heartRate;
|
||||||
|
runOnUiThread(() -> mHRSValue.setText(getString(R.string.hrs_value, heartRate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -230,6 +226,7 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
mHRSValue.setText(R.string.not_available_value);
|
mHRSValue.setText(R.string.not_available_value);
|
||||||
mHRSPosition.setText(R.string.not_available);
|
mHRSPosition.setText(R.string.not_available);
|
||||||
|
mBatteryLevelView.setText(R.string.not_available);
|
||||||
stopShowGraph();
|
stopShowGraph();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -238,6 +235,7 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
|||||||
protected void setDefaultUI() {
|
protected void setDefaultUI() {
|
||||||
mHRSValue.setText(R.string.not_available_value);
|
mHRSValue.setText(R.string.not_available_value);
|
||||||
mHRSPosition.setText(R.string.not_available);
|
mHRSPosition.setText(R.string.not_available);
|
||||||
|
mBatteryLevelView.setText(R.string.not_available);
|
||||||
clearGraph();
|
clearGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,33 +21,37 @@
|
|||||||
*/
|
*/
|
||||||
package no.nordicsemi.android.nrftoolbox.hrs;
|
package no.nordicsemi.android.nrftoolbox.hrs;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
import android.bluetooth.BluetoothGattService;
|
import android.bluetooth.BluetoothGattService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Deque;
|
import java.util.List;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import no.nordicsemi.android.ble.BleManager;
|
import no.nordicsemi.android.ble.common.callback.hr.BodySensorLocationDataCallback;
|
||||||
import no.nordicsemi.android.ble.Request;
|
import no.nordicsemi.android.ble.common.callback.hr.HeartRateMeasurementDataCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
import no.nordicsemi.android.log.LogContract;
|
import no.nordicsemi.android.log.LogContract;
|
||||||
import no.nordicsemi.android.nrftoolbox.R;
|
import no.nordicsemi.android.nrftoolbox.battery.BatteryManager;
|
||||||
import no.nordicsemi.android.nrftoolbox.parser.BodySensorLocationParser;
|
import no.nordicsemi.android.nrftoolbox.parser.BodySensorLocationParser;
|
||||||
import no.nordicsemi.android.nrftoolbox.parser.HeartRateMeasurementParser;
|
import no.nordicsemi.android.nrftoolbox.parser.HeartRateMeasurementParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HRSManager class performs BluetoothGatt operations for connection, service discovery, enabling notification and reading characteristics. All operations required to connect to device with BLE HR
|
* HRSManager class performs BluetoothGatt operations for connection, service discovery,
|
||||||
* Service and reading heart rate values are performed here. HRSActivity implements HRSManagerCallbacks in order to receive callbacks of BluetoothGatt operations
|
* enabling notification and reading characteristics.
|
||||||
|
* All operations required to connect to device with BLE Heart Rate Service and reading
|
||||||
|
* heart rate values are performed here.
|
||||||
*/
|
*/
|
||||||
public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||||
public final static UUID HR_SERVICE_UUID = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb");
|
public static final UUID HR_SERVICE_UUID = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb");
|
||||||
private static final UUID HR_SENSOR_LOCATION_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb");
|
private static final UUID HR_SENSOR_LOCATION_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb");
|
||||||
private static final UUID HR_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb");
|
private static final UUID HR_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb");
|
||||||
|
|
||||||
private BluetoothGattCharacteristic mHRCharacteristic, mHRLocationCharacteristic;
|
private BluetoothGattCharacteristic mHeartRateCharacteristic, mBodySensorLocationCharacteristic;
|
||||||
|
|
||||||
private static HRSManager managerInstance = null;
|
private static HRSManager managerInstance = null;
|
||||||
|
|
||||||
@@ -61,93 +65,83 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
|||||||
return managerInstance;
|
return managerInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HRSManager(final Context context) {
|
private HRSManager(final Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected BleManagerGattCallback getGattCallback() {
|
protected BatteryManagerGattCallback getGattCallback() {
|
||||||
return mGattCallback;
|
return mGattCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving notification, etc
|
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving notification, etc
|
||||||
*/
|
*/
|
||||||
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
|
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Deque<Request> initGatt(@NonNull final BluetoothGatt gatt) {
|
protected void initialize() {
|
||||||
final LinkedList<Request> requests = new LinkedList<>();
|
super.initialize();
|
||||||
if (mHRLocationCharacteristic != null)
|
readCharacteristic(mBodySensorLocationCharacteristic)
|
||||||
requests.add(Request.newReadRequest(mHRLocationCharacteristic));
|
.with(new BodySensorLocationDataCallback() {
|
||||||
requests.add(Request.newEnableNotificationsRequest(mHRCharacteristic));
|
@Override
|
||||||
return requests;
|
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||||
|
log(LogContract.Log.Level.APPLICATION, "\"" + BodySensorLocationParser.parse(data) + "\" received");
|
||||||
|
super.onDataReceived(device, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBodySensorLocationReceived(@NonNull final BluetoothDevice device,
|
||||||
|
final int sensorLocation) {
|
||||||
|
mCallbacks.onBodySensorLocationReceived(device, sensorLocation);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Body Sensor Location characteristic not found"));
|
||||||
|
setNotificationCallback(mHeartRateCharacteristic)
|
||||||
|
.with(new HeartRateMeasurementDataCallback() {
|
||||||
|
@Override
|
||||||
|
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||||
|
log(LogContract.Log.Level.APPLICATION, "\"" + HeartRateMeasurementParser.parse(data) + "\" received");
|
||||||
|
super.onDataReceived(device, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHeartRateMeasurementReceived(@NonNull final BluetoothDevice device,
|
||||||
|
final int heartRate,
|
||||||
|
@Nullable final Boolean contactDetected,
|
||||||
|
@Nullable final Integer energyExpanded,
|
||||||
|
@Nullable final List<Integer> rrIntervals) {
|
||||||
|
mCallbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
enableNotifications(mHeartRateCharacteristic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||||
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
mHRCharacteristic = service.getCharacteristic(HR_CHARACTERISTIC_UUID);
|
mHeartRateCharacteristic = service.getCharacteristic(HR_CHARACTERISTIC_UUID);
|
||||||
}
|
}
|
||||||
return mHRCharacteristic != null;
|
return mHeartRateCharacteristic != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
|
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||||
|
super.isOptionalServiceSupported(gatt);
|
||||||
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
mHRLocationCharacteristic = service.getCharacteristic(HR_SENSOR_LOCATION_CHARACTERISTIC_UUID);
|
mBodySensorLocationCharacteristic = service.getCharacteristic(HR_SENSOR_LOCATION_CHARACTERISTIC_UUID);
|
||||||
}
|
}
|
||||||
return mHRLocationCharacteristic != null;
|
return mBodySensorLocationCharacteristic != null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCharacteristicRead(@NonNull final BluetoothGatt gatt, @NonNull final BluetoothGattCharacteristic characteristic) {
|
|
||||||
log(LogContract.Log.Level.APPLICATION, "\"" + BodySensorLocationParser.parse(characteristic) + "\" received");
|
|
||||||
|
|
||||||
final String sensorPosition = getBodySensorPosition(characteristic.getValue()[0]);
|
|
||||||
//This will send callback to HRSActivity when HR sensor position on body is found in HR device
|
|
||||||
mCallbacks.onHRSensorPositionFound(gatt.getDevice(), sensorPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDeviceDisconnected() {
|
protected void onDeviceDisconnected() {
|
||||||
mHRLocationCharacteristic = null;
|
super.onDeviceDisconnected();
|
||||||
mHRCharacteristic = null;
|
mBodySensorLocationCharacteristic = null;
|
||||||
}
|
mHeartRateCharacteristic = null;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCharacteristicNotified(@NonNull final BluetoothGatt gatt, @NonNull final BluetoothGattCharacteristic characteristic) {
|
|
||||||
log(LogContract.Log.Level.APPLICATION, "\"" + HeartRateMeasurementParser.parse(characteristic) + "\" received");
|
|
||||||
|
|
||||||
int hrValue;
|
|
||||||
if (isHeartRateInUINT16(characteristic.getValue()[0])) {
|
|
||||||
hrValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 1);
|
|
||||||
} else {
|
|
||||||
hrValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);
|
|
||||||
}
|
|
||||||
//This will send callback to HRSActivity when new HR value is received from HR device
|
|
||||||
mCallbacks.onHRValueReceived(gatt.getDevice(), hrValue);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will decode and return Heart rate sensor position on body
|
|
||||||
*/
|
|
||||||
private String getBodySensorPosition(final byte bodySensorPositionValue) {
|
|
||||||
final String[] locations = getContext().getResources().getStringArray(R.array.hrs_locations);
|
|
||||||
if (bodySensorPositionValue > locations.length)
|
|
||||||
return getContext().getString(R.string.hrs_location_other);
|
|
||||||
return locations[bodySensorPositionValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will check if Heart rate value is in 8 bits or 16 bits
|
|
||||||
*/
|
|
||||||
private boolean isHeartRateInUINT16(final byte value) {
|
|
||||||
return ((value & 0x01) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,27 +21,10 @@
|
|||||||
*/
|
*/
|
||||||
package no.nordicsemi.android.nrftoolbox.hrs;
|
package no.nordicsemi.android.nrftoolbox.hrs;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import no.nordicsemi.android.ble.common.profile.hr.BodySensorLocationCallback;
|
||||||
|
import no.nordicsemi.android.ble.common.profile.hr.HeartRateMeasurementCallback;
|
||||||
|
import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks;
|
||||||
|
|
||||||
import no.nordicsemi.android.ble.BleManagerCallbacks;
|
interface HRSManagerCallbacks extends BatteryManagerCallbacks, BodySensorLocationCallback, HeartRateMeasurementCallback {
|
||||||
|
|
||||||
public interface HRSManagerCallbacks extends BleManagerCallbacks {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the sensor position information has been obtained from the sensor
|
|
||||||
*
|
|
||||||
* @param device the bluetooth device from which the value was obtained
|
|
||||||
* @param position
|
|
||||||
* the sensor position
|
|
||||||
*/
|
|
||||||
void onHRSensorPositionFound(final BluetoothDevice device, String position);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when new Heart Rate value has been obtained from the sensor
|
|
||||||
*
|
|
||||||
* @param device the bluetooth device from which the value was obtained
|
|
||||||
* @param value
|
|
||||||
* the new value
|
|
||||||
*/
|
|
||||||
void onHRValueReceived(final BluetoothDevice device, int value);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,36 +21,22 @@
|
|||||||
*/
|
*/
|
||||||
package no.nordicsemi.android.nrftoolbox.parser;
|
package no.nordicsemi.android.nrftoolbox.parser;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
public class BodySensorLocationParser {
|
public class BodySensorLocationParser {
|
||||||
|
|
||||||
public static String parse(final BluetoothGattCharacteristic characteristic) {
|
public static String parse(final Data data) {
|
||||||
final int value = unsignedByteToInt(characteristic.getValue()[0]);
|
final int value = data.getIntValue(Data.FORMAT_UINT8, 0);
|
||||||
|
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 6:
|
case 6: return "Foot";
|
||||||
return "Foot";
|
case 5: return "Ear Lobe";
|
||||||
case 5:
|
case 4: return "Hand";
|
||||||
return "Ear Lobe";
|
case 3: return "Finger";
|
||||||
case 4:
|
case 2: return "Wrist";
|
||||||
return "Hand";
|
case 1: return "Chest";
|
||||||
case 3:
|
case 0:
|
||||||
return "Finger";
|
default: return "Other";
|
||||||
case 2:
|
|
||||||
return "Wrist";
|
|
||||||
case 1:
|
|
||||||
return "Chest";
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
return "Other";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a signed byte to an unsigned int.
|
|
||||||
*/
|
|
||||||
private static int unsignedByteToInt(byte b) {
|
|
||||||
return b & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,21 +21,21 @@
|
|||||||
*/
|
*/
|
||||||
package no.nordicsemi.android.nrftoolbox.parser;
|
package no.nordicsemi.android.nrftoolbox.parser;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
public class HeartRateMeasurementParser {
|
public class HeartRateMeasurementParser {
|
||||||
private static final byte HEART_RATE_VALUE_FORMAT = 0x01; // 1 bit
|
private static final byte HEART_RATE_VALUE_FORMAT = 0x01; // 1 bit
|
||||||
private static final byte SENSOR_CONTACT_STATUS = 0x06; // 2 bits
|
private static final byte SENSOR_CONTACT_STATUS = 0x06; // 2 bits
|
||||||
private static final byte ENERGY_EXPANDED_STATUS = 0x08; // 1 bit
|
private static final byte ENERGY_EXPANDED_STATUS = 0x08; // 1 bit
|
||||||
private static final byte RR_INTERVAL = 0x10; // 1 bit
|
private static final byte RR_INTERVAL = 0x10; // 1 bit
|
||||||
|
|
||||||
public static String parse(final BluetoothGattCharacteristic characteristic) {
|
public static String parse(final Data data) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
final int flags = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
final int flags = data.getIntValue(Data.FORMAT_UINT8, offset++);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* false Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)
|
* false Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)
|
||||||
@@ -64,21 +64,21 @@ public class HeartRateMeasurementParser {
|
|||||||
final boolean rrIntervalStatus = (flags & RR_INTERVAL) > 0;
|
final boolean rrIntervalStatus = (flags & RR_INTERVAL) > 0;
|
||||||
|
|
||||||
// heart rate value is 8 or 16 bit long
|
// heart rate value is 8 or 16 bit long
|
||||||
int heartRateValue = characteristic.getIntValue(value16bit ? BluetoothGattCharacteristic.FORMAT_UINT16 : BluetoothGattCharacteristic.FORMAT_UINT8, offset++); // bits per minute
|
int heartRateValue = data.getIntValue(value16bit ? Data.FORMAT_UINT16 : Data.FORMAT_UINT8, offset++); // bits per minute
|
||||||
if (value16bit)
|
if (value16bit)
|
||||||
offset++;
|
offset++;
|
||||||
|
|
||||||
// energy expanded value is present if a flag was set
|
// energy expanded value is present if a flag was set
|
||||||
int energyExpanded = -1;
|
int energyExpanded = -1;
|
||||||
if (energyExpandedStatus)
|
if (energyExpandedStatus)
|
||||||
energyExpanded = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
energyExpanded = data.getIntValue(Data.FORMAT_UINT16, offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
|
||||||
// RR-interval is set when a flag is set
|
// RR-interval is set when a flag is set
|
||||||
final List<Float> rrIntervals = new ArrayList<>();
|
final List<Float> rrIntervals = new ArrayList<>();
|
||||||
if (rrIntervalStatus) {
|
if (rrIntervalStatus) {
|
||||||
for (int o = offset; o < characteristic.getValue().length; o += 2) {
|
for (int o = offset; o < data.getValue().length; o += 2) {
|
||||||
final int units = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, o);
|
final int units = data.getIntValue(Data.FORMAT_UINT16, o);
|
||||||
rrIntervals.add(units * 1000.0f / 1024.0f); // RR interval is in [1/1024s]
|
rrIntervals.add(units * 1000.0f / 1024.0f); // RR interval is in [1/1024s]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
<dimen name="hrs_feature_title_long_margin">-152dp</dimen>
|
<dimen name="hrs_feature_title_long_margin">-152dp</dimen>
|
||||||
|
|
||||||
<string name="hrs_default_name">DEFAULT HRM</string>
|
<string name="hrs_default_name">DEFAULT HRM</string>
|
||||||
|
<string name="hrs_value">%d</string>
|
||||||
<string name="hrs_value_unit">bpm</string>
|
<string name="hrs_value_unit">bpm</string>
|
||||||
<string name="hrs_position_label">sensor position</string>
|
<string name="hrs_position_label">sensor position</string>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user