mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-07 00:34:33 +01:00
CGMS profile fixed, BleManager callback report BluetootDevice
This commit fixes some issues in CGMS profile. It also modiefied the BleManager and BleManagerCallback to report the related BluetoothDevice object. This is a preparation for adding multiconnect support.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.bpm;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -102,23 +103,23 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady() {
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
// this may notify user
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBloodPressureMeasurementRead(final float systolic, final float diastolic, final float meanArterialPressure, final int unit) {
|
||||
public void onBloodPressureMeasurementRead(final BluetoothDevice device, final float systolic, final float diastolic, final float meanArterialPressure, final int unit) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSystolicView.setText(Float.toString(systolic));
|
||||
mDiastolicView.setText(Float.toString(diastolic));
|
||||
mMeanAPView.setText(Float.toString(meanArterialPressure));
|
||||
mSystolicView.setText(String.valueOf(systolic));
|
||||
mDiastolicView.setText(String.valueOf(diastolic));
|
||||
mMeanAPView.setText(String.valueOf(meanArterialPressure));
|
||||
|
||||
mSystolicUnitView.setText(unit == UNIT_mmHG ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
mDiastolicUnitView.setText(unit == UNIT_mmHG ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
@@ -128,11 +129,11 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIntermediateCuffPressureRead(final float cuffPressure, final int unit) {
|
||||
public void onIntermediateCuffPressureRead(final BluetoothDevice device, final float cuffPressure, final int unit) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSystolicView.setText(Float.toString(cuffPressure));
|
||||
mSystolicView.setText(String.valueOf(cuffPressure));
|
||||
mDiastolicView.setText(R.string.not_available_value);
|
||||
mMeanAPView.setText(R.string.not_available_value);
|
||||
|
||||
@@ -144,12 +145,12 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPulseRateRead(final float pulseRate) {
|
||||
public void onPulseRateRead(final BluetoothDevice device, final float pulseRate) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (pulseRate >= 0)
|
||||
mPulseView.setText(Float.toString(pulseRate));
|
||||
mPulseView.setText(String.valueOf(pulseRate));
|
||||
else
|
||||
mPulseView.setText(R.string.not_available_value);
|
||||
}
|
||||
@@ -157,7 +158,7 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimestampRead(final Calendar calendar) {
|
||||
public void onTimestampRead(final BluetoothDevice device, final Calendar calendar) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -76,8 +76,8 @@ public class BPMManager extends BleManager<BPMManagerCallbacks> {
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
if (mICPCharacteristic != null)
|
||||
requests.push(Request.newEnableNotificationsRequest(mICPCharacteristic));
|
||||
requests.push(Request.newEnableIndicationsRequest(mBPMCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mICPCharacteristic));
|
||||
requests.add(Request.newEnableIndicationsRequest(mBPMCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -105,22 +105,20 @@ public class BPMManager extends BleManager<BPMManagerCallbacks> {
|
||||
@Override
|
||||
protected void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
// Intermediate Cuff Pressure characteristic read
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, IntermediateCuffPressureParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + IntermediateCuffPressureParser.parse(characteristic) + "\" received");
|
||||
|
||||
parseBPMValue(characteristic);
|
||||
parseBPMValue(gatt, characteristic);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
// Blood Pressure Measurement characteristic read
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, BloodPressureMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + BloodPressureMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
parseBPMValue(characteristic);
|
||||
parseBPMValue(gatt, characteristic);
|
||||
}
|
||||
|
||||
private void parseBPMValue(final BluetoothGattCharacteristic characteristic) {
|
||||
private void parseBPMValue(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
// Both BPM and ICP have the same structure.
|
||||
|
||||
// first byte - flags
|
||||
@@ -137,12 +135,12 @@ public class BPMManager extends BleManager<BPMManagerCallbacks> {
|
||||
final float diastolic = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset + 2);
|
||||
final float meanArterialPressure = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset + 4);
|
||||
offset += 6;
|
||||
mCallbacks.onBloodPressureMeasurementRead(systolic, diastolic, meanArterialPressure, unit);
|
||||
mCallbacks.onBloodPressureMeasurementRead(gatt.getDevice(), systolic, diastolic, meanArterialPressure, unit);
|
||||
} else if (ICP_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
|
||||
// following bytes - cuff pressure. Diastolic and MAP are unused
|
||||
final float cuffPressure = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 6;
|
||||
mCallbacks.onIntermediateCuffPressureRead(cuffPressure, unit);
|
||||
mCallbacks.onIntermediateCuffPressureRead(gatt.getDevice(), cuffPressure, unit);
|
||||
}
|
||||
|
||||
// parse timestamp if present
|
||||
@@ -155,17 +153,17 @@ public class BPMManager extends BleManager<BPMManagerCallbacks> {
|
||||
calendar.set(Calendar.MINUTE, characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset + 5));
|
||||
calendar.set(Calendar.SECOND, characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset + 6));
|
||||
offset += 7;
|
||||
mCallbacks.onTimestampRead(calendar);
|
||||
mCallbacks.onTimestampRead(gatt.getDevice(), calendar);
|
||||
} else
|
||||
mCallbacks.onTimestampRead(null);
|
||||
mCallbacks.onTimestampRead(gatt.getDevice(), null);
|
||||
|
||||
// parse pulse rate if present
|
||||
if (pulseRatePresent) {
|
||||
final float pulseRate = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
// offset += 2;
|
||||
mCallbacks.onPulseRateRead(pulseRate);
|
||||
mCallbacks.onPulseRateRead(gatt.getDevice(), pulseRate);
|
||||
} else
|
||||
mCallbacks.onPulseRateRead(-1.0f);
|
||||
mCallbacks.onPulseRateRead(gatt.getDevice(), -1.0f);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,47 +21,53 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.bpm;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface BPMManagerCallbacks extends BleManagerCallbacks {
|
||||
public static final int UNIT_mmHG = 0;
|
||||
public static final int UNIT_kPa = 1;
|
||||
int UNIT_mmHG = 0;
|
||||
int UNIT_kPa = 1;
|
||||
|
||||
/**
|
||||
* Called when new BPM value has been obtained from the sensor
|
||||
*
|
||||
*
|
||||
* @param device the target device
|
||||
* @param systolic
|
||||
* @param diastolic
|
||||
* @param meanArterialPressure
|
||||
* @param unit
|
||||
* one of the following {@link #UNIT_kPa} or {@link #UNIT_mmHG}
|
||||
*/
|
||||
public void onBloodPressureMeasurementRead(final float systolic, final float diastolic, final float meanArterialPressure, final int unit);
|
||||
void onBloodPressureMeasurementRead(final BluetoothDevice device, final float systolic, final float diastolic, final float meanArterialPressure, final int unit);
|
||||
|
||||
/**
|
||||
* Called when new ICP value has been obtained from the device
|
||||
*
|
||||
*
|
||||
* @param device the target device
|
||||
* @param cuffPressure
|
||||
* @param unit
|
||||
* one of the following {@link #UNIT_kPa} or {@link #UNIT_mmHG}
|
||||
*/
|
||||
public void onIntermediateCuffPressureRead(final float cuffPressure, final int unit);
|
||||
void onIntermediateCuffPressureRead(final BluetoothDevice device, final float cuffPressure, final int unit);
|
||||
|
||||
/**
|
||||
* Called when new pulse rate value has been obtained from the device. If there was no pulse rate in the packet the parameter will be equal -1.0f
|
||||
*
|
||||
*
|
||||
* @param device the target device
|
||||
* @param pulseRate
|
||||
* pulse rate or -1.0f
|
||||
*/
|
||||
public void onPulseRateRead(final float pulseRate);
|
||||
void onPulseRateRead(final BluetoothDevice device, final float pulseRate);
|
||||
|
||||
/**
|
||||
* Called when the timestamp value has been read from the device. If there was no timestamp information the parameter will be <code>null</code>
|
||||
*
|
||||
*
|
||||
* @param device the target device
|
||||
* @param calendar
|
||||
* the timestamp or <code>null</code>
|
||||
*/
|
||||
public void onTimestampRead(final Calendar calendar);
|
||||
void onTimestampRead(final BluetoothDevice device, final Calendar calendar);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -34,7 +35,6 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -42,251 +42,232 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity;
|
||||
|
||||
public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMSBinder> implements PopupMenu.OnMenuItemClickListener {
|
||||
public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMSBinder> implements PopupMenu.OnMenuItemClickListener {
|
||||
private View mControlPanelStd;
|
||||
private View mControlPanelAbort;
|
||||
private ListView mRecordsListView;
|
||||
private CGMSRecordsAdapter mCgmsRecordsAdapter;
|
||||
|
||||
private View mControlPanelStd;
|
||||
private View mControlPanelAbort;
|
||||
private TextView mUnitView;
|
||||
private ListView mRecordsListView;
|
||||
private CGMSRecordsAdapter mCgmsRecordsAdapter;
|
||||
private CGMService.CGMSBinder mBinder;
|
||||
|
||||
private CGMService.CGMSBinder mBinder;
|
||||
@Override
|
||||
protected void onCreateView(Bundle savedInstanceState) {
|
||||
setContentView(R.layout.activity_feature_cgms);
|
||||
setGUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateView(Bundle savedInstanceState) {
|
||||
setContentView(R.layout.activity_feature_cgms);
|
||||
setGUI();
|
||||
}
|
||||
@Override
|
||||
protected void onInitialize(Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize(Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
private void setGUI() {
|
||||
mRecordsListView = (ListView) findViewById(R.id.list);
|
||||
mControlPanelStd = findViewById(R.id.cgms_control_std);
|
||||
mControlPanelAbort = findViewById(R.id.cgms_control_abort);
|
||||
|
||||
private void setGUI() {
|
||||
mRecordsListView = (ListView) findViewById(R.id.list);
|
||||
mUnitView = (TextView) findViewById(R.id.unit);
|
||||
mControlPanelStd = findViewById(R.id.cgms_control_std);
|
||||
mControlPanelAbort = findViewById(R.id.cgms_control_abort);
|
||||
findViewById(R.id.action_last).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clearRecords();
|
||||
if (mBinder != null) {
|
||||
mBinder.clear();
|
||||
mBinder.getLastRecord();
|
||||
}
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_all).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clearRecords();
|
||||
if (mBinder != null) {
|
||||
clearRecords();
|
||||
mBinder.getAllRecords();
|
||||
}
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_abort).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mBinder != null) {
|
||||
mBinder.abort();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
findViewById(R.id.action_last).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clearRecords();
|
||||
if(mBinder != null) {
|
||||
mBinder.clear();
|
||||
mBinder.getLastRecord();
|
||||
}
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_all).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clearRecords();
|
||||
if(mBinder != null){
|
||||
clearRecords();
|
||||
mBinder.getAllRecords();
|
||||
}
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_abort).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(mBinder != null){
|
||||
mBinder.abort();
|
||||
}
|
||||
}
|
||||
});
|
||||
// create popup menu attached to the button More
|
||||
findViewById(R.id.action_more).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PopupMenu menu = new PopupMenu(CGMSActivity.this, v);
|
||||
menu.setOnMenuItemClickListener(CGMSActivity.this);
|
||||
MenuInflater inflater = menu.getMenuInflater();
|
||||
inflater.inflate(R.menu.gls_more, menu.getMenu());
|
||||
menu.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// create popup menu attached to the button More
|
||||
findViewById(R.id.action_more).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PopupMenu menu = new PopupMenu(CGMSActivity.this, v);
|
||||
menu.setOnMenuItemClickListener(CGMSActivity.this);
|
||||
MenuInflater inflater = menu.getMenuInflater();
|
||||
inflater.inflate(R.menu.gls_more, menu.getMenu());
|
||||
menu.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
private void loadAdapter(SparseArray<CGMSRecord> records) {
|
||||
mCgmsRecordsAdapter.clear();
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
mCgmsRecordsAdapter.addItem(records.valueAt(i));
|
||||
}
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void loadAdapter(SparseArray<CGMSRecord> records){
|
||||
for(int i = 0; i < records.size(); i++){
|
||||
mCgmsRecordsAdapter.addItem(records.get(i));
|
||||
}
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
@Override
|
||||
protected void onServiceBinded(final CGMService.CGMSBinder binder) {
|
||||
mBinder = binder;
|
||||
final SparseArray<CGMSRecord> cgmsRecords = binder.getRecords();
|
||||
if (cgmsRecords != null && cgmsRecords.size() > 0) {
|
||||
if (mCgmsRecordsAdapter == null) {
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
}
|
||||
loadAdapter(cgmsRecords);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceBinded(CGMService.CGMSBinder binder) {
|
||||
mBinder = binder;
|
||||
SparseArray<CGMSRecord> cgmsRecords = binder.getCgmsRecords();
|
||||
if(cgmsRecords != null && cgmsRecords.size() > 0){
|
||||
if(mCgmsRecordsAdapter == null) {
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
}
|
||||
loadAdapter(cgmsRecords);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onServiceUnbinded() {
|
||||
mBinder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceUnbinded() {
|
||||
mBinder = null;
|
||||
}
|
||||
@Override
|
||||
protected Class<? extends BleProfileService> getServiceClass() {
|
||||
return CGMService.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends BleProfileService> getServiceClass() {
|
||||
return CGMService.class;
|
||||
}
|
||||
@Override
|
||||
protected int getLoggerProfileTitle() {
|
||||
return R.string.cgms_feature_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLoggerProfileTitle() {
|
||||
return R.string.cgms_feature_title;
|
||||
}
|
||||
@Override
|
||||
protected int getAboutTextId() {
|
||||
return R.string.cgms_about_text;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getAboutTextId() {
|
||||
return R.string.cgms_about_text;
|
||||
}
|
||||
@Override
|
||||
protected int getDefaultDeviceName() {
|
||||
return R.string.cgms_default_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultDeviceName() {
|
||||
return R.string.cgms_default_name;
|
||||
}
|
||||
@Override
|
||||
protected UUID getFilterUUID() {
|
||||
return CGMSManager.CGMS_UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID getFilterUUID() {
|
||||
return CGMSManager.CGMS_UUID;
|
||||
}
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
private void setOperationInProgress(final boolean progress) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// setSupportProgressBarIndeterminateVisibility(progress);
|
||||
mControlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
mControlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady() {
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
setOperationInProgress(false);
|
||||
clearRecords();
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private void setOperationInProgress(final boolean progress) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// setSupportProgressBarIndeterminateVisibility(progress);
|
||||
mControlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
mControlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_refresh:
|
||||
if(mBinder != null)
|
||||
mBinder.refreshRecords();
|
||||
break;
|
||||
case R.id.action_first:
|
||||
if (mBinder != null)
|
||||
mBinder.getFirstRecord();
|
||||
break;
|
||||
case R.id.action_clear:
|
||||
if (mBinder != null)
|
||||
mBinder.clear();
|
||||
break;
|
||||
case R.id.action_delete_all:
|
||||
if (mBinder != null)
|
||||
mBinder.deleteAllRecords();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
setOperationInProgress(false);
|
||||
clearRecords();
|
||||
}
|
||||
private void clearRecords() {
|
||||
if (mCgmsRecordsAdapter != null) {
|
||||
mCgmsRecordsAdapter.clear();
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
}
|
||||
switch (action) {
|
||||
case CGMService.BROADCAST_NEW_CGMS_VALUE: {
|
||||
CGMSRecord cgmsRecord = intent.getExtras().getParcelable(CGMService.EXTRA_CGMS_RECORD);
|
||||
if (mCgmsRecordsAdapter == null) {
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
}
|
||||
mCgmsRecordsAdapter.addItem(cgmsRecord);
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
case CGMService.BROADCAST_DATA_SET_CLEAR:
|
||||
// Update GUI
|
||||
clearRecords();
|
||||
break;
|
||||
case CGMService.OPERATION_STARTED:
|
||||
// Update GUI
|
||||
setOperationInProgress(true);
|
||||
break;
|
||||
case CGMService.OPERATION_FAILED:
|
||||
// Update GUI
|
||||
showToast(R.string.gls_operation_failed);
|
||||
// breakthrough intended
|
||||
default:
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_refresh:
|
||||
/*if(mBinder != null)
|
||||
mBinder.refreshRecords();*/
|
||||
break;
|
||||
case R.id.action_first:
|
||||
clearRecords();
|
||||
if(mBinder != null)
|
||||
mBinder.getFirstRecord();
|
||||
break;
|
||||
case R.id.action_clear:
|
||||
clearRecords();
|
||||
if(mBinder != null)
|
||||
mBinder.clear();
|
||||
break;
|
||||
case R.id.action_delete_all:
|
||||
clearRecords();
|
||||
if(mBinder != null)
|
||||
mBinder.deleteAllRecords();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void clearRecords(){
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mCgmsRecordsAdapter != null){
|
||||
mCgmsRecordsAdapter.clear();
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (CGMService.BROADCAST_CGMS_VALUES.equals(action)) {
|
||||
CGMSRecord cgmsRecord = intent.getExtras().getParcelable(CGMService.EXTRA_CGMS_RECORD);
|
||||
if(mCgmsRecordsAdapter == null){
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
}
|
||||
mCgmsRecordsAdapter.addItem(cgmsRecord);
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
|
||||
} else if (CGMService.BROADCAST_DATA_SET_CHANGED.equals(action)) {
|
||||
// Update GUI
|
||||
clearRecords();
|
||||
} else if (CGMService.OPERATION_STARTED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(true);
|
||||
} else if (CGMService.OPERATION_COMPLETED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
} else if (CGMService.OPERATION_SUPPORTED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
} else if (CGMService.OPERATION_NOT_SUPPORTED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
} else if (CGMService.OPERATION_ABORTED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
} else if (CGMService.OPERATION_FAILED.equals(action)) {
|
||||
// Update GUI
|
||||
setOperationInProgress(false);
|
||||
showToast(R.string.gls_operation_failed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static IntentFilter makeIntentFilter() {
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(CGMService.BROADCAST_CGMS_VALUES);
|
||||
intentFilter.addAction(CGMService.BROADCAST_DATA_SET_CHANGED);
|
||||
intentFilter.addAction(CGMService.OPERATION_STARTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_COMPLETED);
|
||||
intentFilter.addAction(CGMService.OPERATION_SUPPORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_NOT_SUPPORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_ABORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_FAILED);
|
||||
return intentFilter;
|
||||
}
|
||||
private static IntentFilter makeIntentFilter() {
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(CGMService.BROADCAST_NEW_CGMS_VALUE);
|
||||
intentFilter.addAction(CGMService.BROADCAST_DATA_SET_CLEAR);
|
||||
intentFilter.addAction(CGMService.OPERATION_STARTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_COMPLETED);
|
||||
intentFilter.addAction(CGMService.OPERATION_SUPPORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_NOT_SUPPORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_ABORTED);
|
||||
intentFilter.addAction(CGMService.OPERATION_FAILED);
|
||||
return intentFilter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,19 +26,15 @@ import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import android.nfc.Tag;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.log.Logger;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.HeartRateMeasurementParser;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.CGMMeasurementParser;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.CGMSpecificOpsControlPointParser;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.RecordAccessControlPointParser;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
|
||||
import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
|
||||
@@ -47,337 +43,363 @@ import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
|
||||
* Created by rora on 10.05.2016.
|
||||
*/
|
||||
public class CGMSManager extends BleManager<CGMSManagerCallbacks> {
|
||||
private static final String TAG = "CGMSManager";
|
||||
private static final String TAG = "CGMSManager";
|
||||
|
||||
/** Cycling Speed and Cadence service UUID */
|
||||
public final static UUID CGMS_UUID = UUID.fromString("0000181F-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 */
|
||||
private final static UUID RACP_UUID = UUID.fromString("00002A52-0000-1000-8000-00805f9b34fb");
|
||||
/**
|
||||
* Cycling Speed and Cadence service UUID
|
||||
*/
|
||||
public final static UUID CGMS_UUID = UUID.fromString("0000181F-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");
|
||||
private final static int OP_CODE_START_SESSION = 26;
|
||||
/**
|
||||
* Record Access Control Point characteristic UUID
|
||||
*/
|
||||
private final static UUID RACP_UUID = UUID.fromString("00002A52-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private final static int OP_CODE_REPORT_STORED_RECORDS = 1;
|
||||
private final static int OP_CODE_DELETE_STORED_RECORDS = 2;
|
||||
private final static int OP_CODE_ABORT_OPERATION = 3;
|
||||
private final static int OP_CODE_REPORT_NUMBER_OF_RECORDS = 4;
|
||||
private final static int OP_CODE_NUMBER_OF_STORED_RECORDS_RESPONSE = 5;
|
||||
private final static int OP_CODE_RESPONSE_CODE = 6;
|
||||
private final static int OP_CODE_REPORT_STORED_RECORDS = 1;
|
||||
private final static int OP_CODE_DELETE_STORED_RECORDS = 2;
|
||||
private final static int OP_CODE_ABORT_OPERATION = 3;
|
||||
private final static int OP_CODE_REPORT_NUMBER_OF_RECORDS = 4;
|
||||
private final static int OP_CODE_NUMBER_OF_STORED_RECORDS_RESPONSE = 5;
|
||||
private final static int OP_CODE_RESPONSE_CODE = 6;
|
||||
|
||||
private final static int OPERATOR_NULL = 0;
|
||||
private final static int OPERATOR_ALL_RECORDS = 1;
|
||||
private final static int OPERATOR_LESS_THEN_OR_EQUAL = 2;
|
||||
private final static int OPERATOR_GREATER_THEN_OR_EQUAL = 3;
|
||||
private final static int OPERATOR_WITHING_RANGE = 4;
|
||||
private final static int OPERATOR_FIRST_RECORD = 5;
|
||||
private final static int OPERATOR_LAST_RECORD = 6;
|
||||
private final static int OPERATOR_NULL = 0;
|
||||
private final static int OPERATOR_ALL_RECORDS = 1;
|
||||
private final static int OPERATOR_LESS_THEN_OR_EQUAL = 2;
|
||||
private final static int OPERATOR_GREATER_THEN_OR_EQUAL = 3;
|
||||
private final static int OPERATOR_WITHING_RANGE = 4;
|
||||
private final static int OPERATOR_FIRST_RECORD = 5;
|
||||
private final static int OPERATOR_LAST_RECORD = 6;
|
||||
|
||||
/**
|
||||
* The filter type is used for range operators ({@link #OPERATOR_LESS_THEN_OR_EQUAL}, {@link #OPERATOR_GREATER_THEN_OR_EQUAL}, {@link #OPERATOR_WITHING_RANGE}.<br/>
|
||||
* The syntax of the operand is: [Filter Type][Minimum][Maximum].<br/>
|
||||
* This filter selects the records by the sequence number.
|
||||
*/
|
||||
private final static int FILTER_TYPE_SEQUENCE_NUMBER = 1;
|
||||
/**
|
||||
* The filter type is used for range operators ({@link #OPERATOR_LESS_THEN_OR_EQUAL}, {@link #OPERATOR_GREATER_THEN_OR_EQUAL}, {@link #OPERATOR_WITHING_RANGE}.<br/>
|
||||
* The syntax of the operand is: [Filter Type][Minimum][Maximum].<br/>
|
||||
* This filter selects the records by the user facing time (base time + offset time).
|
||||
*/
|
||||
private final static int FILTER_TYPE_USER_FACING_TIME = 2;
|
||||
private final static int RESPONSE_SUCCESS = 1;
|
||||
private final static int RESPONSE_OP_CODE_NOT_SUPPORTED = 2;
|
||||
private final static int RESPONSE_INVALID_OPERATOR = 3;
|
||||
private final static int RESPONSE_OPERATOR_NOT_SUPPORTED = 4;
|
||||
private final static int RESPONSE_INVALID_OPERAND = 5;
|
||||
private final static int RESPONSE_NO_RECORDS_FOUND = 6;
|
||||
private final static int RESPONSE_ABORT_UNSUCCESSFUL = 7;
|
||||
private final static int RESPONSE_PROCEDURE_NOT_COMPLETED = 8;
|
||||
private final static int RESPONSE_OPERAND_NOT_SUPPORTED = 9;
|
||||
/**
|
||||
* The filter type is used for range operators ({@link #OPERATOR_LESS_THEN_OR_EQUAL}, {@link #OPERATOR_GREATER_THEN_OR_EQUAL}, {@link #OPERATOR_WITHING_RANGE}.<br/>
|
||||
* The syntax of the operand is: [Filter Type][Minimum][Maximum].<br/>
|
||||
* This filter selects the records by the sequence number.
|
||||
*/
|
||||
private final static int FILTER_TYPE_SEQUENCE_NUMBER = 1;
|
||||
/**
|
||||
* The filter type is used for range operators ({@link #OPERATOR_LESS_THEN_OR_EQUAL}, {@link #OPERATOR_GREATER_THEN_OR_EQUAL}, {@link #OPERATOR_WITHING_RANGE}.<br/>
|
||||
* The syntax of the operand is: [Filter Type][Minimum][Maximum].<br/>
|
||||
* This filter selects the records by the user facing time (base time + offset time).
|
||||
*/
|
||||
private final static int FILTER_TYPE_USER_FACING_TIME = 2;
|
||||
private final static int RESPONSE_SUCCESS = 1;
|
||||
private final static int RESPONSE_OP_CODE_NOT_SUPPORTED = 2;
|
||||
private final static int RESPONSE_INVALID_OPERATOR = 3;
|
||||
private final static int RESPONSE_OPERATOR_NOT_SUPPORTED = 4;
|
||||
private final static int RESPONSE_INVALID_OPERAND = 5;
|
||||
private final static int RESPONSE_NO_RECORDS_FOUND = 6;
|
||||
private final static int RESPONSE_ABORT_UNSUCCESSFUL = 7;
|
||||
private final static int RESPONSE_PROCEDURE_NOT_COMPLETED = 8;
|
||||
private final static int RESPONSE_OPERAND_NOT_SUPPORTED = 9;
|
||||
|
||||
private final static SimpleDateFormat mTimeFormat= new SimpleDateFormat("dd MM YYYY HH:mm:ss");
|
||||
private BluetoothGattCharacteristic mCGMMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic mCGMOpsControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic mRecordAccessControlPointCharacteristic;
|
||||
|
||||
private BluetoothGattCharacteristic mCGMMEasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic mCGMOpsControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic mRecordAccessControlPointCharacteristic;
|
||||
private static CGMSManager managerInstance = null;
|
||||
private SparseArray<CGMSRecord> mRecords = new SparseArray<>();
|
||||
private boolean mAbort;
|
||||
private long mSessionStartTime;
|
||||
|
||||
private static CGMSManager managerInstance = null;
|
||||
private SparseArray<CGMSRecord> mRecords = new SparseArray<>();
|
||||
private boolean mAbort;
|
||||
private long mSessionStartTime;
|
||||
/**
|
||||
* singleton implementation of HRSManager class
|
||||
*/
|
||||
public static synchronized CGMSManager getInstance(final Context context) {
|
||||
if (managerInstance == null) {
|
||||
managerInstance = new CGMSManager(context);
|
||||
}
|
||||
return managerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* singleton implementation of HRSManager class
|
||||
*/
|
||||
public static synchronized CGMSManager getInstance(final Context context) {
|
||||
if (managerInstance == null) {
|
||||
managerInstance = new CGMSManager(context);
|
||||
}
|
||||
return managerInstance;
|
||||
}
|
||||
public CGMSManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public CGMSManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BleManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
}
|
||||
@Override
|
||||
protected BleManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving notification, etc
|
||||
*/
|
||||
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving notification, etc
|
||||
*/
|
||||
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableNotificationsRequest(mCGMMEasurementCharacteristic));
|
||||
if (mCGMOpsControlPointCharacteristic != null) {
|
||||
mSessionStartTime = System.currentTimeMillis();
|
||||
requests.push(Request.newWriteRequest(mCGMOpsControlPointCharacteristic, new byte[]{26} /*start session value*/));
|
||||
}
|
||||
requests.push(Request.newEnableIndicationsRequest(mRecordAccessControlPointCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.add(Request.newEnableNotificationsRequest(mCGMMeasurementCharacteristic));
|
||||
if (mCGMOpsControlPointCharacteristic != null) {
|
||||
mSessionStartTime = System.currentTimeMillis();
|
||||
requests.add(Request.newEnableIndicationsRequest(mCGMOpsControlPointCharacteristic));
|
||||
requests.add(Request.newWriteRequest(mCGMOpsControlPointCharacteristic, new byte[]{OP_CODE_START_SESSION}));
|
||||
}
|
||||
requests.add(Request.newEnableIndicationsRequest(mRecordAccessControlPointCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CGMS_UUID);
|
||||
if (service != null) {
|
||||
mCGMMEasurementCharacteristic = service.getCharacteristic(CGM_MEASUREMENT_UUID);
|
||||
mCGMOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
mRecordAccessControlPointCharacteristic = service.getCharacteristic(RACP_UUID);
|
||||
}
|
||||
return mCGMMEasurementCharacteristic != null && mCGMOpsControlPointCharacteristic != null && mRecordAccessControlPointCharacteristic != null;
|
||||
}
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CGMS_UUID);
|
||||
if (service != null) {
|
||||
mCGMMeasurementCharacteristic = service.getCharacteristic(CGM_MEASUREMENT_UUID);
|
||||
mCGMOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
mRecordAccessControlPointCharacteristic = service.getCharacteristic(RACP_UUID);
|
||||
}
|
||||
return mCGMMeasurementCharacteristic != null && mCGMOpsControlPointCharacteristic != null && mRecordAccessControlPointCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOptionalServiceSupported(final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CGMS_UUID);
|
||||
if (service != null) {
|
||||
mCGMOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
}
|
||||
return mCGMOpsControlPointCharacteristic != null;
|
||||
}
|
||||
@Override
|
||||
protected boolean isOptionalServiceSupported(final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CGMS_UUID);
|
||||
if (service != null) {
|
||||
mCGMOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
}
|
||||
return mCGMOpsControlPointCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
}
|
||||
@Override
|
||||
public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mCGMOpsControlPointCharacteristic = null;
|
||||
mCGMMEasurementCharacteristic = null;
|
||||
//mRecordAccessControlPointCharacteristic = null;
|
||||
}
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mCGMOpsControlPointCharacteristic = null;
|
||||
mCGMMeasurementCharacteristic = null;
|
||||
mRecordAccessControlPointCharacteristic = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
final UUID uuid = characteristic.getUuid();
|
||||
if(CGM_MEASUREMENT_UUID.equals(uuid)) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, HeartRateMeasurementParser.parse(characteristic));
|
||||
byte [] data = characteristic.getValue();
|
||||
int cgmSize = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
float cgmValue;
|
||||
int timeOffset;
|
||||
if (cgmSize > 0) {
|
||||
cgmValue = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, 2);
|
||||
timeOffset = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 4);
|
||||
Date date = new Date(mSessionStartTime + (timeOffset * 3600));
|
||||
final String timeStamp = mTimeFormat.format(date);
|
||||
//This will send callback to CGMSActivity when new concentration value is received from CGMS device
|
||||
mCallbacks.onCGMValueReceived(cgmValue, timeStamp);
|
||||
}
|
||||
} else if (CGM_OPS_CONTROL_POINT_UUID.equals(uuid)){
|
||||
Log.v(TAG, "CGM Ops control");
|
||||
} else if (RACP_UUID.equals(uuid)){
|
||||
Log.v(TAG, "RACP Ops control");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (characteristic.getUuid().equals(RACP_UUID)) {
|
||||
Logger.a(mLogSession, "\"" + RecordAccessControlPointParser.parse(characteristic) + "\" sent");
|
||||
} else { // uuid == CGM_OPS_CONTROL_POINT_UUID
|
||||
Logger.a(mLogSession, "\"" + CGMSpecificOpsControlPointParser.parse(characteristic) + "\" sent");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, RecordAccessControlPointParser.parse(characteristic));
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
Logger.a(mLogSession, "\"" + CGMMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
// Record Access Control Point characteristic
|
||||
int offset = 0;
|
||||
final int opCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 2; // skip the operator
|
||||
// CGM Measurement characteristic
|
||||
final int cgmSize = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
if (cgmSize > 0) {
|
||||
final float cgmValue = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, 2);
|
||||
final int sequenceNumber = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 4);
|
||||
final long timestamp = mSessionStartTime + (sequenceNumber * 60000L); // Sequence number is in minutes since Start Session
|
||||
//This will send callback to CGMSActivity when new concentration value is received from CGMS device
|
||||
final CGMSRecord cgmsRecord = new CGMSRecord(sequenceNumber, cgmValue, timestamp);
|
||||
mRecords.put(cgmsRecord.sequenceNumber, cgmsRecord);
|
||||
mCallbacks.onCGMValueReceived(gatt.getDevice(), cgmsRecord);
|
||||
}
|
||||
}
|
||||
|
||||
if (opCode == OP_CODE_NUMBER_OF_STORED_RECORDS_RESPONSE) {
|
||||
// We've obtained the number of all records
|
||||
final int number = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
@Override
|
||||
protected void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (characteristic.getUuid().equals(RACP_UUID)) {
|
||||
Logger.a(mLogSession, "\"" + RecordAccessControlPointParser.parse(characteristic) + "\" received");
|
||||
|
||||
mCallbacks.onNumberOfRecordsRequested(number);
|
||||
// Record Access Control Point characteristic
|
||||
int offset = 0;
|
||||
final int opCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 2; // skip the operator
|
||||
|
||||
// Request the records
|
||||
if (number > 0) {
|
||||
final BluetoothGattCharacteristic racpCharacteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(racpCharacteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(racpCharacteristic);
|
||||
} else {
|
||||
mCallbacks.onOperationCompleted();
|
||||
}
|
||||
} else if (opCode == OP_CODE_RESPONSE_CODE) {
|
||||
final int requestedOpCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
final int responseCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset + 1);
|
||||
DebugLogger.d(TAG, "Response result for: " + requestedOpCode + " is: " + responseCode);
|
||||
if (opCode == OP_CODE_NUMBER_OF_STORED_RECORDS_RESPONSE) {
|
||||
// We've obtained the number of all records
|
||||
final int number = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
|
||||
switch (responseCode) {
|
||||
case RESPONSE_SUCCESS:
|
||||
if (!mAbort)
|
||||
mCallbacks.onOperationCompleted();
|
||||
else
|
||||
mCallbacks.onOperationAborted();
|
||||
break;
|
||||
case RESPONSE_NO_RECORDS_FOUND:
|
||||
mCallbacks.onOperationCompleted();
|
||||
break;
|
||||
case RESPONSE_OP_CODE_NOT_SUPPORTED:
|
||||
mCallbacks.onOperationNotSupported();
|
||||
break;
|
||||
case RESPONSE_PROCEDURE_NOT_COMPLETED:
|
||||
case RESPONSE_ABORT_UNSUCCESSFUL:
|
||||
default:
|
||||
mCallbacks.onOperationFailed();
|
||||
break;
|
||||
}
|
||||
mAbort = false;
|
||||
}
|
||||
}
|
||||
mCallbacks.onNumberOfRecordsRequested(gatt.getDevice(), number);
|
||||
|
||||
};
|
||||
// Request the records
|
||||
if (number > 0) {
|
||||
final BluetoothGattCharacteristic racpCharacteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(racpCharacteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(racpCharacteristic);
|
||||
} else {
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
}
|
||||
} else if (opCode == OP_CODE_RESPONSE_CODE) {
|
||||
final int requestedOpCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
final int responseCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset + 1);
|
||||
DebugLogger.d(TAG, "Response result for: " + requestedOpCode + " is: " + responseCode);
|
||||
|
||||
/**
|
||||
* Writes given operation parameters to the characteristic
|
||||
*
|
||||
* @param characteristic
|
||||
* the characteristic to write. This must be the Record Access Control Point characteristic
|
||||
* @param opCode
|
||||
* the operation code
|
||||
* @param operator
|
||||
* the operator (see {@link #OPERATOR_NULL} and others
|
||||
* @param params
|
||||
* optional parameters (one for >=, <=, two for the range, none for other operators)
|
||||
*/
|
||||
private void setOpCode(final BluetoothGattCharacteristic characteristic, final int opCode, final int operator, final Integer... params) {
|
||||
final int size = 2 + ((params.length > 0) ? 1 : 0) + params.length * 2; // 1 byte for opCode, 1 for operator, 1 for filter type (if parameters exists) and 2 for each parameter
|
||||
characteristic.setValue(new byte[size]);
|
||||
switch (responseCode) {
|
||||
case RESPONSE_SUCCESS:
|
||||
if (!mAbort)
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
else
|
||||
mCallbacks.onOperationAborted(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_NO_RECORDS_FOUND:
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_OP_CODE_NOT_SUPPORTED:
|
||||
mCallbacks.onOperationNotSupported(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_PROCEDURE_NOT_COMPLETED:
|
||||
case RESPONSE_ABORT_UNSUCCESSFUL:
|
||||
default:
|
||||
mCallbacks.onOperationFailed(gatt.getDevice());
|
||||
break;
|
||||
}
|
||||
mAbort = false;
|
||||
}
|
||||
} else { // uuid == CGM_OPS_CONTROL_POINT_UUID
|
||||
Logger.a(mLogSession, "\"" + CGMSpecificOpsControlPointParser.parse(characteristic) + "\" received");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// write the operation code
|
||||
int offset = 0;
|
||||
characteristic.setValue(opCode, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
/**
|
||||
* Writes given operation parameters to the characteristic
|
||||
*
|
||||
* @param characteristic the characteristic to write. This must be the Record Access Control Point characteristic
|
||||
* @param opCode the operation code
|
||||
* @param operator the operator (see {@link #OPERATOR_NULL} and others
|
||||
* @param params optional parameters (one for >=, <=, two for the range, none for other operators)
|
||||
*/
|
||||
private void setOpCode(final BluetoothGattCharacteristic characteristic, final int opCode, final int operator, final Integer... params) {
|
||||
final int size = 2 + ((params.length > 0) ? 1 : 0) + params.length * 2; // 1 byte for opCode, 1 for operator, 1 for filter type (if parameters exists) and 2 for each parameter
|
||||
characteristic.setValue(new byte[size]);
|
||||
|
||||
// write the operator. This is always present but may be equal to OPERATOR_NULL
|
||||
characteristic.setValue(operator, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
// write the operation code
|
||||
int offset = 0;
|
||||
characteristic.setValue(opCode, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
|
||||
// if parameters exists, append them. Parameters should be sorted from minimum to maximum. Currently only one or two params are allowed
|
||||
if (params.length > 0) {
|
||||
// our implementation use only sequence number as a filer type
|
||||
characteristic.setValue(FILTER_TYPE_SEQUENCE_NUMBER, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
// write the operator. This is always present but may be equal to OPERATOR_NULL
|
||||
characteristic.setValue(operator, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
|
||||
for (final Integer i : params) {
|
||||
characteristic.setValue(i, BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if parameters exists, append them. Parameters should be sorted from minimum to maximum. Currently only one or two params are allowed
|
||||
if (params.length > 0) {
|
||||
// our implementation use only sequence number as a filer type
|
||||
characteristic.setValue(FILTER_TYPE_SEQUENCE_NUMBER, BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
offset += 1;
|
||||
|
||||
/**
|
||||
* 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 ({@link #RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
for (final Integer i : params) {
|
||||
characteristic.setValue(i, BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
/**
|
||||
* Returns a list of CGM records obtained from this device. The key in the array is the
|
||||
*/
|
||||
public SparseArray<CGMSRecord> getRecords() {
|
||||
return mRecords;
|
||||
}
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_LAST_RECORD);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
/**
|
||||
* Clears the records list locally
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
mCallbacks.onDatasetClear(mBluetoothDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all records as a sparse array where sequence number is the key.
|
||||
*
|
||||
* @return the records list
|
||||
*/
|
||||
public SparseArray<CGMSRecord> getRecords() {
|
||||
return mRecords;
|
||||
}
|
||||
/**
|
||||
* 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 ({@link #RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
/**
|
||||
* Clears the records list locally
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
mCallbacks.onDatasetChanged();
|
||||
}
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
/**
|
||||
* Sends abort operation signal to the device
|
||||
*/
|
||||
public void abort() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_LAST_RECORD);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
mAbort = true;
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_ABORT_OPERATION, OPERATOR_NULL);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
/**
|
||||
* 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 ({@link #RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
/**
|
||||
* 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 ({@link #RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_FIRST_RECORD);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_FIRST_RECORD);
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
/**
|
||||
* Sends abort operation signal to the device
|
||||
*/
|
||||
public void abort() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device. Initially we want to notify him/her about the number of the records so the {@link #OP_CODE_REPORT_NUMBER_OF_RECORDS} is send. The
|
||||
* data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control Point indication with status code ({@link #RESPONSE_SUCCESS} or other in case of
|
||||
* error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
mAbort = true;
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_ABORT_OPERATION, OPERATOR_NULL);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device. Initially we want to notify him/her about the number of the records so the {@link #OP_CODE_REPORT_NUMBER_OF_RECORDS} is send. The
|
||||
* data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control Point indication with status code ({@link #RESPONSE_SUCCESS} or other in case of
|
||||
* error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_NUMBER_OF_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
public void deleteAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_NUMBER_OF_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device. Initially we want to notify him/her about the number of the records so the {@link #OP_CODE_REPORT_NUMBER_OF_RECORDS} is send. The
|
||||
* data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control Point indication with status code ({@link #RESPONSE_SUCCESS} or other in case of
|
||||
* error.
|
||||
*/
|
||||
public void refreshRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_DELETE_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
if (mRecords.size() == 0) {
|
||||
getAllRecords();
|
||||
} else {
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
// obtain the last sequence number
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_GREATER_THEN_OR_EQUAL, sequenceNumber);
|
||||
writeCharacteristic(characteristic);
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_DELETE_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
/**
|
||||
@@ -29,26 +31,22 @@ import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
*/
|
||||
public interface CGMSManagerCallbacks extends BleManagerCallbacks {
|
||||
/**
|
||||
* Called when new CGM value has been obtained from the sensor
|
||||
*
|
||||
* @param value
|
||||
* the new value
|
||||
* Called when new CGM value has been obtained from the sensor.
|
||||
*/
|
||||
public void onCGMValueReceived(float value, String timeStamp);
|
||||
void onCGMValueReceived(final BluetoothDevice device, final CGMSRecord record);
|
||||
|
||||
void onOperationStarted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationStarted();
|
||||
void onOperationCompleted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationCompleted();
|
||||
void onOperationFailed(final BluetoothDevice device);
|
||||
|
||||
public void onOperationFailed();
|
||||
void onOperationAborted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationAborted();
|
||||
void onOperationNotSupported(final BluetoothDevice device);
|
||||
|
||||
public void onOperationNotSupported();
|
||||
void onDatasetClear(final BluetoothDevice device);
|
||||
|
||||
public void onDatasetChanged();
|
||||
|
||||
public void onNumberOfRecordsRequested(final int value);
|
||||
void onNumberOfRecordsRequested(final BluetoothDevice device, final int value);
|
||||
|
||||
}
|
||||
|
||||
@@ -3,31 +3,27 @@ package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Created by rora on 02.09.2016.
|
||||
*/
|
||||
public class CGMSRecord implements Parcelable{
|
||||
|
||||
/** Record sequence number */
|
||||
/** Record sequence number. */
|
||||
protected int sequenceNumber;
|
||||
/** The base time of the measurement */
|
||||
protected Calendar time;
|
||||
/** Time offset of the record */
|
||||
protected String timeStamp;
|
||||
protected float reading;
|
||||
/** The base time of the measurement (start time + sequenceNumber of minutes). */
|
||||
protected long timestamp;
|
||||
/** The glucose concentration in mg/dL. */
|
||||
protected float glucoseConcentration;
|
||||
|
||||
protected CGMSRecord(float cgmsValue, String timeStamp) {
|
||||
sequenceNumber = 0;
|
||||
this.timeStamp = timeStamp;
|
||||
this.reading = cgmsValue;
|
||||
protected CGMSRecord(int sequenceNumber, float glucoseConcentration, long timestamp) {
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.glucoseConcentration = glucoseConcentration;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
protected CGMSRecord(Parcel in) {
|
||||
sequenceNumber = in.readInt();
|
||||
timeStamp = in.readString();
|
||||
reading = in.readFloat();
|
||||
this.sequenceNumber = in.readInt();
|
||||
this.glucoseConcentration = in.readFloat();
|
||||
this.timestamp = in.readLong();
|
||||
}
|
||||
|
||||
public static final Creator<CGMSRecord> CREATOR = new Creator<CGMSRecord>() {
|
||||
@@ -50,7 +46,7 @@ public class CGMSRecord implements Parcelable{
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeInt(sequenceNumber);
|
||||
parcel.writeString(timeStamp);
|
||||
parcel.writeFloat(reading);
|
||||
parcel.writeFloat(glucoseConcentration);
|
||||
parcel.writeLong(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,87 +1,82 @@
|
||||
package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
/**
|
||||
* Created by rora on 02.09.2016.
|
||||
*/
|
||||
public class CGMSRecordsAdapter extends BaseAdapter {
|
||||
private final static SimpleDateFormat mTimeFormat = new SimpleDateFormat("dd.MM.YYYY HH:mm:ss", Locale.US);
|
||||
|
||||
private SparseArray<CGMSRecord> mRecords;
|
||||
private LayoutInflater mInflator;
|
||||
private Context context;
|
||||
private List<CGMSRecord> mRecords;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
public CGMSRecordsAdapter(Context context) {
|
||||
super();
|
||||
mRecords = new SparseArray<>();
|
||||
this.context = context;
|
||||
mInflator = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
public CGMSRecordsAdapter(final Context context) {
|
||||
mRecords = new ArrayList<>();
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mRecords.size();
|
||||
}
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mRecords.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
return i;
|
||||
}
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.activity_feature_cgms_item, parent, false);
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.concentration = (TextView) convertView.findViewById(R.id.cgms_concentration);
|
||||
viewHolder.time = (TextView) convertView.findViewById(R.id.time);
|
||||
viewHolder.details = (TextView) convertView.findViewById(R.id.details);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = mInflator.inflate(R.layout.activity_feature_cgms_item, null);
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.concentration = (TextView) convertView.findViewById(R.id.cgms_concentration);
|
||||
viewHolder.time = (TextView) convertView.findViewById(R.id.time);
|
||||
viewHolder.details = (TextView) convertView.findViewById(R.id.details);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
final CGMSRecord cgmsRecord = mRecords.get(position);
|
||||
viewHolder.concentration.setText(String.valueOf(cgmsRecord.glucoseConcentration));
|
||||
viewHolder.details.setText(viewHolder.details.getResources().getString(R.string.cgms_details, cgmsRecord.sequenceNumber));
|
||||
viewHolder.time.setText(mTimeFormat.format(new Date(cgmsRecord.timestamp)));
|
||||
|
||||
final CGMSRecord cgmsRecord = mRecords.get(position);
|
||||
final String concentration = String.valueOf(cgmsRecord.reading);
|
||||
return convertView;
|
||||
}
|
||||
|
||||
if (concentration != null && concentration.length() > 0) {
|
||||
viewHolder.concentration.setText(concentration /*+ " " + context.getString(R.string.cgms_value_unit*/);
|
||||
viewHolder.time.setText(cgmsRecord.timeStamp);
|
||||
}
|
||||
public void addItem(final CGMSRecord record) {
|
||||
mRecords.add(record);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
}
|
||||
|
||||
public void addItem(CGMSRecord record) {
|
||||
mRecords.put(mRecords.size(), record);
|
||||
}
|
||||
|
||||
public SparseArray<CGMSRecord> getValues() {
|
||||
return mRecords;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
TextView time;
|
||||
TextView details;
|
||||
TextView concentration;
|
||||
}
|
||||
private static class ViewHolder {
|
||||
TextView time;
|
||||
TextView details;
|
||||
TextView concentration;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -22,7 +23,8 @@ import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
|
||||
*/
|
||||
public class CGMService extends BleProfileService implements CGMSManagerCallbacks {
|
||||
private static final String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.cgms.ACTION_DISCONNECT";
|
||||
public static final String BROADCAST_CGMS_VALUES = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_CGMS_VALUES";
|
||||
public static final String BROADCAST_NEW_CGMS_VALUE = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_NEW_CGMS_VALUE";
|
||||
public static final String BROADCAST_DATA_SET_CLEAR = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_DATA_SET_CLEAR";
|
||||
public static final String OPERATION_STARTED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_STARTED";
|
||||
public static final String OPERATION_COMPLETED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_COMPLETED";
|
||||
public static final String OPERATION_SUPPORTED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_SUPPORTED";
|
||||
@@ -30,7 +32,6 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
public static final String OPERATION_FAILED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_FAILED";
|
||||
public static final String OPERATION_ABORTED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_ABORTED";
|
||||
public static final String EXTRA_CGMS_RECORD = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_CGMS_RECORD";
|
||||
public static final String BROADCAST_DATA_SET_CHANGED = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_DATA_SET_CHANGED";
|
||||
public static final String EXTRA_DATA = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_DATA";
|
||||
|
||||
private final static int NOTIFICATION_ID = 229;
|
||||
@@ -39,54 +40,32 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
|
||||
private CGMSManager mManager;
|
||||
private final LocalBinder mBinder = new CGMSBinder();
|
||||
private SparseArray<CGMSRecord> mRecords = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bonded activity to operate with the RSC sensor
|
||||
*/
|
||||
|
||||
public class CGMSBinder extends LocalBinder {
|
||||
public SparseArray<CGMSRecord> getCgmsRecords() {
|
||||
return mRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ({@link CGMSManager#RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
clear();
|
||||
if(mManager != null)
|
||||
mManager.getLastRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all records as a sparse array where sequence number is the key.
|
||||
*
|
||||
* @return the records list
|
||||
*/
|
||||
public SparseArray<CGMSRecord> getRecords() {
|
||||
return mRecords;
|
||||
return mManager.getRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the records list locally
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
if (mManager != null)
|
||||
mManager.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends abort operation signal to the device
|
||||
*/
|
||||
public void abort() {
|
||||
|
||||
if(mManager != null)
|
||||
mManager.abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 ({@link CGMSManager# RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
@@ -95,18 +74,48 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device. Initially we want to notify him/her about the number of the records so the {@link CGMSManager#OP_CODE_REPORT_NUMBER_OF_RECORDS} is send. The
|
||||
* data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control Point indication with status code ({@link CGMSManager#RESPONSE_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 ({@link CGMSManager#RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if(mManager != null)
|
||||
mManager.getLastRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device.
|
||||
* Initially we want to notify user about the number of the records so the {@link CGMSManager#OP_CODE_REPORT_NUMBER_OF_RECORDS} is send.
|
||||
* The data will be returned to Glucose Measurement characteristic as a series of notifications followed by Record Access Control Point
|
||||
* indication with status code ({@link CGMSManager#RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
clear();
|
||||
if(mManager != null)
|
||||
mManager.getAllRecords();
|
||||
}
|
||||
|
||||
public void deleteAllRecords() {
|
||||
/**
|
||||
* Sends the request to obtain all records from glucose device with sequence number greater than the last one already obtained.
|
||||
* The data will be returned to Glucose Measurement characteristic as a series of notifications followed by Record Access Control Point
|
||||
* indication with status code ({@link CGMSManager#RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void refreshRecords() {
|
||||
if (mManager != null)
|
||||
mManager.refreshRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends abort operation signal to the device
|
||||
*/
|
||||
public void abort() {
|
||||
if(mManager != null)
|
||||
mManager.abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Delete op code with All stored records parameter. This method may not be supported by the SDK sample.
|
||||
*/
|
||||
public void deleteAllRecords() {
|
||||
if(mManager != null)
|
||||
mManager.deleteAllRecords();
|
||||
}
|
||||
@@ -212,56 +221,62 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCGMValueReceived(float value, String timeStamp) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CGMS_VALUES);
|
||||
CGMSRecord cgmsRecord = new CGMSRecord(value, timeStamp);
|
||||
broadcast.putExtra(EXTRA_CGMS_RECORD, cgmsRecord);
|
||||
public void onCGMValueReceived(final BluetoothDevice device, final CGMSRecord record) {
|
||||
final Intent broadcast = new Intent(BROADCAST_NEW_CGMS_VALUE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_CGMS_RECORD, record);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
mRecords.put(mRecords.size(), cgmsRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationStarted() {
|
||||
public void onOperationStarted(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(OPERATION_STARTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, true);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationCompleted() {
|
||||
public void onOperationCompleted(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(OPERATION_COMPLETED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, true);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationFailed() {
|
||||
public void onOperationFailed(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(OPERATION_FAILED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, true);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationAborted() {
|
||||
public void onOperationAborted(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(OPERATION_ABORTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, true);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationNotSupported() {
|
||||
public void onOperationNotSupported(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(OPERATION_NOT_SUPPORTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, false);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetChanged() {
|
||||
|
||||
public void onDatasetClear(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DATA_SET_CLEAR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberOfRecordsRequested(int value) {
|
||||
public void onNumberOfRecordsRequested(final BluetoothDevice device, int value) {
|
||||
showToast(getString(R.string.gls_progress, value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.csc;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -33,6 +34,7 @@ import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.view.Menu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
@@ -172,7 +174,7 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// not used
|
||||
}
|
||||
|
||||
@@ -186,35 +188,35 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
// pass through intended
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S:
|
||||
if (distance < 1000) { // 1 km in m
|
||||
mDistanceView.setText(String.format("%.0f", distance));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
} else {
|
||||
mDistanceView.setText(String.format("%.2f", distance / 1000.0f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 1000.0f));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_km);
|
||||
}
|
||||
|
||||
mTotalDistanceView.setText(String.format("%.2f", totalDistance / 1000.0f));
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f));
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH:
|
||||
speed = speed * 2.2369f;
|
||||
if (distance < 1760) { // 1 mile in yrs
|
||||
mDistanceView.setText(String.format("%.0f", distance));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_yd);
|
||||
} else {
|
||||
mDistanceView.setText(String.format("%.2f", distance / 1760.0f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 1760.0f));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_mile);
|
||||
}
|
||||
|
||||
mTotalDistanceView.setText(String.format("%.2f", totalDistance / 1609.31f));
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f));
|
||||
break;
|
||||
}
|
||||
|
||||
mSpeedView.setText(String.format("%.1f", speed));
|
||||
mSpeedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
}
|
||||
|
||||
private void onGearRatioUpdate(final float ratio, final int cadence) {
|
||||
mGearRatioView.setText(String.format("%.1f", ratio));
|
||||
mCadenceView.setText(String.format("%d", cadence));
|
||||
mGearRatioView.setText(String.format(Locale.US, "%.1f", ratio));
|
||||
mCadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
|
||||
@@ -63,7 +63,7 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableNotificationsRequest(mCSCMeasurementCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mCSCMeasurementCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, CSCMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + CSCMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
// Decode the new data
|
||||
int offset = 0;
|
||||
@@ -102,7 +101,7 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
|
||||
offset += 2;
|
||||
|
||||
// Notify listener about the new measurement
|
||||
mCallbacks.onWheelMeasurementReceived(wheelRevolutions, lastWheelEventTime);
|
||||
mCallbacks.onWheelMeasurementReceived(gatt.getDevice(), wheelRevolutions, lastWheelEventTime);
|
||||
}
|
||||
|
||||
if (crankRevPreset) {
|
||||
@@ -113,7 +112,7 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
|
||||
// offset += 2;
|
||||
|
||||
// Notify listener about the new measurement
|
||||
mCallbacks.onCrankMeasurementReceived(crankRevolutions, lastCrankEventTime);
|
||||
mCallbacks.onCrankMeasurementReceived(gatt.getDevice(), crankRevolutions, lastCrankEventTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,12 +21,14 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.csc;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface CSCManagerCallbacks extends BleManagerCallbacks {
|
||||
public static final int NOT_AVAILABLE = -1;
|
||||
int NOT_AVAILABLE = -1;
|
||||
|
||||
public void onWheelMeasurementReceived(final int wheelRevolutions, final int wheelCrankEventTime);
|
||||
void onWheelMeasurementReceived(final BluetoothDevice device, final int wheelRevolutions, final int wheelCrankEventTime);
|
||||
|
||||
public void onCrankMeasurementReceived(final int crankRevolutions, final int lastCrankEventTime);
|
||||
void onCrankMeasurementReceived(final BluetoothDevice device, final int crankRevolutions, final int lastCrankEventTime);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.csc;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -126,7 +127,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWheelMeasurementReceived(final int wheelRevolutions, final int lastWheelEventTime) {
|
||||
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);
|
||||
@@ -151,6 +152,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
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);
|
||||
@@ -161,7 +163,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrankMeasurementReceived(int crankRevolutions, int lastCrankEventTime) {
|
||||
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)
|
||||
@@ -179,6 +181,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
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);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.gls;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseArray;
|
||||
import android.view.MenuInflater;
|
||||
@@ -158,46 +159,46 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationStarted() {
|
||||
public void onOperationStarted(final BluetoothDevice device) {
|
||||
setOperationInProgress(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationCompleted() {
|
||||
public void onOperationCompleted(final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationAborted() {
|
||||
public void onOperationAborted(final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationNotSupported() {
|
||||
public void onOperationNotSupported(final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
showToast(R.string.gls_operation_not_supported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationFailed() {
|
||||
public void onOperationFailed(final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
showToast(R.string.gls_operation_failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String message, final int errorCode) {
|
||||
super.onError(message, errorCode);
|
||||
onOperationFailed();
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
super.onError(device, message, errorCode);
|
||||
onOperationFailed(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetChanged() {
|
||||
public void onDatasetChanged(final BluetoothDevice device) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -215,7 +216,7 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberOfRecordsRequested(final int value) {
|
||||
public void onNumberOfRecordsRequested(final BluetoothDevice device, final int value) {
|
||||
showToast(getString(R.string.gls_progress, value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableNotificationsRequest(mGlucoseMeasurementCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mGlucoseMeasurementCharacteristic));
|
||||
if (mGlucoseMeasurementContextCharacteristic != null)
|
||||
requests.push(Request.newEnableNotificationsRequest(mGlucoseMeasurementContextCharacteristic));
|
||||
requests.push(Request.newEnableIndicationsRequest(mRecordAccessControlPointCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mGlucoseMeasurementContextCharacteristic));
|
||||
requests.add(Request.newEnableIndicationsRequest(mRecordAccessControlPointCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -160,12 +160,16 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
|
||||
protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
Logger.a(mLogSession, "\"" + RecordAccessControlPointParser.parse(characteristic) + "\" sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
final UUID uuid = characteristic.getUuid();
|
||||
|
||||
if (GM_CHARACTERISTIC.equals(uuid)) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, GlucoseMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + GlucoseMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
int offset = 0;
|
||||
final int flags = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
@@ -237,12 +241,11 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
|
||||
// if there is no context information following the measurement data, notify callback about the new record
|
||||
if (!contextInfoFollows)
|
||||
mCallbacks.onDatasetChanged();
|
||||
mCallbacks.onDatasetChanged(gatt.getDevice());
|
||||
}
|
||||
});
|
||||
} else if (GM_CONTEXT_CHARACTERISTIC.equals(uuid)) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, GlucoseMeasurementContextParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + GlucoseMeasurementContextParser.parse(characteristic) + "\" received");
|
||||
|
||||
int offset = 0;
|
||||
final int flags = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
@@ -308,14 +311,13 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
}
|
||||
|
||||
// notify callback about the new record
|
||||
mCallbacks.onDatasetChanged();
|
||||
mCallbacks.onDatasetChanged(gatt.getDevice());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, RecordAccessControlPointParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + RecordAccessControlPointParser.parse(characteristic) + "\" received");
|
||||
|
||||
// Record Access Control Point characteristic
|
||||
int offset = 0;
|
||||
@@ -326,7 +328,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
// We've obtained the number of all records
|
||||
final int number = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
|
||||
mCallbacks.onNumberOfRecordsRequested(number);
|
||||
mCallbacks.onNumberOfRecordsRequested(gatt.getDevice(), number);
|
||||
|
||||
// Request the records
|
||||
if (number > 0) {
|
||||
@@ -334,7 +336,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
setOpCode(racpCharacteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
writeCharacteristic(racpCharacteristic);
|
||||
} else {
|
||||
mCallbacks.onOperationCompleted();
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
}
|
||||
} else if (opCode == OP_CODE_RESPONSE_CODE) {
|
||||
final int requestedOpCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
@@ -344,20 +346,20 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
switch (responseCode) {
|
||||
case RESPONSE_SUCCESS:
|
||||
if (!mAbort)
|
||||
mCallbacks.onOperationCompleted();
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
else
|
||||
mCallbacks.onOperationAborted();
|
||||
mCallbacks.onOperationAborted(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_NO_RECORDS_FOUND:
|
||||
mCallbacks.onOperationCompleted();
|
||||
mCallbacks.onOperationCompleted(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_OP_CODE_NOT_SUPPORTED:
|
||||
mCallbacks.onOperationNotSupported();
|
||||
mCallbacks.onOperationNotSupported(gatt.getDevice());
|
||||
break;
|
||||
case RESPONSE_PROCEDURE_NOT_COMPLETED:
|
||||
case RESPONSE_ABORT_UNSUCCESSFUL:
|
||||
default:
|
||||
mCallbacks.onOperationFailed();
|
||||
mCallbacks.onOperationFailed(gatt.getDevice());
|
||||
break;
|
||||
}
|
||||
mAbort = false;
|
||||
@@ -416,7 +418,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
mCallbacks.onDatasetChanged();
|
||||
mCallbacks.onDatasetChanged(mBluetoothDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,7 +430,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_LAST_RECORD);
|
||||
@@ -444,7 +446,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_STORED_RECORDS, OPERATOR_FIRST_RECORD);
|
||||
@@ -461,7 +463,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_REPORT_NUMBER_OF_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
@@ -483,7 +485,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
if (mRecords.size() == 0) {
|
||||
getAllRecords();
|
||||
} else {
|
||||
mCallbacks.onOperationStarted();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
// obtain the last sequence number
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
@@ -519,7 +521,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted();
|
||||
mCallbacks.onOperationStarted(mBluetoothDevice);
|
||||
|
||||
final BluetoothGattCharacteristic characteristic = mRecordAccessControlPointCharacteristic;
|
||||
setOpCode(characteristic, OP_CODE_DELETE_STORED_RECORDS, OPERATOR_ALL_RECORDS);
|
||||
|
||||
@@ -21,23 +21,22 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.gls;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface GlucoseManagerCallbacks extends BleManagerCallbacks {
|
||||
public static final int UNIT_mmHG = 0;
|
||||
public static final int UNIT_kPa = 1;
|
||||
void onOperationStarted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationStarted();
|
||||
void onOperationCompleted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationCompleted();
|
||||
void onOperationFailed(final BluetoothDevice device);
|
||||
|
||||
public void onOperationFailed();
|
||||
void onOperationAborted(final BluetoothDevice device);
|
||||
|
||||
public void onOperationAborted();
|
||||
void onOperationNotSupported(final BluetoothDevice device);
|
||||
|
||||
public void onOperationNotSupported();
|
||||
void onDatasetChanged(final BluetoothDevice device);
|
||||
|
||||
public void onDatasetChanged();
|
||||
|
||||
public void onNumberOfRecordsRequested(final int value);
|
||||
void onNumberOfRecordsRequested(final BluetoothDevice device, final int value);
|
||||
}
|
||||
|
||||
@@ -210,29 +210,29 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady() {
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
startShowGraph();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHRSensorPositionFound(final String position) {
|
||||
public void onHRSensorPositionFound(final BluetoothDevice device, final String position) {
|
||||
setHRSPositionOnView(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHRValueReceived(int value) {
|
||||
public void onHRValueReceived(final BluetoothDevice device, int value) {
|
||||
mHrmValue = value;
|
||||
setHRSValueOnView(mHrmValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -77,8 +77,8 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
if (mHRLocationCharacteristic != null)
|
||||
requests.push(Request.newReadRequest(mHRLocationCharacteristic));
|
||||
requests.push(Request.newEnableNotificationsRequest(mHRCharacteristic));
|
||||
requests.add(Request.newReadRequest(mHRLocationCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mHRCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -102,12 +102,11 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, BodySensorLocationParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + 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(sensorPosition);
|
||||
mCallbacks.onHRSensorPositionFound(gatt.getDevice(), sensorPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,8 +117,7 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, HeartRateMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + HeartRateMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
int hrValue;
|
||||
if (isHeartRateInUINT16(characteristic.getValue()[0])) {
|
||||
@@ -128,7 +126,7 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
|
||||
hrValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);
|
||||
}
|
||||
//This will send callback to HRSActivity when new HR value is received from HR device
|
||||
mCallbacks.onHRValueReceived(hrValue);
|
||||
mCallbacks.onHRValueReceived(gatt.getDevice(), hrValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,23 +21,27 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.hrs;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
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
|
||||
*/
|
||||
public void onHRSensorPositionFound(String 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
|
||||
*/
|
||||
public void onHRValueReceived(int value);
|
||||
void onHRValueReceived(final BluetoothDevice device, int value);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.hts;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -179,7 +180,7 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.RSCBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public class HTSManager extends BleManager<HTSManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableIndicationsRequest(mHTCharacteristic));
|
||||
requests.add(Request.newEnableIndicationsRequest(mHTCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -93,12 +93,11 @@ public class HTSManager extends BleManager<HTSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, TemperatureMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + TemperatureMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
try {
|
||||
final double tempValue = decodeTemperature(characteristic.getValue());
|
||||
mCallbacks.onHTValueReceived(tempValue);
|
||||
mCallbacks.onHTValueReceived(gatt.getDevice(), tempValue);
|
||||
} catch (Exception e) {
|
||||
DebugLogger.e(TAG, "Invalid temperature value", e);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.hts;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
/**
|
||||
@@ -30,10 +32,11 @@ public interface HTSManagerCallbacks extends BleManagerCallbacks {
|
||||
|
||||
/**
|
||||
* Called when Health Thermometer value has been received
|
||||
*
|
||||
*
|
||||
* @param device the bluetooth device from which the value was obtained
|
||||
* @param value
|
||||
* the new value
|
||||
*/
|
||||
public void onHTValueReceived(double value);
|
||||
void onHTValueReceived(final BluetoothDevice device, double value);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.hts;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -106,8 +107,9 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHTValueReceived(final double value) {
|
||||
public void onHTValueReceived(final BluetoothDevice device, final double value) {
|
||||
final Intent broadcast = new Intent(BROADCAST_HTS_MEASUREMENT);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_TEMPERATURE, value);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
@@ -169,5 +171,4 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
stopSelf();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.parser;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class CGMMeasurementParser {
|
||||
private static final int FLAGS_CGM_TREND_INFO_PRESENT = 1;
|
||||
private static final int FLAGS_CGM_QUALITY_PRESENT = 1 << 1;
|
||||
private static final int FLAGS_SENSOR_STATUS_ANNUNCIATION_WARNING_OCTET_PRESENT = 1 << 2;
|
||||
private static final int FLAGS_SENSOR_STATUS_ANNUNCIATION_CAL_TEMP_OCTET_PRESENT = 1 << 3;
|
||||
private static final int FLAGS_SENSOR_STATUS_ANNUNCIATION_STATUS_OCTET_PRESENT = 1 << 4;
|
||||
|
||||
private static final int SSA_SESSION_STOPPED = 1;
|
||||
private static final int SSA_DEVICE_BATTERY_LOW = 1 << 1;
|
||||
private static final int SSA_SENSOR_TYPE_INCORRECT = 1 << 2;
|
||||
private static final int SSA_SENSOR_MALFUNCTION = 1 << 3;
|
||||
private static final int SSA_DEVICE_SPEC_ALERT = 1 << 4;
|
||||
private static final int SSA_GENERAL_DEVICE_FAULT = 1 << 5;
|
||||
|
||||
private static final int SSA_TIME_SYNC_REQUIRED = 1 << 8;
|
||||
private static final int SSA_CALIBRATION_NOT_ALLOWED = 1 << 9;
|
||||
private static final int SSA_CALIBRATION_RECOMMENDED = 1 << 10;
|
||||
private static final int SSA_CALIBRATION_REQUIRED = 1 << 11;
|
||||
private static final int SSA_SENSOR_TEMP_TOO_HIGH = 1 << 12;
|
||||
private static final int SSA_SENSOR_TEMP_TOO_LOW = 1 << 13;
|
||||
|
||||
private static final int SSA_RESULT_LOWER_THAN_PATIENT_LOW_LEVEL = 1 << 16;
|
||||
private static final int SSA_RESULT_HIGHER_THAN_PATIENT_HIGH_LEVEL = 1 << 17;
|
||||
private static final int SSA_RESULT_LOWER_THAN_HYPO_LEVEL = 1 << 18;
|
||||
private static final int SSA_RESULT_HIGHER_THAN_HYPER_LEVEL = 1 << 19;
|
||||
private static final int SSA_SENSOR_RATE_OF_DECREASE_EXCEEDED = 1 << 20;
|
||||
private static final int SSA_SENSOR_RATE_OF_INCREASE_EXCEEDED = 1 << 21;
|
||||
private static final int SSA_RESULT_LOWER_THAN_DEVICE_CAN_PROCESS = 1 << 22;
|
||||
private static final int SSA_RESULT_HIGHER_THAN_DEVICE_CAN_PROCESS = 1 << 23;
|
||||
|
||||
public static String parse(final BluetoothGattCharacteristic characteristic) {
|
||||
int offset = 0;
|
||||
// Read size and flags bytes
|
||||
final int size = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
final int flags = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
|
||||
/*
|
||||
* false CGM Trend Information is not preset
|
||||
* true CGM Trend Information is preset
|
||||
*/
|
||||
final boolean cgmTrendInformationPresent = (flags & FLAGS_CGM_TREND_INFO_PRESENT) > 0;
|
||||
|
||||
/*
|
||||
* false CGM Quality is not preset
|
||||
* true CGM Quality is preset
|
||||
*/
|
||||
final boolean cgmQualityPresent = (flags & FLAGS_CGM_QUALITY_PRESENT) > 0;
|
||||
|
||||
/*
|
||||
* false Sensor Status Annunciation - Warning-Octet is not preset
|
||||
* true Sensor Status Annunciation - Warning-Octet is preset
|
||||
*/
|
||||
final boolean ssaWarningOctetPresent = (flags & FLAGS_SENSOR_STATUS_ANNUNCIATION_WARNING_OCTET_PRESENT) > 0;
|
||||
|
||||
/*
|
||||
* false Sensor Status Annunciation - Calibration/Temp-Octet is not preset
|
||||
* true Sensor Status Annunciation - Calibration/Temp-Octet is preset
|
||||
*/
|
||||
final boolean ssaCalTempOctetPresent = (flags & FLAGS_SENSOR_STATUS_ANNUNCIATION_CAL_TEMP_OCTET_PRESENT) > 0;
|
||||
|
||||
/*
|
||||
* false Sensor Status Annunciation - Status-Octet is not preset
|
||||
* true Sensor Status Annunciation - Status-Octet is preset
|
||||
*/
|
||||
final boolean ssaStatusOctetPresent = (flags & FLAGS_SENSOR_STATUS_ANNUNCIATION_STATUS_OCTET_PRESENT) > 0;
|
||||
|
||||
// Read CGM Glucose Concentration
|
||||
final float glucoseConcentration = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 2;
|
||||
|
||||
// Read time offset
|
||||
final int timeOffset = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Glucose concentration: ").append(glucoseConcentration).append(" mg/dL\n");
|
||||
builder.append("Sequence number: ").append(timeOffset).append(" (minutes since start)\n");
|
||||
|
||||
if (ssaWarningOctetPresent) {
|
||||
final int ssaWarningOctet = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
builder.append("Warnings:\n");
|
||||
if ((ssaWarningOctet & SSA_SESSION_STOPPED) > 0)
|
||||
builder.append("- Session Stopped\n");
|
||||
if ((ssaWarningOctet & SSA_DEVICE_BATTERY_LOW) > 0)
|
||||
builder.append("- Device Battery Low\n");
|
||||
if ((ssaWarningOctet & SSA_SENSOR_TYPE_INCORRECT) > 0)
|
||||
builder.append("- Sensor Type Incorrect\n");
|
||||
if ((ssaWarningOctet & SSA_SENSOR_MALFUNCTION) > 0)
|
||||
builder.append("- Sensor Malfunction\n");
|
||||
if ((ssaWarningOctet & SSA_DEVICE_SPEC_ALERT) > 0)
|
||||
builder.append("- Device Specific Alert\n");
|
||||
if ((ssaWarningOctet & SSA_GENERAL_DEVICE_FAULT) > 0)
|
||||
builder.append("- General Device Fault\n");
|
||||
}
|
||||
|
||||
if (ssaCalTempOctetPresent) {
|
||||
final int ssaCalTempOctet = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
builder.append("Cal/Temp Info:\n");
|
||||
if ((ssaCalTempOctet & SSA_TIME_SYNC_REQUIRED) > 0)
|
||||
builder.append("- Time Synchronization Required\n");
|
||||
if ((ssaCalTempOctet & SSA_CALIBRATION_NOT_ALLOWED) > 0)
|
||||
builder.append("- Calibration Not Allowed\n");
|
||||
if ((ssaCalTempOctet & SSA_CALIBRATION_RECOMMENDED) > 0)
|
||||
builder.append("- Calibration Recommended\n");
|
||||
if ((ssaCalTempOctet & SSA_CALIBRATION_REQUIRED) > 0)
|
||||
builder.append("- Calibration Required\n");
|
||||
if ((ssaCalTempOctet & SSA_SENSOR_TEMP_TOO_HIGH) > 0)
|
||||
builder.append("- Sensor Temp Too High\n");
|
||||
if ((ssaCalTempOctet & SSA_SENSOR_TEMP_TOO_LOW) > 0)
|
||||
builder.append("- Sensor Temp Too Low\n");
|
||||
}
|
||||
|
||||
if (ssaStatusOctetPresent) {
|
||||
final int ssaStatusOctet = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
builder.append("Status:\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_LOWER_THAN_PATIENT_LOW_LEVEL) > 0)
|
||||
builder.append("- Result Lower then Patient Low Level\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_HIGHER_THAN_PATIENT_HIGH_LEVEL) > 0)
|
||||
builder.append("- Result Higher then Patient High Level\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_LOWER_THAN_HYPO_LEVEL) > 0)
|
||||
builder.append("- Result Lower then Hypo Level\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_HIGHER_THAN_HYPER_LEVEL) > 0)
|
||||
builder.append("- Result Higher then Hyper Level\n");
|
||||
if ((ssaStatusOctet & SSA_SENSOR_RATE_OF_DECREASE_EXCEEDED) > 0)
|
||||
builder.append("- Sensor Rate of Decrease Exceeded\n");
|
||||
if ((ssaStatusOctet & SSA_SENSOR_RATE_OF_INCREASE_EXCEEDED) > 0)
|
||||
builder.append("- Sensor Rate of Increase Exceeded\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_LOWER_THAN_DEVICE_CAN_PROCESS) > 0)
|
||||
builder.append("- Result Lower then Device Can Process\n");
|
||||
if ((ssaStatusOctet & SSA_RESULT_HIGHER_THAN_DEVICE_CAN_PROCESS) > 0)
|
||||
builder.append("- Result Higher then Device Can Process\n");
|
||||
}
|
||||
|
||||
if (cgmTrendInformationPresent) {
|
||||
final float trend = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 2;
|
||||
builder.append("Trend: ").append(trend).append(" mg/dL/min\n");
|
||||
}
|
||||
|
||||
if (cgmQualityPresent) {
|
||||
final float quality = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 2;
|
||||
builder.append("Quality: ").append(quality).append("%\n");
|
||||
}
|
||||
|
||||
if (size > offset + 1) {
|
||||
final int crc = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
// offset += 2;
|
||||
builder.append(String.format(Locale.US, "E2E-CRC: 0x%04X\n", crc));
|
||||
}
|
||||
builder.setLength(builder.length() - 1); // Remove last \n
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.parser;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
public class CGMSpecificOpsControlPointParser {
|
||||
private final static int OP_SET_CGM_COMMUNICATION_INTERVAL = 1;
|
||||
private final static int OP_GET_CGM_COMMUNICATION_INTERVAL = 2;
|
||||
private final static int OP_CGM_COMMUNICATION_INTERVAL_RESPONSE = 3;
|
||||
private final static int OP_SET_GLUCOSE_CALIBRATION_VALUE = 4;
|
||||
private final static int OP_GET_GLUCOSE_CALIBRATION_VALUE = 5;
|
||||
private final static int OP_GLUCOSE_CALIBRATION_VALUE_RESPONSE = 6;
|
||||
private final static int OP_SET_PATIENT_HIGH_ALERT_LEVEL = 7;
|
||||
private final static int OP_GET_PATIENT_HIGH_ALERT_LEVEL = 8;
|
||||
private final static int OP_PATIENT_HIGH_ALERT_LEVEL_RESPONSE = 9;
|
||||
private final static int OP_SET_PATIENT_LOW_ALERT_LEVEL = 10;
|
||||
private final static int OP_GET_PATIENT_LOW_ALERT_LEVEL = 11;
|
||||
private final static int OP_PATIENT_LOW_ALERT_LEVEL_RESPONSE = 12;
|
||||
private final static int OP_SET_HYPO_ALERT_LEVEL = 13;
|
||||
private final static int OP_GET_HYPO_ALERT_LEVEL = 14;
|
||||
private final static int OP_HYPO_ALERT_LEVEL_RESPONSE = 15;
|
||||
private final static int OP_SET_HYPER_ALERT_LEVEL = 16;
|
||||
private final static int OP_GET_HYPER_ALERT_LEVEL = 17;
|
||||
private final static int OP_HYPER_ALERT_LEVEL_RESPONSE = 18;
|
||||
private final static int OP_SET_RATE_OF_DECREASE_ALERT_LEVEL = 19;
|
||||
private final static int OP_GET_RATE_OF_DECREASE_ALERT_LEVEL = 20;
|
||||
private final static int OP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE = 21;
|
||||
private final static int OP_SET_RATE_OF_INCREASE_ALERT_LEVEL = 22;
|
||||
private final static int OP_GET_RATE_OF_INCREASE_ALERT_LEVEL = 23;
|
||||
private final static int OP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE = 24;
|
||||
private final static int OP_RESET_DEVICE_SPECIFIC_ALERT = 25;
|
||||
private final static int OP_CODE_START_SESSION = 26;
|
||||
private final static int OP_CODE_STOP_SESSION = 27;
|
||||
private final static int OP_CODE_RESPONSE_CODE = 28;
|
||||
|
||||
// TODO this parser does not support E2E-CRC!
|
||||
|
||||
public static String parse(final BluetoothGattCharacteristic characteristic) {
|
||||
int offset = 0;
|
||||
final int opCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append(parseOpCode(opCode));
|
||||
switch (opCode) {
|
||||
case OP_SET_CGM_COMMUNICATION_INTERVAL:
|
||||
case OP_CGM_COMMUNICATION_INTERVAL_RESPONSE: {
|
||||
final int interval = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
builder.append(" to ").append(interval).append(" min");
|
||||
break;
|
||||
}
|
||||
case OP_SET_GLUCOSE_CALIBRATION_VALUE: {
|
||||
final float calConcentration = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 2;
|
||||
final int calTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
final int calTypeSampleLocation = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
final int calType = calTypeSampleLocation & 0x0F;
|
||||
final int calSampleLocation = (calTypeSampleLocation & 0xF0) >> 4;
|
||||
// final int calNextCalibrationTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
// offset += 2;
|
||||
// final int calCalibrationDataRecordNumber = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
// offset += 2;
|
||||
// final int calStatus = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
|
||||
builder.append(" to:\n");
|
||||
builder.append("Glucose Concentration of Calibration: ").append(calConcentration).append(" mg/dL\n");
|
||||
builder.append("Time: ").append(calTime).append(" min\n");
|
||||
builder.append("Type: ").append(parseType(calType)).append("\n");
|
||||
builder.append("Sample Location: ").append(parseSampleLocation(calSampleLocation)).append("\n");
|
||||
// builder.append("Next Calibration Time: ").append(parseNextCalibrationTime(calNextCalibrationTime)).append(" min\n"); // field ignored on Set
|
||||
// builder.append("Data Record Number: ").append(calCalibrationDataRecordNumber).append("\n"); // field ignored on Set
|
||||
// parseStatus(builder, calStatus); // field ignored on Set
|
||||
break;
|
||||
}
|
||||
case OP_GET_GLUCOSE_CALIBRATION_VALUE: {
|
||||
final int calibrationRecordNumber = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
builder.append(": ").append(parseRecordNumber(calibrationRecordNumber));
|
||||
break;
|
||||
}
|
||||
case OP_GLUCOSE_CALIBRATION_VALUE_RESPONSE: {
|
||||
final float calConcentration = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
offset += 2;
|
||||
final int calTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
final int calTypeSampleLocation = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
final int calType = calTypeSampleLocation & 0x0F;
|
||||
final int calSampleLocation = (calTypeSampleLocation & 0xF0) >> 4;
|
||||
final int calNextCalibrationTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
final int calCalibrationDataRecordNumber = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, offset);
|
||||
offset += 2;
|
||||
final int calStatus = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset);
|
||||
|
||||
builder.append(":\n");
|
||||
if (calCalibrationDataRecordNumber > 0) {
|
||||
builder.append("Glucose Concentration of Calibration: ").append(calConcentration).append(" mg/dL\n");
|
||||
builder.append("Time: ").append(calTime).append(" min\n");
|
||||
builder.append("Type: ").append(parseType(calType)).append("\n");
|
||||
builder.append("Sample Location: ").append(parseSampleLocation(calSampleLocation)).append("\n");
|
||||
builder.append("Next Calibration Time: ").append(parseNextCalibrationTime(calNextCalibrationTime)).append("\n");
|
||||
builder.append("Data Record Number: ").append(calCalibrationDataRecordNumber);
|
||||
parseStatus(builder, calStatus);
|
||||
} else {
|
||||
builder.append("No Calibration Data Stored");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_SET_PATIENT_HIGH_ALERT_LEVEL:
|
||||
case OP_SET_PATIENT_LOW_ALERT_LEVEL:
|
||||
case OP_SET_HYPO_ALERT_LEVEL:
|
||||
case OP_SET_HYPER_ALERT_LEVEL: {
|
||||
final float level = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
builder.append(" to: ").append(level).append(" mg/dL");
|
||||
break;
|
||||
}
|
||||
case OP_PATIENT_HIGH_ALERT_LEVEL_RESPONSE:
|
||||
case OP_PATIENT_LOW_ALERT_LEVEL_RESPONSE:
|
||||
case OP_HYPO_ALERT_LEVEL_RESPONSE:
|
||||
case OP_HYPER_ALERT_LEVEL_RESPONSE: {
|
||||
final float level = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
builder.append(": ").append(level).append(" mg/dL");
|
||||
break;
|
||||
}
|
||||
case OP_SET_RATE_OF_DECREASE_ALERT_LEVEL:
|
||||
case OP_SET_RATE_OF_INCREASE_ALERT_LEVEL: {
|
||||
final float level = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
builder.append(" to: ").append(level).append(" mg/dL/min");
|
||||
break;
|
||||
}
|
||||
case OP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE:
|
||||
case OP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE: {
|
||||
final float level = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT, offset);
|
||||
builder.append(": ").append(level).append(" mg/dL/min");
|
||||
break;
|
||||
}
|
||||
case OP_CODE_RESPONSE_CODE:
|
||||
final int requestOpCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
final int responseCode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset++);
|
||||
builder.append(" to ").append(parseOpCode(requestOpCode)).append(": ").append(parseResponseCode(responseCode));
|
||||
break;
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static String parseOpCode(final int code) {
|
||||
switch (code) {
|
||||
case OP_SET_CGM_COMMUNICATION_INTERVAL:
|
||||
return "Set CGM Communication Interval";
|
||||
case OP_GET_CGM_COMMUNICATION_INTERVAL:
|
||||
return "Get CGM Communication Interval";
|
||||
case OP_CGM_COMMUNICATION_INTERVAL_RESPONSE:
|
||||
return "CGM Communication Interval";
|
||||
case OP_SET_GLUCOSE_CALIBRATION_VALUE:
|
||||
return "Set CGM Calibration Value";
|
||||
case OP_GET_GLUCOSE_CALIBRATION_VALUE:
|
||||
return "Get CGM Calibration Value";
|
||||
case OP_GLUCOSE_CALIBRATION_VALUE_RESPONSE:
|
||||
return "CGM Calibration Value";
|
||||
case OP_SET_PATIENT_HIGH_ALERT_LEVEL:
|
||||
return "Set Patient High Alert Level";
|
||||
case OP_GET_PATIENT_HIGH_ALERT_LEVEL:
|
||||
return "Get Patient High Alert Level";
|
||||
case OP_PATIENT_HIGH_ALERT_LEVEL_RESPONSE:
|
||||
return "Patient High Alert Level";
|
||||
case OP_SET_PATIENT_LOW_ALERT_LEVEL:
|
||||
return "Set Patient Low Alert Level";
|
||||
case OP_GET_PATIENT_LOW_ALERT_LEVEL:
|
||||
return "Get Patient Low Alert Level";
|
||||
case OP_PATIENT_LOW_ALERT_LEVEL_RESPONSE:
|
||||
return "Patient Low Alert Level";
|
||||
case OP_SET_HYPO_ALERT_LEVEL:
|
||||
return "Set Hypo Alert Level";
|
||||
case OP_GET_HYPO_ALERT_LEVEL:
|
||||
return "Get Hypo Alert Level";
|
||||
case OP_HYPO_ALERT_LEVEL_RESPONSE:
|
||||
return "Hypo Alert Level";
|
||||
case OP_SET_HYPER_ALERT_LEVEL:
|
||||
return "Set Hyper Alert Level";
|
||||
case OP_GET_HYPER_ALERT_LEVEL:
|
||||
return "Get Hyper Alert Level";
|
||||
case OP_HYPER_ALERT_LEVEL_RESPONSE:
|
||||
return "Hyper Alert Level";
|
||||
case OP_SET_RATE_OF_DECREASE_ALERT_LEVEL:
|
||||
return "Set Rate of Decrease Alert Level";
|
||||
case OP_GET_RATE_OF_DECREASE_ALERT_LEVEL:
|
||||
return "Get Rate of Decrease Alert Level";
|
||||
case OP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE:
|
||||
return "Rate of Decrease Alert Level";
|
||||
case OP_SET_RATE_OF_INCREASE_ALERT_LEVEL:
|
||||
return "Set Rate of Increase Alert Level";
|
||||
case OP_GET_RATE_OF_INCREASE_ALERT_LEVEL:
|
||||
return "Get Rate of Increase Alert Level";
|
||||
case OP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE:
|
||||
return "Rate of Increase Alert Level";
|
||||
case OP_RESET_DEVICE_SPECIFIC_ALERT:
|
||||
return "Reset Device Specific Alert";
|
||||
case OP_CODE_START_SESSION:
|
||||
return "Start Session";
|
||||
case OP_CODE_STOP_SESSION:
|
||||
return "Stop Session";
|
||||
case OP_CODE_RESPONSE_CODE:
|
||||
return "Response";
|
||||
default:
|
||||
return "Reserved for future use (" + code + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseResponseCode(final int code) {
|
||||
switch (code) {
|
||||
case 1: return "Success";
|
||||
case 2: return "Op Code not supported";
|
||||
case 3: return "Invalid Operand";
|
||||
case 4: return "Procedure not completed";
|
||||
case 5: return "Parameter out of range";
|
||||
default:
|
||||
return "Reserved for future use (" + code + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseType(final int type) {
|
||||
switch (type) {
|
||||
case 1: return "Capillary Whole blood";
|
||||
case 2: return "Capillary Plasma";
|
||||
case 3: return "Capillary Whole blood";
|
||||
case 4: return "Venous Plasma";
|
||||
case 5: return "Arterial Whole blood";
|
||||
case 6: return "Arterial Plasma";
|
||||
case 7: return "Undetermined Whole blood";
|
||||
case 8: return "Undetermined Plasma";
|
||||
case 9: return "Interstitial Fluid (ISF)";
|
||||
case 10: return "Control Solution";
|
||||
default: return "Reserved for future use (" + type + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseSampleLocation(final int location) {
|
||||
switch (location) {
|
||||
case 1: return "Finger";
|
||||
case 2: return "Alternate Site Test (AST)";
|
||||
case 3: return "Earlobe";
|
||||
case 4: return "Control solution";
|
||||
case 5: return "Subcutaneous tissue";
|
||||
case 15: return "Sample Location value not available";
|
||||
default: return "Reserved for future use (" + location + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseNextCalibrationTime(final int time) {
|
||||
if (time == 0)
|
||||
return "Calibration Required Instantly";
|
||||
return time + " min";
|
||||
}
|
||||
|
||||
private static String parseRecordNumber(final int time) {
|
||||
if (time == 0xFFFF)
|
||||
return "Last Calibration Data";
|
||||
return String.valueOf(time);
|
||||
}
|
||||
|
||||
private static void parseStatus(final StringBuilder builder, final int status) {
|
||||
if (status == 0)
|
||||
return;
|
||||
builder.append("\nStatus:\n");
|
||||
if ((status & 1) > 0)
|
||||
builder.append("- Calibration Data rejected");
|
||||
if ((status & 2) > 0)
|
||||
builder.append("- Calibration Data out of range");
|
||||
if ((status & 4) > 0)
|
||||
builder.append("- Calibration Process pending");
|
||||
if ((status & 0xF8) > 0)
|
||||
builder.append("- Reserved for future use (").append(status).append(")");
|
||||
}
|
||||
}
|
||||
@@ -33,11 +33,13 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.log.ILogSession;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
import no.nordicsemi.android.log.Logger;
|
||||
import no.nordicsemi.android.nrftoolbox.error.GattError;
|
||||
import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
|
||||
@@ -53,8 +55,8 @@ import no.nordicsemi.android.nrftoolbox.utility.ParserUtils;
|
||||
* <li>The manager tries to read the Battery Level characteristic. No matter the result of this operation (for example the Battery Level characteristic may not have the READ property)
|
||||
* it tries to enable Battery Level notifications, to get battery updates from the device.</li>
|
||||
* <li>Afterwards, the manager initializes the device using given queue of commands. See {@link BleManagerGattCallback#initGatt(BluetoothGatt)} method for more details.</li>
|
||||
* <li>When initialization complete, the {@link BleManagerCallbacks#onDeviceReady()} callback is called.</li>
|
||||
* </ol>The manager also is responsible for parsing the Battery Level values and calling {@link BleManagerCallbacks#onBatteryValueReceived(int)} method.</p>
|
||||
* <li>When initialization complete, the {@link BleManagerCallbacks#onDeviceReady(BluetoothDevice)} callback is called.</li>
|
||||
* </ol>The manager also is responsible for parsing the Battery Level values and calling {@link BleManagerCallbacks#onBatteryValueReceived(BluetoothDevice, int)} method.</p>
|
||||
* <p>Events from all profiles are being logged into the nRF Logger application,
|
||||
* which may be downloaded from Google Play: <a href="https://play.google.com/store/apps/details?id=no.nordicsemi.android.log">https://play.google.com/store/apps/details?id=no.nordicsemi.android.log</a></p>
|
||||
* <p>The nRF Logger application allows you to see application logs without need to connect it to the computer.</p>
|
||||
@@ -82,11 +84,17 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
* The log session or null if nRF Logger is not installed.
|
||||
*/
|
||||
protected ILogSession mLogSession;
|
||||
protected BluetoothDevice mBluetoothDevice;
|
||||
protected E mCallbacks;
|
||||
private Handler mHandler;
|
||||
private BluetoothGatt mBluetoothGatt;
|
||||
private Context mContext;
|
||||
/**
|
||||
* This flag is set to false only when the {@link #shouldAutoConnect()} method returns true and the device got disconnected without calling {@link #disconnect()} method.
|
||||
* If {@link #shouldAutoConnect()} returns false (dafault) this is always set to true.
|
||||
*/
|
||||
private boolean mUserDisconnected;
|
||||
/** Flag set to true when the device is connected. */
|
||||
private boolean mConnected;
|
||||
|
||||
private BroadcastReceiver mBondingBroadcastReceiver = new BroadcastReceiver() {
|
||||
@@ -105,11 +113,11 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
|
||||
switch (bondState) {
|
||||
case BluetoothDevice.BOND_BONDING:
|
||||
mCallbacks.onBondingRequired();
|
||||
mCallbacks.onBondingRequired(device);
|
||||
break;
|
||||
case BluetoothDevice.BOND_BONDED:
|
||||
Logger.i(mLogSession, "Device bonded");
|
||||
mCallbacks.onBonded();
|
||||
mCallbacks.onBonded(device);
|
||||
|
||||
// Start initializing again.
|
||||
// In fact, bonding forces additional, internal service discovery (at least on Nexus devices), so this method may safely be used to start this process again.
|
||||
@@ -199,6 +207,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
mUserDisconnected = !autoConnect; // We will receive Linkloss events only when the device is connected with autoConnect=true
|
||||
Logger.v(mLogSession, "Connecting...");
|
||||
Logger.d(mLogSession, "gatt = device.connectGatt(autoConnect = " + autoConnect + ")");
|
||||
mBluetoothDevice = device;
|
||||
mBluetoothGatt = device.connectGatt(mContext, autoConnect, getGattCallback());
|
||||
}
|
||||
|
||||
@@ -211,7 +220,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
|
||||
if (mConnected && mBluetoothGatt != null) {
|
||||
Logger.v(mLogSession, "Disconnecting...");
|
||||
mCallbacks.onDeviceDisconnecting();
|
||||
mCallbacks.onDeviceDisconnecting(mBluetoothGatt.getDevice());
|
||||
Logger.d(mLogSession, "gatt.disconnect()");
|
||||
mBluetoothGatt.disconnect();
|
||||
return true;
|
||||
@@ -219,6 +228,13 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns true if the device is connected. Services could have not been discovered yet.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes and releases resources. May be also used to unregister broadcast listeners.
|
||||
*/
|
||||
@@ -230,9 +246,11 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
// the receiver must have been not registered or unregistered before
|
||||
}
|
||||
if (mBluetoothGatt != null) {
|
||||
Logger.d(mLogSession, "gatt.close()");
|
||||
mBluetoothGatt.close();
|
||||
mBluetoothGatt = null;
|
||||
}
|
||||
mBluetoothDevice = null;
|
||||
mUserDisconnected = false;
|
||||
}
|
||||
|
||||
@@ -248,6 +266,30 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
mLogSession = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message on the manager's log session. Does nothing when log session has not been set by {@link #setLogger(ILogSession)}.
|
||||
* @param level
|
||||
* the log level, one of {@link LogContract.Log.Level#DEBUG}, {@link LogContract.Log.Level#VERBOSE}, {@link LogContract.Log.Level#INFO}, {@link LogContract.Log.Level#WARNING},
|
||||
* {@link LogContract.Log.Level#ERROR}
|
||||
* @param message
|
||||
* the message to be logged
|
||||
*/
|
||||
public void log(final int level, final String message) {
|
||||
Logger.log(mLogSession, level, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message on the manager's log session. Does nothing when log session has not been set by {@link #setLogger(ILogSession)}.
|
||||
* @param level
|
||||
* the log level, one of {@link LogContract.Log.Level#DEBUG}, {@link LogContract.Log.Level#VERBOSE}, {@link LogContract.Log.Level#INFO}, {@link LogContract.Log.Level#WARNING},
|
||||
* {@link LogContract.Log.Level#ERROR}
|
||||
* @param messageRes
|
||||
* the message string resource to be logged
|
||||
*/
|
||||
public void log(final int level, @StringRes final int messageRes) {
|
||||
Logger.log(mLogSession, level, messageRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the manager callback listener
|
||||
*
|
||||
@@ -573,7 +615,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
* Called then the initialization queue is complete.
|
||||
*/
|
||||
protected void onDeviceReady() {
|
||||
mCallbacks.onDeviceReady();
|
||||
mCallbacks.onDeviceReady(mBluetoothGatt.getDevice());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -617,9 +659,9 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private void onError(final String message, final int errorCode) {
|
||||
private void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
Logger.e(mLogSession, "Error (0x" + Integer.toHexString(errorCode) + "): " + GattError.parse(errorCode));
|
||||
mCallbacks.onError(message, errorCode);
|
||||
mCallbacks.onError(device, message, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -630,7 +672,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
// Notify the parent activity/service
|
||||
Logger.i(mLogSession, "Connected to " + gatt.getDevice().getAddress());
|
||||
mConnected = true;
|
||||
mCallbacks.onDeviceConnected();
|
||||
mCallbacks.onDeviceConnected(gatt.getDevice());
|
||||
|
||||
/*
|
||||
* The onConnectionStateChange event is triggered just after the Android connects to a device.
|
||||
@@ -668,11 +710,11 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
mConnected = false;
|
||||
if (mUserDisconnected) {
|
||||
Logger.i(mLogSession, "Disconnected");
|
||||
mCallbacks.onDeviceDisconnected();
|
||||
mCallbacks.onDeviceDisconnected(gatt.getDevice());
|
||||
close();
|
||||
} else {
|
||||
Logger.w(mLogSession, "Connection lost");
|
||||
mCallbacks.onLinklossOccur();
|
||||
mCallbacks.onLinklossOccur(gatt.getDevice());
|
||||
// We are not closing the connection here as the device should try to reconnect automatically.
|
||||
// This may be only called when the shouldAutoConnect() method returned true.
|
||||
}
|
||||
@@ -681,7 +723,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
|
||||
// TODO Should the disconnect method be called or the connection is still valid? Does this ever happen?
|
||||
Logger.e(mLogSession, "Error (0x" + Integer.toHexString(status) + "): " + GattError.parseConnectionError(status));
|
||||
mCallbacks.onError(ERROR_CONNECTION_STATE_CHANGE, status);
|
||||
mCallbacks.onError(gatt.getDevice(), ERROR_CONNECTION_STATE_CHANGE, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,7 +738,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
Logger.v(mLogSession, "Secondary service found");
|
||||
|
||||
// Notify the parent activity
|
||||
mCallbacks.onServicesDiscovered(optionalServicesFound);
|
||||
mCallbacks.onServicesDiscovered(gatt.getDevice(), optionalServicesFound);
|
||||
|
||||
// Obtain the queue of initialization requests
|
||||
mInitInProgress = true;
|
||||
@@ -713,12 +755,12 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
nextRequest();
|
||||
} else {
|
||||
Logger.w(mLogSession, "Device is not supported");
|
||||
mCallbacks.onDeviceNotSupported();
|
||||
mCallbacks.onDeviceNotSupported(gatt.getDevice());
|
||||
disconnect();
|
||||
}
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onServicesDiscovered error " + status);
|
||||
onError(ERROR_DISCOVERY_SERVICE, status);
|
||||
onError(gatt.getDevice(), ERROR_DISCOVERY_SERVICE, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,7 +772,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
if (isBatteryLevelCharacteristic(characteristic)) {
|
||||
final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
Logger.a(mLogSession, "Battery level received: " + batteryValue + "%");
|
||||
mCallbacks.onBatteryValueReceived(batteryValue);
|
||||
mCallbacks.onBatteryValueReceived(gatt.getDevice(), batteryValue);
|
||||
|
||||
// The Battery Level value has been read. Let's try to enable Battery Level notifications.
|
||||
// If the Battery Level characteristic does not have the NOTIFY property, proceed with the initialization queue.
|
||||
@@ -744,16 +786,16 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
|
||||
mCallbacks.onError(ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
}
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onCharacteristicRead error " + status);
|
||||
onError(ERROR_READ_CHARACTERISTIC, status);
|
||||
onError(gatt.getDevice(), ERROR_READ_CHARACTERISTIC, status);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
|
||||
public final void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
Logger.i(mLogSession, "Data written to " + characteristic.getUuid() + ", value: " + ParserUtils.parse(characteristic.getValue()));
|
||||
// The value has been written. Notify the manager and proceed with the initialization queue.
|
||||
@@ -762,11 +804,11 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
|
||||
mCallbacks.onError(ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
}
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onCharacteristicRead error " + status);
|
||||
onError(ERROR_READ_CHARACTERISTIC, status);
|
||||
onError(gatt.getDevice(), ERROR_READ_CHARACTERISTIC, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,11 +834,11 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED);
|
||||
mCallbacks.onError(ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status);
|
||||
}
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onDescriptorWrite error " + status);
|
||||
onError(ERROR_WRITE_DESCRIPTOR, status);
|
||||
onError(gatt.getDevice(), ERROR_WRITE_DESCRIPTOR, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +850,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
|
||||
Logger.i(mLogSession, "Notification received from " + characteristic.getUuid() + ", value: " + data);
|
||||
final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
Logger.a(mLogSession, "Battery level received: " + batteryValue + "%");
|
||||
mCallbacks.onBatteryValueReceived(batteryValue);
|
||||
mCallbacks.onBatteryValueReceived(gatt.getDevice(), batteryValue);
|
||||
} else {
|
||||
final BluetoothGattDescriptor cccd = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
|
||||
final boolean notifications = cccd == null || cccd.getValue() == null || cccd.getValue().length != 2 || cccd.getValue()[0] == 0x01;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.profile;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCallback;
|
||||
|
||||
@@ -28,71 +29,82 @@ public interface BleManagerCallbacks {
|
||||
|
||||
/**
|
||||
* Called when the device has been connected. This does not mean that the application may start communication. A service discovery will be handled automatically after this call. Service discovery
|
||||
* may ends up with calling {@link #onServicesDiscovered(boolean)} or {@link #onDeviceNotSupported()} if required services have not been found.
|
||||
* may ends up with calling {@link #onServicesDiscovered(BluetoothDevice, boolean)} or {@link #onDeviceNotSupported(BluetoothDevice)} if required services have not been found.
|
||||
* @param device the device that got connected
|
||||
*/
|
||||
public void onDeviceConnected();
|
||||
void onDeviceConnected(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when user initialized disconnection.
|
||||
* @param device the device that gets disconnecting
|
||||
*/
|
||||
public void onDeviceDisconnecting();
|
||||
void onDeviceDisconnecting(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when the device has disconnected (when the callback returned {@link BluetoothGattCallback#onConnectionStateChange(BluetoothGatt, int, int)} with state DISCONNECTED.
|
||||
* @param device the device that got disconnected
|
||||
*/
|
||||
public void onDeviceDisconnected();
|
||||
void onDeviceDisconnected(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* This callback is invoked when the Ble Manager lost connection to a device that has been connected with autoConnect option. Otherwise a {@link #onDeviceDisconnected()}
|
||||
* This callback is invoked when the Ble Manager lost connection to a device that has been connected with autoConnect option. Otherwise a {@link #onDeviceDisconnected(BluetoothDevice)}
|
||||
* method will be called on such event.
|
||||
* @param device the device that got disconnected due to a link loss
|
||||
*/
|
||||
public void onLinklossOccur();
|
||||
void onLinklossOccur(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when service discovery has finished and primary services has been found. The device is ready to operate. This method is not called if the primary, mandatory services were not found
|
||||
* during service discovery. For example in the Blood Pressure Monitor, a Blood Pressure service is a primary service and Intermediate Cuff Pressure service is a optional secondary service.
|
||||
* Existence of battery service is not notified by this call.
|
||||
*
|
||||
*
|
||||
* @param optionalServicesFound
|
||||
* if <code>true</code> the secondary services were also found on the device.
|
||||
* @param device the device which services got disconnected
|
||||
*/
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound);
|
||||
void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound);
|
||||
|
||||
/**
|
||||
* Method called when all initialization requests has been completed.
|
||||
* @param device the device that get ready
|
||||
*/
|
||||
public void onDeviceReady();
|
||||
void onDeviceReady(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when battery value has been received from the device.
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
* the battery value in percent
|
||||
* @param device the device frm which the battery value has changed
|
||||
*/
|
||||
public void onBatteryValueReceived(final int value);
|
||||
void onBatteryValueReceived(final BluetoothDevice device, final int value);
|
||||
|
||||
/**
|
||||
* Called when an {@link BluetoothGatt#GATT_INSUFFICIENT_AUTHENTICATION} error occurred and the device bond state is NOT_BONDED
|
||||
* @param device the device that requires bonding
|
||||
*/
|
||||
public void onBondingRequired();
|
||||
void onBondingRequired(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when the device has been successfully bonded.
|
||||
* @param device the device that got bonded
|
||||
*/
|
||||
public void onBonded();
|
||||
void onBonded(final BluetoothDevice device);
|
||||
|
||||
/**
|
||||
* Called when a BLE error has occurred
|
||||
*
|
||||
*
|
||||
* @param message
|
||||
* the error message
|
||||
* @param errorCode
|
||||
* the error code
|
||||
* @param device the device that caused an error
|
||||
*/
|
||||
public void onError(final String message, final int errorCode);
|
||||
void onError(final BluetoothDevice device, final String message, final int errorCode);
|
||||
|
||||
/**
|
||||
* Called when service discovery has finished but the main services were not found on the device.
|
||||
* @param device the device that failed to connect due to lack of required services
|
||||
*/
|
||||
public void onDeviceNotSupported();
|
||||
void onDeviceNotSupported(final BluetoothDevice device);
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected() {
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mDeviceConnected = true;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -251,12 +251,12 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting() {
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
mBleManager.close();
|
||||
runOnUiThread(new Runnable() {
|
||||
@@ -271,7 +271,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -284,7 +284,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryValueReceived(final int value) {
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -294,23 +294,23 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired() {
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
showToast(R.string.bonding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded() {
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
showToast(R.string.bonded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String message, final int errorCode) {
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
|
||||
showToast(message + " (" + errorCode + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported() {
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
showToast(R.string.not_supported);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
|
||||
public abstract class BleProfileExpandableListActivity extends ExpandableListActivity implements BleManagerCallbacks, ScannerFragment.OnDeviceSelectedListener {
|
||||
private static final String TAG = "BaseProfileActivity";
|
||||
|
||||
private static final String CONNECTION_STATUS = "connection_status";
|
||||
private static final String DEVICE_NAME = "device_name";
|
||||
private static final String SIS_CONNECTION_STATUS = "connection_status";
|
||||
private static final String SIS_DEVICE_NAME = "device_name";
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
private BleManager<? extends BleManagerCallbacks> mBleManager;
|
||||
@@ -127,15 +127,15 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(CONNECTION_STATUS, mDeviceConnected);
|
||||
outState.putString(DEVICE_NAME, mDeviceName);
|
||||
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
|
||||
outState.putString(SIS_DEVICE_NAME, mDeviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mDeviceConnected = savedInstanceState.getBoolean(CONNECTION_STATUS);
|
||||
mDeviceName = savedInstanceState.getString(DEVICE_NAME);
|
||||
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
|
||||
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
|
||||
if (mDeviceConnected) {
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
@@ -236,7 +236,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected() {
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mDeviceConnected = true;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -248,12 +248,12 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting() {
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
mBleManager.close();
|
||||
runOnUiThread(new Runnable() {
|
||||
@@ -267,7 +267,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -280,19 +280,19 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the initialization process in completed.
|
||||
*/
|
||||
public void onDeviceReady() {
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryValueReceived(final int value) {
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -302,23 +302,23 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired() {
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
showToast(R.string.bonding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded() {
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
showToast(R.string.bonded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String message, final int errorCode) {
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
|
||||
showToast(message + " (" + errorCode + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported() {
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
showToast(R.string.not_supported);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public static final String EXTRA_DEVICE_ADDRESS = "no.nordicsemi.android.nrftoolbox.EXTRA_DEVICE_ADDRESS";
|
||||
/** The key for the device name that is returned in {@link #BROADCAST_CONNECTION_STATE} with state {@link #STATE_CONNECTED}. */
|
||||
public static final String EXTRA_DEVICE_NAME = "no.nordicsemi.android.nrftoolbox.EXTRA_DEVICE_NAME";
|
||||
public static final String EXTRA_DEVICE = "no.nordicsemi.android.nrftoolbox.EXTRA_DEVICE";
|
||||
public static final String EXTRA_LOG_URI = "no.nordicsemi.android.nrftoolbox.EXTRA_LOG_URI";
|
||||
public static final String EXTRA_CONNECTION_STATE = "no.nordicsemi.android.nrftoolbox.EXTRA_CONNECTION_STATE";
|
||||
public static final String EXTRA_BOND_STATE = "no.nordicsemi.android.nrftoolbox.EXTRA_BOND_STATE";
|
||||
@@ -72,7 +73,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
protected boolean mBinded;
|
||||
private boolean mActivityFinished;
|
||||
private boolean mConnected;
|
||||
private String mDeviceAddress;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private String mDeviceName;
|
||||
private ILogSession mLogSession;
|
||||
|
||||
@@ -83,7 +84,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public final void disconnect() {
|
||||
if (!mConnected) {
|
||||
mBleManager.close();
|
||||
onDeviceDisconnected();
|
||||
onDeviceDisconnected(mBluetoothDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return device address
|
||||
*/
|
||||
public String getDeviceAddress() {
|
||||
return mDeviceAddress;
|
||||
return mBluetoothDevice.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +117,15 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
return mDeviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Bluetooth device
|
||||
*
|
||||
* @return the Bluetooth device
|
||||
*/
|
||||
public BluetoothDevice getBluetoothDevice() {
|
||||
return mBluetoothDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the device is connected to the sensor.
|
||||
*
|
||||
@@ -218,7 +228,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
|
||||
final Uri logUri = intent.getParcelableExtra(EXTRA_LOG_URI);
|
||||
mLogSession = Logger.openSession(getApplicationContext(), logUri);
|
||||
mDeviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
|
||||
mDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
|
||||
Logger.i(mLogSession, "Service started");
|
||||
|
||||
@@ -229,11 +239,11 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
|
||||
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
|
||||
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
|
||||
final BluetoothDevice device = adapter.getRemoteDevice(mDeviceAddress);
|
||||
mDeviceName = device.getName();
|
||||
final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
|
||||
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
|
||||
onServiceStarted();
|
||||
|
||||
mBleManager.connect(device);
|
||||
mBleManager.connect(mBluetoothDevice);
|
||||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@@ -252,27 +262,28 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
mBleManager.close();
|
||||
Logger.i(mLogSession, "Service destroyed");
|
||||
mBleManager = null;
|
||||
mDeviceAddress = null;
|
||||
mBluetoothDevice = null;
|
||||
mDeviceName = null;
|
||||
mConnected = false;
|
||||
mLogSession = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected() {
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mConnected = true;
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE_ADDRESS, mDeviceAddress);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE_NAME, mDeviceName);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting() {
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
// Notify user about changing the state to DISCONNECTING
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -287,12 +298,12 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mConnected = false;
|
||||
mDeviceAddress = null;
|
||||
mDeviceName = null;
|
||||
|
||||
// Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
@@ -307,31 +318,35 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
mConnected = false;
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true);
|
||||
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, optionalServicesFound);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady() {
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported() {
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, false);
|
||||
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, false);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
@@ -340,33 +355,37 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryValueReceived(final int value) {
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired() {
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded() {
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonded);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String message, final int errorCode) {
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
final Intent broadcast = new Intent(BROADCAST_ERROR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
|
||||
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
@@ -421,7 +440,16 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return device address
|
||||
*/
|
||||
protected String getDeviceAddress() {
|
||||
return mDeviceAddress;
|
||||
return mBluetoothDevice.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Bluetooth device object
|
||||
*
|
||||
* @return bluetooth device
|
||||
*/
|
||||
protected BluetoothDevice getBluetoothDevice() {
|
||||
return mBluetoothDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,6 @@ package no.nordicsemi.android.nrftoolbox.profile;
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGattCallback;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@@ -73,7 +72,8 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
ScannerFragment.OnDeviceSelectedListener, BleManagerCallbacks {
|
||||
private static final String TAG = "BleProfileServiceReadyActivity";
|
||||
|
||||
private static final String DEVICE_NAME = "device_name";
|
||||
private static final String SIS_DEVICE_NAME = "device_name";
|
||||
private static final String SIS_DEVICE = "device";
|
||||
private static final String LOG_URI = "log_uri";
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
@@ -84,13 +84,18 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
private Button mConnectButton;
|
||||
|
||||
private ILogSession mLogSession;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private String mDeviceName;
|
||||
|
||||
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
// Check if the broadcast applies the connected device
|
||||
if (!isBroadcastForThisDevice(intent))
|
||||
return;
|
||||
|
||||
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
|
||||
final String action = intent.getAction();
|
||||
switch (action) {
|
||||
case BleProfileService.BROADCAST_CONNECTION_STATE: {
|
||||
final int state = intent.getIntExtra(BleProfileService.EXTRA_CONNECTION_STATE, BleProfileService.STATE_DISCONNECTED);
|
||||
@@ -98,16 +103,16 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
switch (state) {
|
||||
case BleProfileService.STATE_CONNECTED: {
|
||||
mDeviceName = intent.getStringExtra(BleProfileService.EXTRA_DEVICE_NAME);
|
||||
onDeviceConnected();
|
||||
onDeviceConnected(bluetoothDevice);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.STATE_DISCONNECTED: {
|
||||
onDeviceDisconnected();
|
||||
onDeviceDisconnected(bluetoothDevice);
|
||||
mDeviceName = null;
|
||||
break;
|
||||
}
|
||||
case BleProfileService.STATE_LINK_LOSS: {
|
||||
onLinklossOccur();
|
||||
onLinklossOccur(bluetoothDevice);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.STATE_CONNECTING:
|
||||
@@ -124,24 +129,24 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
final boolean secondaryService = intent.getBooleanExtra(BleProfileService.EXTRA_SERVICE_SECONDARY, false);
|
||||
|
||||
if (primaryService) {
|
||||
onServicesDiscovered(secondaryService);
|
||||
onServicesDiscovered(bluetoothDevice, secondaryService);
|
||||
} else {
|
||||
onDeviceNotSupported();
|
||||
onDeviceNotSupported(bluetoothDevice);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_DEVICE_READY: {
|
||||
onDeviceReady();
|
||||
onDeviceReady(bluetoothDevice);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_BOND_STATE: {
|
||||
final int state = intent.getIntExtra(BleProfileService.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
|
||||
switch (state) {
|
||||
case BluetoothDevice.BOND_BONDING:
|
||||
onBondingRequired();
|
||||
onBondingRequired(bluetoothDevice);
|
||||
break;
|
||||
case BluetoothDevice.BOND_BONDED:
|
||||
onBonded();
|
||||
onBonded(bluetoothDevice);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -149,13 +154,13 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
case BleProfileService.BROADCAST_BATTERY_LEVEL: {
|
||||
final int value = intent.getIntExtra(BleProfileService.EXTRA_BATTERY_LEVEL, -1);
|
||||
if (value > 0)
|
||||
onBatteryValueReceived(value);
|
||||
onBatteryValueReceived(bluetoothDevice, value);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_ERROR: {
|
||||
final String message = intent.getStringExtra(BleProfileService.EXTRA_ERROR_MESSAGE);
|
||||
final int errorCode = intent.getIntExtra(BleProfileService.EXTRA_ERROR_CODE, 0);
|
||||
onError(message, errorCode);
|
||||
onError(bluetoothDevice, message, errorCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -167,6 +172,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
final E bleService = mService = (E) service;
|
||||
mBluetoothDevice = bleService.getBluetoothDevice();
|
||||
mLogSession = mService.getLogSession();
|
||||
Logger.d(mLogSession, "Activity binded to the service");
|
||||
onServiceBinded(bleService);
|
||||
@@ -178,7 +184,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
|
||||
// and notify user if device is connected
|
||||
if (bleService.isConnected())
|
||||
onDeviceConnected();
|
||||
onDeviceConnected(mBluetoothDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -189,6 +195,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
|
||||
mService = null;
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
onServiceUnbinded();
|
||||
}
|
||||
@@ -260,6 +267,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
Logger.d(mLogSession, "Activity unbinded from the service");
|
||||
onServiceUnbinded();
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// do nothing, we were not connected to the sensor
|
||||
@@ -351,7 +359,8 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(DEVICE_NAME, mDeviceName);
|
||||
outState.putString(SIS_DEVICE_NAME, mDeviceName);
|
||||
outState.putParcelable(SIS_DEVICE, mBluetoothDevice);
|
||||
if (mLogSession != null)
|
||||
outState.putParcelable(LOG_URI, mLogSession.getSessionUri());
|
||||
}
|
||||
@@ -359,7 +368,8 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
@Override
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mDeviceName = savedInstanceState.getString(DEVICE_NAME);
|
||||
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
mBluetoothDevice = savedInstanceState.getParcelable(SIS_DEVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -441,6 +451,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
}
|
||||
}
|
||||
mBluetoothDevice = device;
|
||||
mDeviceName = name;
|
||||
mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
|
||||
mConnectButton.setText(R.string.action_connecting);
|
||||
@@ -450,6 +461,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
Logger.d(mLogSession, "Creating service...");
|
||||
final Intent service = new Intent(this, getServiceClass());
|
||||
service.putExtra(BleProfileService.EXTRA_DEVICE_ADDRESS, device.getAddress());
|
||||
service.putExtra(BleProfileService.EXTRA_DEVICE_NAME, name);
|
||||
if (mLogSession != null)
|
||||
service.putExtra(BleProfileService.EXTRA_LOG_URI, mLogSession.getSessionUri());
|
||||
startService(service);
|
||||
@@ -462,27 +474,20 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the device has been connected. This does not mean that the application may start communication. A service discovery will be handled
|
||||
* automatically after this call. Service discovery may ends up with calling {@link #onServicesDiscovered(boolean)} or {@link #onDeviceNotSupported()} if required
|
||||
* services have not been found.
|
||||
*/
|
||||
public void onDeviceConnected() {
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mDeviceNameView.setText(mDeviceName);
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
mConnectButton.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting() {
|
||||
// do nothing
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the device has disconnected (when the callback returned
|
||||
* {@link BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} with state DISCONNECTED.
|
||||
*/
|
||||
public void onDeviceDisconnected() {
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
mDeviceNameView.setText(getDefaultDeviceName());
|
||||
if (mBatteryLevelView != null)
|
||||
@@ -493,79 +498,53 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
unbindService(mServiceConnection);
|
||||
mService = null;
|
||||
|
||||
Logger.d(mLogSession, "Activity unbinded from the service");
|
||||
Logger.d(mLogSession, "Activity unbound from the service");
|
||||
onServiceUnbinded();
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// do nothing. This should never happen but does...
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some profiles may use this method to notify user that the link was lost. You must call this method in your Ble Manager instead of
|
||||
* {@link #onDeviceDisconnected()} while you discover disconnection not initiated by the user.
|
||||
*/
|
||||
public void onLinklossOccur() {
|
||||
@Override
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
if (mBatteryLevelView != null)
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when service discovery has finished and primary services has been found. The device is ready to operate. This method is not called if the primary,
|
||||
* mandatory services were not found during service discovery. For example in the Blood Pressure Monitor, a Blood Pressure service is a primary service and
|
||||
* Intermediate Cuff Pressure service is a optional secondary service. Existence of battery service is not notified by this call.
|
||||
*
|
||||
* @param optionalServicesFound if <code>true</code> the secondary services were also found on the device.
|
||||
*/
|
||||
public abstract void onServicesDiscovered(final boolean optionalServicesFound);
|
||||
@Override
|
||||
public abstract void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound);
|
||||
|
||||
/**
|
||||
* Called when the initialization process in completed.
|
||||
*/
|
||||
public void onDeviceReady() {
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the device has started bonding process
|
||||
*/
|
||||
public void onBondingRequired() {
|
||||
@Override
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the device has finished bonding process successfully
|
||||
*/
|
||||
public void onBonded() {
|
||||
@Override
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when service discovery has finished but the main services were not found on the device. This may occur when connecting to bonded device that does
|
||||
* not support required services.
|
||||
*/
|
||||
public void onDeviceNotSupported() {
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
showToast(R.string.not_supported);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when battery value has been received from the device
|
||||
*
|
||||
* @param value the battery value in percent
|
||||
*/
|
||||
public void onBatteryValueReceived(final int value) {
|
||||
@Override
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
if (mBatteryLevelView != null)
|
||||
mBatteryLevelView.setText(getString(R.string.battery, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a BLE error has occurred
|
||||
*
|
||||
* @param message the error message
|
||||
* @param errorCode the error code
|
||||
*/
|
||||
public void onError(final String message, final int errorCode) {
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
|
||||
showToast(message + " (" + errorCode + ")");
|
||||
}
|
||||
@@ -640,6 +619,16 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
*/
|
||||
protected abstract UUID getFilterUUID();
|
||||
|
||||
/**
|
||||
* Checks the {@link BleProfileService#EXTRA_DEVICE} in the given intent and compares it with the connected BluetoothDevice object.
|
||||
* @param intent intent received via a broadcast from the service
|
||||
* @return true if the data in the intent apply to the connected device, false otherwise
|
||||
*/
|
||||
protected boolean isBroadcastForThisDevice(final Intent intent) {
|
||||
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
|
||||
return mBluetoothDevice != null && mBluetoothDevice.equals(bluetoothDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the scanner fragment.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
@@ -134,35 +135,35 @@ public class ProximityActivity extends BleProfileServiceReadyActivity<ProximityS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, boolean optionalServicesFound) {
|
||||
// this may notify user or update views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady() {
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
showOpenLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
showClosedLock();
|
||||
mGattServerSwitch.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired() {
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
showClosedLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded() {
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
showOpenLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
super.onLinklossOccur();
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
super.onLinklossOccur(device);
|
||||
showClosedLock();
|
||||
resetForLinkloss();
|
||||
|
||||
|
||||
@@ -185,10 +185,10 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
|
||||
if (!preparedWrite && value != null && value.length == 1) { // small validation
|
||||
if (value[0] != NO_ALERT[0]) {
|
||||
Logger.a(mLogSession, "[Server] Immediate alarm request received: " + AlertLevelParser.parse(characteristic));
|
||||
mCallbacks.onAlarmTriggered();
|
||||
mCallbacks.onAlarmTriggered(device);
|
||||
} else {
|
||||
Logger.a(mLogSession, "[Server] Immediate alarm request received: OFF");
|
||||
mCallbacks.onAlarmStopped();
|
||||
mCallbacks.onAlarmStopped(device);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newWriteRequest(mLinklossCharacteristic, HIGH_ALERT));
|
||||
requests.add(Request.newWriteRequest(mLinklossCharacteristic, HIGH_ALERT));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -306,10 +306,14 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
|
||||
mAlertLevelCharacteristic = null;
|
||||
mLinklossCharacteristic = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
Logger.a(mLogSession, "\"" + AlertLevelParser.parse(characteristic) + "\" sent");
|
||||
}
|
||||
};
|
||||
|
||||
public void writeImmediateAlertOn() {
|
||||
Logger.a(mLogSession, "Immediate alarm request: ON");
|
||||
if (mAlertLevelCharacteristic != null) {
|
||||
mAlertLevelCharacteristic.setValue(HIGH_ALERT);
|
||||
writeCharacteristic(mAlertLevelCharacteristic);
|
||||
@@ -319,7 +323,6 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
|
||||
}
|
||||
|
||||
public void writeImmediateAlertOff() {
|
||||
Logger.a(mLogSession, "Immediate alarm request: OFF");
|
||||
if (mAlertLevelCharacteristic != null) {
|
||||
mAlertLevelCharacteristic.setValue(NO_ALERT);
|
||||
writeCharacteristic(mAlertLevelCharacteristic);
|
||||
|
||||
@@ -21,10 +21,12 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface ProximityManagerCallbacks extends BleManagerCallbacks {
|
||||
public void onAlarmTriggered();
|
||||
void onAlarmTriggered(final BluetoothDevice device);
|
||||
|
||||
public void onAlarmStopped();
|
||||
void onAlarmStopped(final BluetoothDevice device);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -169,19 +170,19 @@ public class ProximityService extends BleProfileService implements ProximityMana
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting() {
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
stopAlarm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
isImmediateAlertOn = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
super.onLinklossOccur();
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
super.onLinklossOccur(device);
|
||||
isImmediateAlertOn = false;
|
||||
|
||||
if (!mBinded) {
|
||||
@@ -192,12 +193,12 @@ public class ProximityService extends BleProfileService implements ProximityMana
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarmTriggered() {
|
||||
public void onAlarmTriggered(final BluetoothDevice device) {
|
||||
playAlarm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarmStopped() {
|
||||
public void onAlarmStopped(final BluetoothDevice device) {
|
||||
stopAlarm();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.rsc;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -33,6 +34,7 @@ import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.view.Menu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
@@ -175,7 +177,7 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// not used
|
||||
}
|
||||
|
||||
@@ -192,7 +194,7 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
mTotalDistanceView.setText(R.string.not_available);
|
||||
mTotalDistanceUnitView.setText(null);
|
||||
} else {
|
||||
mTotalDistanceView.setText(String.format("%.2f", totalDistance / 1000.0f)); // 1 km in m
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f)); // 1 km in m
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
}
|
||||
break;
|
||||
@@ -202,14 +204,14 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
mTotalDistanceView.setText(R.string.not_available);
|
||||
mTotalDistanceUnitView.setText(null);
|
||||
} else {
|
||||
mTotalDistanceView.setText(String.format("%.2f", totalDistance / 1609.31f)); // 1 mile in m
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f)); // 1 mile in m
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_mile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mSpeedView.setText(String.format("%.1f", speed));
|
||||
mCadenceView.setText(String.format("%d", cadence));
|
||||
mSpeedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
mCadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
mActivityView.setText(activity == RSCManagerCallbacks.ACTIVITY_RUNNING ? R.string.rsc_running : R.string.rsc_walking);
|
||||
}
|
||||
|
||||
@@ -225,19 +227,19 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
case SettingsFragment.SETTINGS_UNIT_KM_H:
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S:
|
||||
if (distance < 100000) { // 1 km in cm
|
||||
mDistanceView.setText(String.format("%.0f", distance / 100.0f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance / 100.0f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
} else {
|
||||
mDistanceView.setText(String.format("%.2f", distance / 100000.0f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 100000.0f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_km);
|
||||
}
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH:
|
||||
if (distance < 160931) { // 1 mile in cm
|
||||
mDistanceView.setText(String.format("%.0f", distance / 91.4392f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance / 91.4392f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_yd);
|
||||
} else {
|
||||
mDistanceView.setText(String.format("%.2f", distance / 160931.23f));
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 160931.23f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_mile);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class RSCManager extends BleManager<RSCManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableNotificationsRequest(mRSCMeasurementCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mRSCMeasurementCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,7 @@ public class RSCManager extends BleManager<RSCManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, RSCMeasurementParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + RSCMeasurementParser.parse(characteristic) + "\" received");
|
||||
|
||||
// Decode the new data
|
||||
int offset = 0;
|
||||
@@ -115,8 +114,8 @@ public class RSCManager extends BleManager<RSCManagerCallbacks> {
|
||||
}
|
||||
|
||||
// Notify listener about the new measurement
|
||||
mCallbacks.onMeasurementReceived(instantaneousSpeed, instantaneousCadence, totalDistance, instantaneousStrideLength, running ? RSCManagerCallbacks.ACTIVITY_RUNNING
|
||||
: RSCManagerCallbacks.ACTIVITY_WALKING);
|
||||
mCallbacks.onMeasurementReceived(gatt.getDevice(), instantaneousSpeed, instantaneousCadence, totalDistance, instantaneousStrideLength,
|
||||
running ? RSCManagerCallbacks.ACTIVITY_RUNNING : RSCManagerCallbacks.ACTIVITY_WALKING);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,12 +21,14 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.rsc;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface RSCManagerCallbacks extends BleManagerCallbacks {
|
||||
public static final int NOT_AVAILABLE = -1;
|
||||
public static final int ACTIVITY_WALKING = 0;
|
||||
public static final int ACTIVITY_RUNNING = 1;
|
||||
int NOT_AVAILABLE = -1;
|
||||
int ACTIVITY_WALKING = 0;
|
||||
int ACTIVITY_RUNNING = 1;
|
||||
|
||||
public void onMeasurementReceived(float speed, int cadence, float distance, float strideLen, int activity);
|
||||
void onMeasurementReceived(final BluetoothDevice device, float speed, int cadence, float distance, float strideLen, int activity);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.rsc;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -149,8 +150,9 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onMeasurementReceived(final float speed, final int cadence, final float totalDistance, final float strideLen, final int activity) {
|
||||
public void onMeasurementReceived(final BluetoothDevice device, final float speed, final int cadence, final float totalDistance, final float strideLen, final int activity) {
|
||||
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_TOTAL_DISTANCE, totalDistance);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.template;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -133,7 +134,7 @@ public class TemplateActivity extends BleProfileServiceReadyActivity<TemplateSer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public class TemplateManager extends BleManager<TemplateManagerCallbacks> {
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
// TODO initialize your device, enable required notifications and indications, write what needs to be written to start working
|
||||
requests.push(Request.newEnableNotificationsRequest(mCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -99,8 +99,7 @@ public class TemplateManager extends BleManager<TemplateManagerCallbacks> {
|
||||
// TODO this method is called when a notification has been received
|
||||
// This method may be removed from this class if not required
|
||||
|
||||
if (mLogSession != null)
|
||||
Logger.a(mLogSession, TemplateParser.parse(characteristic));
|
||||
Logger.a(mLogSession, "\"" + TemplateParser.parse(characteristic) + "\" received");
|
||||
|
||||
int value;
|
||||
final int flags = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
@@ -110,7 +109,7 @@ public class TemplateManager extends BleManager<TemplateManagerCallbacks> {
|
||||
value = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);
|
||||
}
|
||||
//This will send callback to the Activity when new value is received from HR device
|
||||
mCallbacks.onSampleValueReceived(value);
|
||||
mCallbacks.onSampleValueReceived(gatt.getDevice(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.template;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
/**
|
||||
@@ -32,10 +34,11 @@ public interface TemplateManagerCallbacks extends BleManagerCallbacks {
|
||||
|
||||
/**
|
||||
* Called when a value is received.
|
||||
*
|
||||
*
|
||||
* @param device a device from which the value was obtained
|
||||
* @param value
|
||||
* the new value
|
||||
*/
|
||||
public void onSampleValueReceived(int value);
|
||||
void onSampleValueReceived(final BluetoothDevice device, int value);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.template;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -112,8 +113,9 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampleValueReceived(final int value) {
|
||||
public void onSampleValueReceived(final BluetoothDevice device, final int value) {
|
||||
final Intent broadcast = new Intent(BROADCAST_TEMPLATE_MEASUREMENT);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, value);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.log.Logger;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
|
||||
|
||||
public class UARTManager extends BleManager<UARTManagerCallbacks> {
|
||||
@@ -66,7 +67,7 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
|
||||
@Override
|
||||
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
|
||||
final LinkedList<Request> requests = new LinkedList<>();
|
||||
requests.push(Request.newEnableNotificationsRequest(mTXCharacteristic));
|
||||
requests.add(Request.newEnableNotificationsRequest(mTXCharacteristic));
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -106,7 +107,9 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
|
||||
final byte[] buffer = mOutgoingBuffer;
|
||||
if (mBufferOffset == buffer.length) {
|
||||
try {
|
||||
mCallbacks.onDataSent(new String(buffer, "UTF-8"));
|
||||
final String data = new String(buffer, "UTF-8");
|
||||
Logger.a(mLogSession, "\"" + data + "\" sent");
|
||||
mCallbacks.onDataSent(gatt.getDevice(), data);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
// do nothing
|
||||
}
|
||||
@@ -124,7 +127,8 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
|
||||
@Override
|
||||
public void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
final String data = characteristic.getStringValue(0);
|
||||
mCallbacks.onDataReceived(data);
|
||||
Logger.a(mLogSession, "\"" + data + "\" received");
|
||||
mCallbacks.onDataReceived(gatt.getDevice(), data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.uart;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks;
|
||||
|
||||
public interface UARTManagerCallbacks extends BleManagerCallbacks {
|
||||
|
||||
public void onDataReceived(final String data);
|
||||
void onDataReceived(final BluetoothDevice device, final String data);
|
||||
|
||||
public void onDataSent(final String data);
|
||||
void onDataSent(final BluetoothDevice device, final String data);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,8 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.uart;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
@@ -33,7 +31,6 @@ import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
@@ -53,21 +50,21 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
* @param name the name
|
||||
* @param duplicate true if configuration is to be duplicated
|
||||
*/
|
||||
public void onNewConfiguration(final String name, final boolean duplicate);
|
||||
void onNewConfiguration(final String name, final boolean duplicate);
|
||||
|
||||
/**
|
||||
* Renames the current configuration with given name.
|
||||
* @param newName the new name
|
||||
*/
|
||||
public void onRenameConfiguration(final String newName);
|
||||
void onRenameConfiguration(final String newName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(final Activity activity) {
|
||||
super.onAttach(activity);
|
||||
public void onAttach(final Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
if (activity instanceof NewConfigurationDialogListener) {
|
||||
mListener = (NewConfigurationDialogListener) activity;
|
||||
if (context instanceof NewConfigurationDialogListener) {
|
||||
mListener = (NewConfigurationDialogListener) context;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The parent activity must implement NewConfigurationDialogListener");
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.uart;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -143,8 +144,8 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected() {
|
||||
super.onDeviceConnected();
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
super.onDeviceConnected(device);
|
||||
sendMessageToWearables(Constants.UART.DEVICE_CONNECTED, notNull(getDeviceName()));
|
||||
}
|
||||
|
||||
@@ -154,14 +155,14 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
sendMessageToWearables(Constants.UART.DEVICE_DISCONNECTED, notNull(getDeviceName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinklossOccur() {
|
||||
super.onLinklossOccur();
|
||||
public void onLinklossOccur(final BluetoothDevice device) {
|
||||
super.onLinklossOccur(device);
|
||||
sendMessageToWearables(Constants.UART.DEVICE_LINKLOSS, notNull(getDeviceName()));
|
||||
}
|
||||
|
||||
@@ -172,24 +173,23 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataReceived(final String data) {
|
||||
Logger.a(getLogSession(), "\"" + data + "\" received");
|
||||
|
||||
public void onDataReceived(final BluetoothDevice device, final String data) {
|
||||
final Intent broadcast = new Intent(BROADCAST_UART_RX);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, data);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
// send the data received to other apps, e.g. the Tasker
|
||||
final Intent globalBroadcast = new Intent(ACTION_RECEIVE);
|
||||
globalBroadcast.putExtra(BluetoothDevice.EXTRA_DEVICE, getBluetoothDevice());
|
||||
globalBroadcast.putExtra(Intent.EXTRA_TEXT, data);
|
||||
sendBroadcast(globalBroadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataSent(final String data) {
|
||||
Logger.a(getLogSession(), "\"" + data + "\" sent");
|
||||
|
||||
public void onDataSent(final BluetoothDevice device, final String data) {
|
||||
final Intent broadcast = new Intent(BROADCAST_UART_TX);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, data);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
style="@style/Widget.ListTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cgms_value_unit"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="4dp"/>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
style="@style/Widget.ListTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cgms_value_unit"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="4dp"/>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -20,52 +20,35 @@
|
||||
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeightSmall"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
|
||||
android:paddingTop="2dp"
|
||||
android:orientation="horizontal">
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="2dp">
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/details"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="12sp"
|
||||
android:text="@string/cgms_item_summary"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/details"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/time"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cgms_concentration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="right"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingLeft"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cgms_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:text="@string/cgms_value_unit"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -23,7 +23,5 @@
|
||||
|
||||
<resources>
|
||||
<string name="cgms_feature_title_long">CGMS</string>
|
||||
<string name="text_cgms_interval">GCM updates are notified every minute</string>
|
||||
<string name="cgms_item_summary">Glucose concentration level</string>
|
||||
<dimen name="cgms_feature_title_long_margin">-16dp</dimen>
|
||||
</resources>
|
||||
@@ -22,16 +22,15 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="cgms_feature_title">CGMS</string>
|
||||
<string name="cgms_feature_title_long">CONT. GLUCOSE MONITOR</string>
|
||||
<dimen name="cgms_feature_title_long_margin">-180dp</dimen>
|
||||
<string name="cgms_feature_title">CGMS</string>
|
||||
<string name="cgms_feature_title_long">CONT. GLUCOSE MONITOR</string>
|
||||
<dimen name="cgms_feature_title_long_margin">-180dp</dimen>
|
||||
|
||||
<string name="cgms_default_name">DEFAULT CGMS</string>
|
||||
<string name="cgms_value_unit">mg/dL</string>
|
||||
<string name="cgms_position_label">sensor position</string>
|
||||
<string name="cgms_default_name">DEFAULT CGMS</string>
|
||||
<string name="cgms_value_unit">mg/dL</string>
|
||||
<string name="cgms_details">Sequence number: %d</string>
|
||||
|
||||
<string name="cgms_about_text">CGMS (Continuous Glucode Monitoring Service) profile allows you to connect to your Continuous Glucose Monitoring sensor.
|
||||
It shows you the continuous glucose measurement on the table.</string>
|
||||
<string name="text_cgms_interval">GCM updates are notified every minute</string>
|
||||
<string name="cgms_item_summary">Glucose concentration level</string>
|
||||
It shows you the continuous glucose measurement on the table. A new record should show up on the list every minute. You may also request all, first or the last
|
||||
record using buttons below the list.</string>
|
||||
</resources>
|
||||
@@ -25,11 +25,8 @@ package no.nordicsemi.android.nrftoolbox.uart;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -82,7 +79,7 @@ public class UARTProfile extends BleProfile {
|
||||
|
||||
// We don't want to enable notifications on TX characteristic as we are not showing them here. A watch may be just used to send data. At least now.
|
||||
// final LinkedList<BleManager.Request> requests = new LinkedList<>();
|
||||
// requests.push(BleManager.Request.newEnableNotificationsRequest(mTXCharacteristic));
|
||||
// requests.add(BleManager.Request.newEnableNotificationsRequest(mTXCharacteristic));
|
||||
// return requests;
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user