Major refactoring: enqueue() method added to Request.

This commit is contained in:
Aleksander Nowakowski
2018-06-18 17:28:23 +02:00
parent 906ec36f08
commit 15c82a8c56
13 changed files with 206 additions and 188 deletions

View File

@@ -17,7 +17,8 @@ import no.nordicsemi.android.log.LogContract;
/**
* The Ble Manager with Battery Service support.
* @param <T> The profile callbacks type
*
* @param <T> The profile callbacks type.
* @see BleManager
*/
@SuppressWarnings("WeakerAccess")
@@ -62,7 +63,8 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
if (isConnected()) {
readCharacteristic(mBatteryLevelCharacteristic)
.with(mBatteryLevelDataCallback)
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING,"Battery Level characteristic not found"))
.enqueue();
}
}
@@ -73,7 +75,8 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
.with(mBatteryLevelDataCallback);
enableNotifications(mBatteryLevelCharacteristic)
.done(device -> log(LogContract.Log.Level.INFO, "Battery Level notifications enabled"))
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found"))
.enqueue();
}
}
@@ -83,7 +86,8 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
public void disableBatteryLevelCharacteristicNotifications() {
if (isConnected()) {
disableNotifications(mBatteryLevelCharacteristic)
.done(device -> log(LogContract.Log.Level.INFO, "Battery Level notifications disabled"));
.done(device -> log(LogContract.Log.Level.INFO, "Battery Level notifications disabled"))
.enqueue();
}
}

View File

@@ -121,7 +121,8 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
final int unit, @Nullable final Float pulseRate,
@Nullable final Integer userID, @Nullable final BPMStatus status,
@Nullable final Calendar calendar) {
mCallbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic, meanArterialPressure, unit, pulseRate, userID, status, calendar);
mCallbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic,
meanArterialPressure, unit, pulseRate, userID, status, calendar);
}
@Override
@@ -130,8 +131,8 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
}
});
enableNotifications(mICPCharacteristic);
enableIndications(mBPMCharacteristic);
enableNotifications(mICPCharacteristic).enqueue();
enableIndications(mBPMCharacteristic).enqueue();
}
@Override

View File

@@ -48,19 +48,13 @@ import no.nordicsemi.android.nrftoolbox.parser.CGMSpecificOpsControlPointParser;
import no.nordicsemi.android.nrftoolbox.parser.RecordAccessControlPointParser;
public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
private static final String TAG = "CGMSManager";
/**
* Cycling Speed and Cadence service UUID
*/
/** Cycling Speed and Cadence service UUID. */
public static final UUID CGMS_UUID = UUID.fromString("0000181F-0000-1000-8000-00805f9b34fb");
private static final UUID CGM_STATUS_UUID = UUID.fromString("00002AA9-0000-1000-8000-00805f9b34fb");
private static final UUID CGM_FEAURE_UUID = UUID.fromString("00002AA8-0000-1000-8000-00805f9b34fb");
private static final UUID CGM_FEATURE_UUID = UUID.fromString("00002AA8-0000-1000-8000-00805f9b34fb");
private static final UUID CGM_MEASUREMENT_UUID = UUID.fromString("00002AA7-0000-1000-8000-00805f9b34fb");
private static final UUID CGM_OPS_CONTROL_POINT_UUID = UUID.fromString("00002AAC-0000-1000-8000-00805f9b34fb");
/**
* Record Access Control Point characteristic UUID
*/
/** Record Access Control Point characteristic UUID. */
private static final UUID RACP_UUID = UUID.fromString("00002A52-0000-1000-8000-00805f9b34fb");
private BluetoothGattCharacteristic mCGMStatusCharacteristic;
@@ -111,7 +105,9 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
mSecured = features.e2eCrcSupported;
log(LogContract.Log.Level.APPLICATION, "E2E CRC feature " + (mSecured ? "supported" : "not supported"));
}
}).fail((device, status) -> log(LogContract.Log.Level.WARNING, "Could not read CGM Feature characteristic"));
})
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Could not read CGM Feature characteristic"))
.enqueue();
// Check if the session is already started. This is not supported in the experimental CGMS from the SDK.
readCharacteristic(mCGMStatusCharacteristic)
@@ -123,7 +119,9 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
log(LogContract.Log.Level.APPLICATION, "Session already started");
}
}
}).fail((device, status) -> log(LogContract.Log.Level.WARNING, "Could not read CGM Status characteristic"));
})
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Could not read CGM Status characteristic"))
.enqueue();
// Set notification and indication callbacks
setNotificationCallback(mCGMMeasurementCharacteristic)
@@ -135,7 +133,13 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onContinuousGlucoseMeasurementReceived(@NonNull final BluetoothDevice device, final float glucoseConcentration, @Nullable final Float cgmTrend, @Nullable final Float cgmQuality, final CGMStatus status, final int timeOffset, final boolean secured) {
public void onContinuousGlucoseMeasurementReceived(@NonNull final BluetoothDevice device,
final float glucoseConcentration,
@Nullable final Float cgmTrend,
@Nullable final Float cgmQuality,
final CGMStatus status,
final int timeOffset,
final boolean secured) {
// If the CGM Status characteristic has not been read and the session was already started before,
// estimate the Session Start Time by subtracting timeOffset minutes from the current timestamp.
if (mSessionStartTime == 0 && !mRecordAccessRequestInProgress) {
@@ -151,7 +155,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onContinuousGlucoseMeasurementReceivedWithCrcError(@NonNull final BluetoothDevice device, @NonNull final Data data) {
public void onContinuousGlucoseMeasurementReceivedWithCrcError(@NonNull final BluetoothDevice device,
@NonNull final Data data) {
log(LogContract.Log.Level.WARNING, "Continuous Glucose Measurement record received with CRC error");
}
});
@@ -165,7 +170,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onCGMSpecificOpsOperationCompleted(@NonNull final BluetoothDevice device, final int requestCode, final boolean secured) {
public void onCGMSpecificOpsOperationCompleted(@NonNull final BluetoothDevice device,
final int requestCode, final boolean secured) {
switch (requestCode) {
case CGM_OP_CODE_START_SESSION:
mSessionStartTime = System.currentTimeMillis();
@@ -176,14 +182,19 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
}
@Override
public void onCGMSpecificOpsOperationError(@NonNull final BluetoothDevice device, final int requestCode, final int errorCode, final boolean secured) {
@SuppressWarnings("StatementWithEmptyBody")
@Override
public void onCGMSpecificOpsOperationError(@NonNull final BluetoothDevice device,
final int requestCode, final int errorCode,
final boolean secured) {
switch (requestCode) {
case CGM_OP_CODE_START_SESSION:
if (errorCode == CGM_ERROR_PROCEDURE_NOT_COMPLETED) {
// Session was already started before.
// Looks like the CGM Status characteristic has not been read, otherwise we would have got the Session Start Time before.
// The Session Start Time will be calculated when a next CGM packet is received based on it's Time Offset.
// Looks like the CGM Status characteristic has not been read,
// otherwise we would have got the Session Start Time before.
// The Session Start Time will be calculated when a next CGM
// packet is received based on it's Time Offset.
}
case CGM_OP_CODE_STOP_SESSION:
mSessionStartTime = 0;
@@ -192,7 +203,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onCGMSpecificOpsResponseReceivedWithCrcError(@NonNull final BluetoothDevice device, @NonNull final Data data) {
public void onCGMSpecificOpsResponseReceivedWithCrcError(@NonNull final BluetoothDevice device,
@NonNull final Data data) {
log(LogContract.Log.Level.ERROR, "Request failed: CRC error");
}
});
@@ -219,7 +231,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device, final int requestCode) {
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device,
final int requestCode) {
mRecordAccessRequestInProgress = false;
mCallbacks.onOperationCompleted(device);
}
@@ -230,9 +243,11 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
if (numberOfRecords > 0) {
if (mRecords.size() > 0) {
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber));
writeCharacteristic(mRecordAccessControlPointCharacteristic,
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber));
} else {
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportAllStoredRecords());
writeCharacteristic(mRecordAccessControlPointCharacteristic,
RecordAccessControlPointData.reportAllStoredRecords());
}
} else {
mRecordAccessRequestInProgress = false;
@@ -241,7 +256,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
@Override
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device, final int requestCode, final int errorCode) {
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device,
final int requestCode, final int errorCode) {
log(LogContract.Log.Level.WARNING, "Record Access operation failed (error " + errorCode + ")");
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
mCallbacks.onOperationNotSupported(device);
@@ -253,17 +269,21 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
// Enable notifications and indications
enableNotifications(mCGMMeasurementCharacteristic)
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable Continuous Glucose Measurement notifications (" + status + ")"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable Continuous Glucose Measurement notifications (" + status + ")"))
.enqueue();
enableIndications(mCGMSpecificOpsControlPointCharacteristic)
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable CGM Specific Ops Control Point indications notifications (" + status + ")"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable CGM Specific Ops Control Point indications notifications (" + status + ")"))
.enqueue();
enableIndications(mRecordAccessControlPointCharacteristic)
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enabled Record Access Control Point indications (error " + status + ")"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enabled Record Access Control Point indications (error " + status + ")"))
.enqueue();
// Start Continuous Glucose session if hasn't been started before
if (mSessionStartTime == 0L) {
writeCharacteristic(mCGMSpecificOpsControlPointCharacteristic, CGMSpecificOpsControlPointData.startSession(mSecured))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + CGMSpecificOpsControlPointParser.parse(data) + "\" sent"))
.fail((device, status) -> log(LogContract.Log.Level.ERROR, "Failed to start session (error " + status + ")"));
.fail((device, status) -> log(LogContract.Log.Level.ERROR, "Failed to start session (error " + status + ")"))
.enqueue();
}
}
@@ -272,12 +292,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
final BluetoothGattService service = gatt.getService(CGMS_UUID);
if (service != null) {
mCGMStatusCharacteristic = service.getCharacteristic(CGM_STATUS_UUID);
mCGMFeatureCharacteristic = service.getCharacteristic(CGM_FEAURE_UUID);
mCGMFeatureCharacteristic = service.getCharacteristic(CGM_FEATURE_UUID);
mCGMMeasurementCharacteristic = service.getCharacteristic(CGM_MEASUREMENT_UUID);
mCGMSpecificOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
mRecordAccessControlPointCharacteristic = service.getCharacteristic(RACP_UUID);
}
return mCGMMeasurementCharacteristic != null && mCGMSpecificOpsControlPointCharacteristic != null && mRecordAccessControlPointCharacteristic != null;
return mCGMMeasurementCharacteristic != null
&& mCGMSpecificOpsControlPointCharacteristic != null
&& mRecordAccessControlPointCharacteristic != null;
}
@Override
@@ -307,8 +329,9 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
}
/**
* Sends the request to obtain the last (most recent) record from glucose device. The data will be returned to Glucose Measurement characteristic as a notification followed by Record Access
* Control Point indication with status code Success or other in case of error.
* Sends the request to obtain the last (most recent) record from glucose device.
* The data will be returned to Glucose Measurement characteristic as a notification followed by
* Record Access Control Point indication with status code Success or other in case of error.
*/
public void getLastRecord() {
if (mRecordAccessControlPointCharacteristic == null)
@@ -318,13 +341,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
mCallbacks.onOperationStarted(getBluetoothDevice());
mRecordAccessRequestInProgress = true;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
* Sends the request to obtain the first (oldest) record from glucose device.
* The data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control
* Point indication with status code Success or other in case of error.
* The data will be returned to Glucose Measurement characteristic as a notification followed by
* Record Access Control Point indication with status code Success or other in case of error.
*/
public void getFirstRecord() {
if (mRecordAccessControlPointCharacteristic == null)
@@ -334,7 +358,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
mCallbacks.onOperationStarted(getBluetoothDevice());
mRecordAccessRequestInProgress = true;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -345,7 +370,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
return;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -362,7 +388,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
mCallbacks.onOperationStarted(getBluetoothDevice());
mRecordAccessRequestInProgress = true;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -384,7 +411,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
mRecordAccessRequestInProgress = true;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
// Info:
// Operators OPERATOR_GREATER_THEN_OR_EQUAL, OPERATOR_LESS_THEN_OR_EQUAL and OPERATOR_RANGE are not supported by the CGMS sample from SDK
// The "Operation not supported" response will be received
@@ -403,7 +431,8 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
clear();
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
}

View File

@@ -82,25 +82,29 @@ public class CSCManager extends BatteryManager<CSCManagerCallbacks> {
@Override
public float getWheelCircumference() {
return Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_WHEEL_SIZE, String.valueOf(SettingsFragment.SETTINGS_WHEEL_SIZE_DEFAULT)));
return Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_WHEEL_SIZE,
String.valueOf(SettingsFragment.SETTINGS_WHEEL_SIZE_DEFAULT)));
}
@Override
public void onDistanceChanged(@NonNull final BluetoothDevice device, final float totalDistance, final float distance, final float speed) {
public void onDistanceChanged(@NonNull final BluetoothDevice device,
final float totalDistance, final float distance, final float speed) {
mCallbacks.onDistanceChanged(device, totalDistance, distance, speed);
}
@Override
public void onCrankDataChanged(@NonNull final BluetoothDevice device, final float crankCadence, final float gearRatio) {
public void onCrankDataChanged(@NonNull final BluetoothDevice device,
final float crankCadence, final float gearRatio) {
mCallbacks.onCrankDataChanged(device, crankCadence, gearRatio);
}
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) {
public void onInvalidDataReceived(@NonNull final BluetoothDevice device,
final @NonNull Data data) {
log(LogContract.Log.Level.WARNING, "Invalid CSC Measurement data received: " + data);
}
});
enableNotifications(mCSCMeasurementCharacteristic);
enableNotifications(mCSCMeasurementCharacteristic).enqueue();
}
@Override

View File

@@ -222,9 +222,11 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
if (numberOfRecords > 0) {
if (mRecords.size() > 0) {
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber));
writeCharacteristic(mRecordAccessControlPointCharacteristic,
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber));
} else {
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportAllStoredRecords());
writeCharacteristic(mRecordAccessControlPointCharacteristic,
RecordAccessControlPointData.reportAllStoredRecords());
}
} else {
mCallbacks.onOperationCompleted(device);
@@ -232,7 +234,8 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
}
@Override
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device, final int requestCode, final int errorCode) {
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device,
final int requestCode, final int errorCode) {
log(LogContract.Log.Level.WARNING, "Record Access operation failed (error " + errorCode + ")");
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
mCallbacks.onOperationNotSupported(device);
@@ -242,10 +245,11 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
}
});
enableNotifications(mGlucoseMeasurementCharacteristic);
enableNotifications(mGlucoseMeasurementContextCharacteristic);
enableNotifications(mGlucoseMeasurementCharacteristic).enqueue();
enableNotifications(mGlucoseMeasurementContextCharacteristic).enqueue();
enableIndications(mRecordAccessControlPointCharacteristic)
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enabled Record Access Control Point indications (error " + status + ")"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enabled Record Access Control Point indications (error " + status + ")"))
.enqueue();
}
@Override
@@ -302,7 +306,8 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
clear();
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -317,7 +322,8 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
clear();
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -333,7 +339,8 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
clear();
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
@@ -360,7 +367,8 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
writeCharacteristic(mRecordAccessControlPointCharacteristic,
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
// Info:
// Operators OPERATOR_LESS_THEN_OR_EQUAL and OPERATOR_RANGE are not supported by Nordic Semiconductor Glucose Service in SDK 4.4.2.
}
@@ -374,14 +382,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
return;
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
/**
* Sends the request to delete all data from the device. A Record Access Control Point indication
* with status code Success (or other in case of error) will be send.
*
* FIXME This method is not supported by Nordic Semiconductor Glucose Service in SDK 4.4.2.
*/
public void deleteAllRecords() {
if (mRecordAccessControlPointCharacteristic == null)
@@ -390,6 +397,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
clear();
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"));
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
}
}

View File

@@ -97,7 +97,8 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
mCallbacks.onBodySensorLocationReceived(device, sensorLocation);
}
})
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Body Sensor Location characteristic not found"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Body Sensor Location characteristic not found"))
.enqueue();
setNotificationCallback(mHeartRateCharacteristic)
.with(new HeartRateMeasurementDataCallback() {
@Override
@@ -115,7 +116,7 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
mCallbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
}
});
enableNotifications(mHeartRateCharacteristic);
enableNotifications(mHeartRateCharacteristic).enqueue();
}
@Override

View File

@@ -45,8 +45,6 @@ import no.nordicsemi.android.nrftoolbox.parser.TemperatureMeasurementParser;
* HTSActivity implements HTSManagerCallbacks in order to receive callbacks of BluetoothGatt operations.
*/
public class HTSManager extends BatteryManager<HTSManagerCallbacks> {
private static final String TAG = "HTSManager";
/** Health Thermometer service UUID */
public final static UUID HT_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
/** Health Thermometer Measurement characteristic UUID */
@@ -87,7 +85,7 @@ public class HTSManager extends BatteryManager<HTSManagerCallbacks> {
mCallbacks.onTemperatureMeasurementReceived(device, temperature, unit, calendar, type);
}
});
enableIndications(mHTCharacteristic);
enableIndications(mHTCharacteristic).enqueue();
}
@Override

View File

@@ -29,13 +29,13 @@ import android.support.v7.app.AlertDialog;
import no.nordicsemi.android.nrftoolbox.R;
public class LinklossFragment extends DialogFragment {
public class LinkLossFragment extends DialogFragment {
private static final String ARG_NAME = "name";
private String mName;
public static LinklossFragment getInstance(String name) {
final LinklossFragment fragment = new LinklossFragment();
public static LinkLossFragment getInstance(String name) {
final LinkLossFragment fragment = new LinkLossFragment();
final Bundle args = new Bundle();
args.putString(ARG_NAME, name);

View File

@@ -40,12 +40,6 @@ import no.nordicsemi.android.nrftoolbox.profile.multiconnect.BleMulticonnectProf
import no.nordicsemi.android.nrftoolbox.widget.DividerItemDecoration;
public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivity<ProximityService.ProximityBinder> {
private static final String TAG = "ProximityActivity";
// This is not used any more. Server is created always after the service is started or
// after Bluetooth adapter is enabled.
// public static final String PREFS_GATT_SERVER_ENABLED = "prefs_gatt_server_enabled";
private RecyclerView mDevicesView;
private DeviceAdapter mAdapter;
@@ -99,7 +93,7 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
@Override
protected UUID getFilterUUID() {
return ProximityManager.LINKLOSS_SERVICE_UUID;
return ProximityManager.LINK_LOSS_SERVICE_UUID;
}
@Override
@@ -146,18 +140,19 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
// The link loss may also be called when Bluetooth adapter was disabled
if (BluetoothAdapter.getDefaultAdapter().isEnabled())
showLinklossDialog(device.getName());
showLinkLossDialog(device.getName());
}
@SuppressWarnings("unused")
private void onBatteryLevelChanged(final BluetoothDevice device, final int batteryLevel) {
if (mAdapter != null)
mAdapter.onBatteryValueReceived(device); // Value will be obtained from the service
}
private void showLinklossDialog(final String name) {
private void showLinkLossDialog(final String name) {
try {
final LinklossFragment dialog = LinklossFragment.getInstance(name);
final LinkLossFragment dialog = LinkLossFragment.getInstance(name);
dialog.show(getSupportFragmentManager(), "scan_fragment");
} catch (final Exception e) {
// the activity must have been destroyed

View File

@@ -36,13 +36,11 @@ import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser;
@SuppressWarnings("WeakerAccess")
class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
private final String TAG = "ProximityManager";
/** Link Loss service UUID */
final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
/** Immediate Alert service UUID */
/** Link Loss service UUID. */
final static UUID LINK_LOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
/** Immediate Alert service UUID. */
private final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
/** Alert Level characteristic UUID */
/** Alert Level characteristic UUID. */
private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
private BluetoothGattCharacteristic mAlertLevelCharacteristic, mLinkLossCharacteristic;
@@ -71,12 +69,13 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
@Override
protected void initialize() {
super.initialize();
writeCharacteristic(mLinkLossCharacteristic, AlertLevelData.highAlert());
writeCharacteristic(mLinkLossCharacteristic, AlertLevelData.highAlert())
.enqueue();
}
@Override
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
final BluetoothGattService llService = gatt.getService(LINKLOSS_SERVICE_UUID);
final BluetoothGattService llService = gatt.getService(LINK_LOSS_SERVICE_UUID);
if (llService != null) {
mLinkLossCharacteristic = llService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
}
@@ -105,6 +104,7 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
/**
* Toggles the immediate alert on the target device.
*
* @return true if alarm has been enabled, false if disabled
*/
public boolean toggleImmediateAlert() {
@@ -114,6 +114,7 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
/**
* Writes the HIGH ALERT or NO ALERT command to the target device
*
* @param on true to enable the alarm on proximity tag, false to disable it
*/
public void writeImmediateAlert(final boolean on) {
@@ -124,7 +125,8 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
writeCharacteristic(mAlertLevelCharacteristic, on ? AlertLevelData.highAlert() : AlertLevelData.noAlert())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + AlertLevelParser.parse(data) + "\" sent"))
.done(device -> mAlertOn = on)
.fail((device, status) -> log(LogContract.Log.Level.APPLICATION, "Alert Level characteristic not found"));
.fail((device, status) -> log(LogContract.Log.Level.APPLICATION, "Alert Level characteristic not found"))
.enqueue();
}
/**

View File

@@ -30,12 +30,8 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
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.ble.common.callback.rsc.RunningSpeedAndCadenceMeasurementDataCallback;
import no.nordicsemi.android.ble.data.Data;
import no.nordicsemi.android.log.LogContract;
@@ -85,7 +81,7 @@ public class RSCManager extends BatteryManager<RSCManagerCallbacks> {
instantaneousCadence, strideLength, totalDistance);
}
});
enableNotifications(mRSCMeasurementCharacteristic);
enableNotifications(mRSCMeasurementCharacteristic).enqueue();
}
@Override

View File

@@ -45,15 +45,25 @@ import no.nordicsemi.android.nrftoolbox.template.callback.TemplateDataCallback;
*/
public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
// TODO Replace the services and characteristics below to match your device.
/** The service UUID */
/**
* The service UUID
*/
static final UUID SERVICE_UUID = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb"); // Heart Rate service
/** A UUID of a characteristic with notify property */
/**
* A UUID of a characteristic with notify property
*/
private static final UUID MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb"); // Heart Rate Measurement
/** A UUID of a characteristic with read property */
/**
* A UUID of a characteristic with read property
*/
private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb"); // Body Sensor Location
/** Some other service UUID */
/**
* Some other service UUID
*/
private static final UUID OTHER_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); // Generic Access service
/** A UUID of a characteristic with write property */
/**
* A UUID of a characteristic with write property
*/
private static final UUID WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00002A00-0000-1000-8000-00805f9b34fb"); // Device Name
// TODO Add more services and characteristics references.
@@ -88,38 +98,40 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
// Increase the MTU
requestMtu(43)
.with((device, mtu) -> log(LogContract.Log.Level.APPLICATION, "MTU changed to " + mtu))
.done(device -> {
// You may do some logic in here that should be done when the request finished successfully.
// In case of MTU this method is called also when the MTU hasn't changed, or has changed
// to a different (lower) value. Use .with(...) to get the MTU value.
})
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "MTU change not supported"));
.with((device, mtu) -> log(LogContract.Log.Level.APPLICATION, "MTU changed to " + mtu))
.done(device -> {
// You may do some logic in here that should be done when the request finished successfully.
// In case of MTU this method is called also when the MTU hasn't changed, or has changed
// to a different (lower) value. Use .with(...) to get the MTU value.
})
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "MTU change not supported"))
.enqueue();
// Set notification callback
setNotificationCallback(mRequiredCharacteristic)
// This callback will be called each time the notification is received
.with(new TemplateDataCallback() {
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
// Let's lass received data to the service
mCallbacks.onSampleValueReceived(device, value);
}
// This callback will be called each time the notification is received
.with(new TemplateDataCallback() {
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
// Let's lass received data to the service
mCallbacks.onSampleValueReceived(device, value);
}
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
log(LogContract.Log.Level.WARNING, "Invalid data received: " + data);
}
});
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
log(LogContract.Log.Level.WARNING, "Invalid data received: " + data);
}
});
// Enable notifications
enableNotifications(mRequiredCharacteristic)
// Method called after the data were sent (data will contain 0x0100 in this case)
.with((device, data) -> log(LogContract.Log.Level.DEBUG, "Data sent: " + data))
// Method called when the request finished successfully. This will be called after .with(..) callback
.done(device -> log(LogContract.Log.Level.APPLICATION, "Notifications enabled successfully"))
// Methods called in case of an error, for example when the characteristic does not have Notify property
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable notifications"));
// Method called after the data were sent (data will contain 0x0100 in this case)
.with((device, data) -> log(LogContract.Log.Level.DEBUG, "Data sent: " + data))
// Method called when the request finished successfully. This will be called after .with(..) callback
.done(device -> log(LogContract.Log.Level.APPLICATION, "Notifications enabled successfully"))
// Methods called in case of an error, for example when the characteristic does not have Notify property
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to enable notifications"))
.enqueue();
}
@Override
@@ -181,7 +193,8 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
} else {
log(LogContract.Log.Level.WARNING, "Value is empty!");
}
});
})
.enqueue();
}
};
@@ -206,6 +219,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
// Write Without Request type was used. This is called after .with(...) callback.
.done(device -> log(LogContract.Log.Level.APPLICATION, "Device name set to \"" + parameter + "\""))
// Callback called when write has failed.
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to change device name"));
.fail((device, status) -> log(LogContract.Log.Level.WARNING, "Failed to change device name"))
.enqueue();
}
}

View File

@@ -29,13 +29,10 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import java.io.UnsupportedEncodingException;
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.ble.WriteRequest;
import no.nordicsemi.android.log.LogContract;
public class UARTManager extends BleManager<UARTManagerCallbacks> {
@@ -45,14 +42,11 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
private final static UUID UART_RX_CHARACTERISTIC_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
/** TX characteristic UUID */
private final static UUID UART_TX_CHARACTERISTIC_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
/** The maximum packet size is 20 bytes. */
private static final int MAX_PACKET_SIZE = 20;
private BluetoothGattCharacteristic mRXCharacteristic, mTXCharacteristic;
private byte[] mOutgoingBuffer;
private int mBufferOffset;
private boolean mUseLongWrite = true;
public UARTManager(final Context context) {
UARTManager(final Context context) {
super(context);
}
@@ -63,15 +57,20 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
}
/**
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc.
*/
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Deque<Request> initGatt(@NonNull final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mTXCharacteristic));
return requests;
protected void initialize() {
requestMtu(260).enqueue();
setNotificationCallback(mTXCharacteristic)
.with((device, data) -> {
final String text = data.getStringValue(0);
log(LogContract.Log.Level.APPLICATION, "\"" + text + "\" received");
mCallbacks.onDataReceived(device, text);
});
enableNotifications(mTXCharacteristic).enqueue();
}
@Override
@@ -89,10 +88,14 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
writeRequest = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
writeCommand = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0;
// Set the WRITE REQUEST type when the characteristic supports it. This will allow to send long write (also if the characteristic support it).
// In case there is no WRITE REQUEST property, this manager will divide texts longer then 20 bytes into up to 20 bytes chunks.
// Set the WRITE REQUEST type when the characteristic supports it.
// This will allow to send long write (also if the characteristic support it).
// In case there is no WRITE REQUEST property, this manager will divide texts
// longer then MTU-3 bytes into up to MTU-3 bytes chunks.
if (writeRequest)
mRXCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
else
mUseLongWrite = false;
}
return mRXCharacteristic != null && mTXCharacteristic != null && (writeRequest || writeCommand);
@@ -102,33 +105,7 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
protected void onDeviceDisconnected() {
mRXCharacteristic = null;
mTXCharacteristic = null;
}
@Override
public void onCharacteristicWrite(@NonNull final BluetoothGatt gatt, @NonNull final BluetoothGattCharacteristic characteristic) {
// When the whole buffer has been sent
final byte[] buffer = mOutgoingBuffer;
if (mBufferOffset == buffer.length) {
try {
final String data = new String(buffer, "UTF-8");
log(LogContract.Log.Level.APPLICATION, "\"" + data + "\" sent");
mCallbacks.onDataSent(gatt.getDevice(), data);
} catch (final UnsupportedEncodingException e) {
// do nothing
}
mOutgoingBuffer = null;
} else { // Otherwise...
final int length = Math.min(buffer.length - mBufferOffset, MAX_PACKET_SIZE);
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, mBufferOffset, length));
mBufferOffset += length;
}
}
@Override
public void onCharacteristicNotified(@NonNull final BluetoothGatt gatt, @NonNull final BluetoothGattCharacteristic characteristic) {
final String data = characteristic.getStringValue(0);
log(LogContract.Log.Level.APPLICATION, "\"" + data + "\" received");
mCallbacks.onDataReceived(gatt.getDevice(), data);
mUseLongWrite = true;
}
};
@@ -147,23 +124,12 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
if (mRXCharacteristic == null)
return;
// An outgoing buffer may not be null if there is already another packet being sent. We do nothing in this case.
if (!TextUtils.isEmpty(text) && mOutgoingBuffer == null) {
final byte[] buffer = mOutgoingBuffer = text.getBytes();
mBufferOffset = 0;
// Depending on whether the characteristic has the WRITE REQUEST property or not, we will either send it as it is (hoping the long write is implemented),
// or divide it into up to 20 bytes chunks and send them one by one.
final boolean writeRequest = (mRXCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
if (!writeRequest) { // no WRITE REQUEST property
final int length = Math.min(buffer.length, MAX_PACKET_SIZE);
mBufferOffset += length;
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, 0, length));
} else { // there is WRITE REQUEST property, let's try Long Write
mBufferOffset = buffer.length;
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, 0, buffer.length));
if (!TextUtils.isEmpty(text)) {
final WriteRequest request = writeCharacteristic(mRXCharacteristic, text.getBytes());
if (!mUseLongWrite) {
request.split();
}
request.enqueue();
}
}
}