Bugfix: GLS and Glucose Measurement Context information

This commit is contained in:
Aleksander Nowakowski
2017-11-02 11:27:39 +01:00
parent 4a786fe06a
commit 3c379d70b4
5 changed files with 129 additions and 65 deletions

View File

@@ -269,6 +269,6 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
@Override
public void onNumberOfRecordsRequested(final BluetoothDevice device, int value) {
showToast(getString(R.string.gls_progress, value));
showToast(getResources().getQuantityString(R.plurals.gls_progress, value, value));
}
}

View File

@@ -91,7 +91,7 @@ public class ExpandableRecordAdapter extends BaseExpandableListAdapter {
@Override
public int getChildrenCount(final int groupPosition) {
final GlucoseRecord record = (GlucoseRecord) getGroup(groupPosition);
int count = 1 + (record.status != 0 ? 1 : 0); // Sample Location and Sensor Status Annunciation
int count = 1 + (record.status != 0 ? 1 : 0); // Sample Location and optional Sensor Status Annunciation
if (record.context != null) {
final GlucoseRecord.MeasurementContext context = record.context;
if (context.carbohydrateId != 0)
@@ -116,48 +116,95 @@ public class ExpandableRecordAdapter extends BaseExpandableListAdapter {
public Object getChild(final int groupPosition, final int childPosition) {
final Resources resources = mContext.getResources();
final GlucoseRecord record = (GlucoseRecord) getGroup(groupPosition);
switch (childPosition) {
case 0:
String location = null;
try {
location = resources.getStringArray(R.array.gls_location)[record.sampleLocation];
} catch (final ArrayIndexOutOfBoundsException e) {
location = resources.getStringArray(R.array.gls_location)[0];
String tmp;
switch (childIdToItemId(childPosition, record)) {
case 0:
try {
tmp = resources.getStringArray(R.array.gls_location)[record.sampleLocation];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_location)[0];
}
return new Pair<>(resources.getString(R.string.gls_location_title), tmp);
case 1: { // sensor status annunciation
final StringBuilder builder = new StringBuilder();
final int status = record.status;
for (int i = 0; i < 12; ++i)
if ((status & (1 << i)) > 0)
builder.append(resources.getStringArray(R.array.gls_status_annunciation)[i]).append("\n");
builder.setLength(builder.length() - 1);
return new Pair<>(resources.getString(R.string.gls_status_annunciation_title), builder.toString());
}
return new Pair<>(resources.getString(R.string.gls_location_title), location);
case 1: { // sensor status annunciation
final StringBuilder builder = new StringBuilder();
final int status = record.status;
for (int i = 0; i < 12; ++i)
if ((status & (1 << i)) > 0)
builder.append(resources.getStringArray(R.array.gls_status_annunciation)[i]).append("\n");
builder.setLength(builder.length() - 1);
return new Pair<>(resources.getString(R.string.gls_status_annunciation_title), builder.toString());
}
case 2: { // carbohydrate id and unit
final StringBuilder builder = new StringBuilder();
builder.append(resources.getStringArray(R.array.gls_context_carbohydrare)[record.context.carbohydrateId]).append(" (").append(record.context.carbohydrateUnits).append(" kg)");
return new Pair<>(resources.getString(R.string.gls_context_carbohydrare_title), builder.toString());
}
case 3: { // meal
final StringBuilder builder = new StringBuilder();
builder.append(resources.getStringArray(R.array.gls_context_meal)[record.context.meal]);
return new Pair<>(resources.getString(R.string.gls_context_meal_title), builder.toString());
}
case 4: { // tester
final StringBuilder builder = new StringBuilder();
builder.append(resources.getStringArray(R.array.gls_context_tester)[record.context.tester]);
return new Pair<>(resources.getString(R.string.gls_context_tester_title), builder.toString());
}
case 5: { // health
final StringBuilder builder = new StringBuilder();
builder.append(resources.getStringArray(R.array.gls_context_health)[record.context.health]);
return new Pair<>(resources.getString(R.string.gls_context_health_title), builder.toString());
}
default:
// TODO write parsers for other properties
return new Pair<>("Not implemented", "The value exists but is not shown");
case 2: { // carbohydrate id and unit
try {
tmp = resources.getStringArray(R.array.gls_context_carbohydrare)[record.context.carbohydrateId];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_context_carbohydrare)[0];
}
return new Pair<>(resources.getString(R.string.gls_context_carbohydrare_title), tmp + " (" + record.context.carbohydrateUnits + " kg)");
}
case 3: { // meal
try {
tmp = resources.getStringArray(R.array.gls_context_meal)[record.context.meal];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_context_meal)[0];
}
return new Pair<>(resources.getString(R.string.gls_context_meal_title), tmp);
}
case 4: { // tester
try {
tmp = resources.getStringArray(R.array.gls_context_tester)[record.context.tester];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_context_tester)[0];
}
return new Pair<>(resources.getString(R.string.gls_context_tester_title), tmp);
}
case 5: { // health
try {
tmp = resources.getStringArray(R.array.gls_context_health)[record.context.health];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_context_health)[0];
}
return new Pair<>(resources.getString(R.string.gls_context_health_title), tmp);
}
case 6: { // exercise duration and intensity
return new Pair<>(resources.getString(R.string.gls_context_exercise_title), resources.getString(R.string.gls_context_exercise, record.context.exerciseDuration, record.context.exerciseIntensity));
}
case 7: { // medication ID and quantity
try {
tmp = resources.getStringArray(R.array.gls_context_medication_id)[record.context.medicationId];
} catch (final ArrayIndexOutOfBoundsException e) {
tmp = resources.getStringArray(R.array.gls_context_medication_id)[0];
}
final int resId = record.context.medicationUnit == GlucoseRecord.UNIT_kgpl ? R.string.gls_context_medication_kg : R.string.gls_context_medication_l;
return new Pair<>(resources.getString(R.string.gls_context_medication_title), resources.getString(resId, tmp, record.context.medicationQuantity));
}
case 8: { // HbA1c value
return new Pair<>(resources.getString(R.string.gls_context_hba1c_title), resources.getString(R.string.gls_context_hba1c, record.context.HbA1c));
}
default:
return new Pair<>("Not implemented", "The value exists but is not shown");
}
}
private int childIdToItemId(final int childPosition, final GlucoseRecord record) {
int itemId = 0;
int child = childPosition;
// Location is required
if (itemId == childPosition)
return itemId;
if (++itemId > 0 && record.status != 0 && --child == 0) return itemId;
if (record.context != null) {
if (++itemId > 0 && record.context.carbohydrateId != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.meal != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.tester != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.health != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.exerciseDuration != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.medicationId != 0 && --child == 0) return itemId;
if (++itemId > 0 && record.context.HbA1c != 0 && --child == 0) return itemId;
}
throw new IllegalArgumentException("No item ID for position " + childPosition);
}
@Override

View File

@@ -51,8 +51,6 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
@Override
protected void onCreateView(final Bundle savedInstanceState) {
// FEATURE_INDETERMINATE_PROGRESS notifies the system, that we are going to show indeterminate progress bar in the ActionBar (during device scan)
// requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); // <- Deprecated
setContentView(R.layout.activity_feature_gls);
setGUI();
}
@@ -150,6 +148,18 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
@Override
public void onOperationCompleted(final BluetoothDevice device) {
setOperationInProgress(false);
runOnUiThread(() -> {
final SparseArray<GlucoseRecord> records = mGlucoseManager.getRecords();
if (records.size() > 0) {
final int unit = records.valueAt(0).unit;
mUnitView.setVisibility(View.VISIBLE);
mUnitView.setText(unit == GlucoseRecord.UNIT_kgpl ? R.string.gls_unit_mgpdl : R.string.gls_unit_mmolpl);
} else {
mUnitView.setVisibility(View.GONE);
}
mAdapter.notifyDataSetChanged();
});
}
@Override
@@ -177,24 +187,11 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
@Override
public void onDatasetChanged(final BluetoothDevice device) {
runOnUiThread(new Runnable() {
@Override
public void run() {
final SparseArray<GlucoseRecord> records = mGlucoseManager.getRecords();
if (records.size() > 0) {
final int unit = records.valueAt(0).unit;
mUnitView.setVisibility(View.VISIBLE);
mUnitView.setText(unit == GlucoseRecord.UNIT_kgpl ? R.string.gls_unit_mgpdl : R.string.gls_unit_mmolpl);
} else
mUnitView.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
}
});
// Do nothing. Refreshing the list is done in onOperationCompleted
}
@Override
public void onNumberOfRecordsRequested(final BluetoothDevice device, final int value) {
showToast(getString(R.string.gls_progress, value));
showToast(getResources().getQuantityString(R.plurals.gls_progress, value, value));
}
}

View File

@@ -415,7 +415,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
*/
public void clear() {
mRecords.clear();
mCallbacks.onDatasetChanged(mBluetoothDevice);
mCallbacks.onOperationCompleted(mBluetoothDevice);
}
/**

View File

@@ -146,9 +146,30 @@
<item></item>
<item>Health value not available</item>
</string-array>
<string name="gls_context_exercise_title">Exercise</string>
<string name="gls_context_exercise">Duration: %ds, intensity: %d%%</string>
<string name="gls_context_medication_title">Medication</string>
<string name="gls_context_medication_kg">%s (%.2f mg)</string>
<string name="gls_context_medication_l">%s (%.2f ml)</string>
<string-array name="gls_context_medication_id">
<item>Reserved for future use</item>
<item>Rapid acting insulin</item>
<item>Short acting insulin</item>
<item>Intermediate acting insulin</item>
<item>Long acting insulin</item>
<item>Pre-mixed insulin</item>
</string-array>
<string name="gls_context_hba1c_title">HbA1c</string>
<string name="gls_context_hba1c">%f%%</string>
<string name="gls_progress">Downloading %d records</string>
<plurals name="gls_progress">
<item quantity="zero">No records found</item>
<item quantity="one">Downloading %d record</item>
<item quantity="two">Downloading %d records</item>
<item quantity="few">Downloading %d records</item>
<item quantity="other">Downloading %d records</item>
<item quantity="many">Downloading %d records</item>
</plurals>
<string name="gls_operation_not_supported">Operation not supported by the device</string>
<string name="gls_operation_failed">Operation failed</string>
<string name="gls_value">%.1f</string>
@@ -156,8 +177,7 @@
<string name="gls_unit_mmolpl">mmol/l</string>
<string name="gls_about_text">GLUCOSE SERVICE profile allows you to connect to your Glucose sensor.
You can read the last and historical glucose measurement readings from the device. The current implementation partially supports also the
Glucose Measurement Context characteristic which is not supported by the GLS sample in the NRF51 SDK,
therefore when connecting to this sample application some parameters are not displayed.</string>
You can read the last and historical glucose measurement readings from the device. The current implementation supports also the
Glucose Measurement Context characteristic which is not supported by the GLS sample in the NRF5x SDK.</string>
</resources>