From f70ff41791651c505aa80b0a6690368d8f758917 Mon Sep 17 00:00:00 2001 From: Pogman <subaziro@gmail.com> Date: Sun, 5 Mar 2017 15:55:15 +0000 Subject: [PATCH] EHSM changes and cleanup - cleanup commented out code - move sgv format conversion to main - removed need for EHSM pump comms - removed redundant channel change detection - removed temporary dbg code - added single retry for get pump time and status as occasional short lived noise can casue bad comms and retrying once catchs this rather then waiting until next poll --- .../android/medtronic/MainActivity.java | 39 ++++++--------- .../android/medtronic/MedtronicCnlReader.java | 25 +++++++++- .../message/ContourNextLinkMessage.java | 2 - .../message/PumpStatusRequestMessage.java | 6 +-- .../message/PumpTimeRequestMessage.java | 6 +-- .../message/PumpTimeResponseMessage.java | 1 - .../service/MedtronicCnlIntentService.java | 49 ++----------------- 7 files changed, 49 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java index 4b71e4b..bc72349 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java @@ -94,24 +94,14 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc private int chartZoom = 3; private boolean hasZoomedChart = false; - public static NumberFormat sgvFormatter; - public static boolean mmolxl; - private boolean mmolxlDecimals; + private NumberFormat sgvFormatter; + private static boolean mmolxl; + private static boolean mmolxlDecimals; - public static byte radioChannelInuse = 0; - public static long timeLastEHSM = 0; public static long timeLastGoodSGV = 0; public static short pumpBattery = 0; public static int countUnavailableSGV = 0; - // temporary debug stats for CNL connections - public static int dbgCNL_enterControlMode = 0; - public static int dbgCNL_enterPassthroughMode = 0; - public static int dbgCNL_openConnection = 0; - public static int dbgCNL_beginEHSMSession = 0; - public static int dbgCNL_clearMessage = 0; - public static int dbgCNL_not0x81 = 0; - boolean mEnableCgmService = true; SharedPreferences prefs = null; private PumpInfo mActivePump; @@ -124,6 +114,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver(); private MedtronicCnlAlarmReceiver medtronicCnlAlarmReceiver = new MedtronicCnlAlarmReceiver(); + public static String strFormatSGV(float sgvValue) { + if (mmolxl) { + NumberFormat sgvFormatter; + if (mmolxlDecimals) + sgvFormatter = new DecimalFormat("0.00"); + else + sgvFormatter = new DecimalFormat("0.0"); + return sgvFormatter.format(sgvValue / MMOLXLFACTOR); + } else { + return String.valueOf(sgvValue); + } + } public static long getNextPoll(PumpStatusEvent pumpStatusData) { long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset() @@ -333,7 +335,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc mChart.getGridLabelRenderer().setHumanRounding(false); mChart.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() { -// DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.SHORT); DateFormat mFormat = new SimpleDateFormat("HH:mm"); // 24 hour format forced to fix label overlap @Override @@ -341,11 +342,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc if (isValueX) { return mFormat.format(new Date((long) value)); } else { -// if (mmolxl) { -// return sgvFormatter.format(value / MMOLXLFACTOR); -// } else { return sgvFormatter.format(value); -// } } }} ); @@ -859,11 +856,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc double sgv = dataPoint.getY(); StringBuilder sb = new StringBuilder(mFormat.format(new Date((long) dataPoint.getX())) + ": "); -// if (mmolxl) { -// sb.append(sgvFormatter.format(sgv / MMOLXLFACTOR)); -// } else { - sb.append(sgvFormatter.format(sgv)); -// } + sb.append(sgvFormatter.format(sgv)); Toast.makeText(getBaseContext(), sb.toString(), Toast.LENGTH_SHORT).show(); } }); diff --git a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java index 8dde933..6763c82 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java @@ -171,7 +171,17 @@ public class MedtronicCnlReader { public Date getPumpTime() throws EncryptionException, IOException, ChecksumException, TimeoutException, UnexpectedMessageException { Log.d(TAG, "Begin getPumpTime"); - // FIXME - throw if not in EHSM mode (add a state machine) + + // CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this + try { + PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice); + Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime()); + return response.getPumpTime(); + } catch (UnexpectedMessageException e) { + Log.e(TAG, "Unexpected Message", e); + } catch (TimeoutException e) { + Log.e(TAG, "Timeout communicating with the Contour Next Link.", e); + } PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice); @@ -182,7 +192,18 @@ public class MedtronicCnlReader { public PumpStatusEvent updatePumpStatus(PumpStatusEvent pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException, UnexpectedMessageException { Log.d(TAG, "Begin updatePumpStatus"); - // FIXME - throw if not in EHSM mode (add a state machine) + // CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this + try { + PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice); + response.updatePumpRecord(pumpRecord); + Log.d(TAG, "Finished updatePumpStatus"); + return pumpRecord; + } catch (UnexpectedMessageException e) { + Log.e(TAG, "Unexpected Message", e); + } catch (TimeoutException e) { + Log.e(TAG, "Timeout communicating with the Contour Next Link.", e); + } + PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice); response.updatePumpRecord(pumpRecord); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java index 095c68c..8c340cb 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java @@ -152,7 +152,6 @@ public abstract class ContourNextLinkMessage { if (responseBytes[18] != (byte) 0x81) { doRetry = true; Log.d(TAG, "readMessage0x81: did not get 0x81 response, got " + responseBytes[18]); - MainActivity.dbgCNL_not0x81++; } else { doRetry = false; responseSize = responseBytes.length; @@ -185,7 +184,6 @@ public abstract class ContourNextLinkMessage { if (bytesClear > 0) { Log.d(TAG, "clearMessage: message stream cleared bytes: " + bytesClear); - MainActivity.dbgCNL_clearMessage++; } return bytesClear; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java index 32e1479..39403a8 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java @@ -23,9 +23,6 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage public PumpStatusResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { - // clear unexpected incoming messages - clearMessage(mDevice); - sendMessage(mDevice); if (millis > 0) { try { @@ -45,6 +42,9 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage } PumpStatusResponseMessage response = this.getResponse(readMessage(mDevice)); + // clear unexpected incoming messages + clearMessage(mDevice); + return response; } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java index 6aa7772..5928004 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java @@ -20,9 +20,6 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P @Override public PumpTimeResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { - // clear unexpected incoming messages - clearMessage(mDevice); - sendMessage(mDevice); if (millis > 0) { try { @@ -41,6 +38,9 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P // Read the 0x80 PumpTimeResponseMessage response = this.getResponse(readMessage(mDevice)); + // Pump sends additional 0x80 message when not using EHSM, lets clear this and any unexpected incoming messages + clearMessage(mDevice); + return response; } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java index 2a816cc..2005880 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java @@ -29,7 +29,6 @@ public class PumpTimeResponseMessage extends MedtronicSendMessageResponseMessage // TODO - deal with this more elegantly Log.e(TAG, "Invalid message received for getPumpTime"); throw new UnexpectedMessageException("Invalid message received for getPumpTime"); -// pumpTime = new Date(); } else { ByteBuffer dateBuffer = ByteBuffer.allocate(8); dateBuffer.order(ByteOrder.BIG_ENDIAN); diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java index 9b95b9d..3b85a0b 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java +++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java @@ -189,13 +189,10 @@ public class MedtronicCnlIntentService extends IntentService { cnlReader.getPumpSession().setStickSerial(info.getSerialNumber()); cnlReader.enterControlMode(); - MainActivity.dbgCNL_enterControlMode += 1; try { cnlReader.enterPassthroughMode(); - MainActivity.dbgCNL_enterPassthroughMode += 1; cnlReader.openConnection(); - MainActivity.dbgCNL_openConnection += 1; cnlReader.requestReadInfo(); @@ -224,33 +221,17 @@ public class MedtronicCnlIntentService extends IntentService { activePump.updateLastQueryTS(); - byte radioChannelInuse = MainActivity.radioChannelInuse; //note: holding here as last channel not always stored due to potential uncommitted transaction - byte radioChannel = cnlReader.negotiateChannel(radioChannelInuse); - MainActivity.radioChannelInuse = radioChannel; - - //byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel()); + byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel()); if (radioChannel == 0) { sendStatus("Could not communicate with the 640g. Are you near the pump?"); Log.i(TAG, "Could not communicate with the 640g. Are you near the pump?"); pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); // reduce polling interval to half until pump is available - } else if ((radioChannel != radioChannelInuse) && (radioChannelInuse != 0) && ((timePollStarted - MainActivity.timeLastEHSM) < (POLL_PERIOD_MS * 3L))) { - // avoid EHSM comms when channel change detected as this reduces any further channel changes and allows pump/sensor to resync - sendStatus(String.format(Locale.getDefault(), "Channel changed to %d", (int) radioChannel)); - sendStatus("SGV: unavailable from pump"); - Log.d(TAG, String.format("Channel changed to %d SGV: unavailable from pump", (int) radioChannel)); - MainActivity.countUnavailableSGV++; //poll clash detection - pollInterval = POLL_PERIOD_MS; // SGV should be available after default poll period } else { setActivePumpMac(pumpMAC); activePump.setLastRadioChannel(radioChannel); - //sendStatus(String.format(Locale.getDefault(), "Connected to Contour Next Link on channel %d.", (int) radioChannel)); sendStatus(String.format(Locale.getDefault(), "Connected on channel %d RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage())); Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel)); - MainActivity.timeLastEHSM = timePollStarted; - cnlReader.beginEHSMSession(); - MainActivity.dbgCNL_beginEHSMSession += 1; - // read pump status PumpStatusEvent pumpRecord = realm.createObject(PumpStatusEvent.class); @@ -269,22 +250,13 @@ public class MedtronicCnlIntentService extends IntentService { pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset)); cnlReader.updatePumpStatus(pumpRecord); - cnlReader.endEHSMSession(); - MainActivity.dbgCNL_beginEHSMSession -= 1; - if (pumpRecord.getSgv() != 0) { - String sgvString; - if (MainActivity.mmolxl) { - sgvString = MainActivity.sgvFormatter.format((float) pumpRecord.getSgv() / MainActivity.MMOLXLFACTOR); - } else { - sgvString = String.valueOf(pumpRecord.getSgv()); - } String offsetSign = ""; if (pumpOffset > 0) { offsetSign = "+"; } - sendStatus("SGV: " + sgvString + " At: " + df.format(pumpRecord.getEventDate().getTime()) + " Pump: " + offsetSign + (pumpOffset / 1000L) + "sec"); //note: event time is currently stored with offset + sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + " At: " + df.format(pumpRecord.getEventDate().getTime()) + " Pump: " + offsetSign + (pumpOffset / 1000L) + "sec"); //note: event time is currently stored with offset // Check if pump sent old event when new expected and schedule a re-poll if (((pumpRecord.getEventDate().getTime() - MainActivity.timeLastGoodSGV) < 5000L) && ((timePollExpected - timePollStarted) < 5000L)) { @@ -320,15 +292,11 @@ public class MedtronicCnlIntentService extends IntentService { sendMessage(Constants.ACTION_UPDATE_PUMP); } - // TODO - consider handling comms during EHSM errors separately as these tend to be CNL<-->PUMP lost/bad/noisy communication errors rather then Uploader<-->CNL errors } catch (UnexpectedMessageException e) { - // unexpected messages during CNL-->Pump comms are usually a lost/dropped connection - // CNL 0x81 message response for lost/dropped connection: 0x55 "u" pump response "55 0D 00 04 00 00 00 00 03 00 01 ..." note: EHSM is auto closed by CNL Log.e(TAG, "Unexpected Message", e); sendStatus("Communication Error: " + e.getMessage()); pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); } catch (TimeoutException e) { - // timeout during CNL-->Pump comms are usually a lost/dropped connection Log.e(TAG, "Timeout communicating with the Contour Next Link.", e); sendStatus("Timeout communicating with the Contour Next Link."); pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); @@ -338,11 +306,8 @@ public class MedtronicCnlIntentService extends IntentService { } finally { try { cnlReader.closeConnection(); - MainActivity.dbgCNL_openConnection -= 1; cnlReader.endPassthroughMode(); - MainActivity.dbgCNL_enterPassthroughMode -= 1; cnlReader.endControlMode(); - MainActivity.dbgCNL_enterControlMode -= 1; } catch (NoSuchAlgorithmException e) {} } @@ -383,7 +348,6 @@ public class MedtronicCnlIntentService extends IntentService { if ((nextRequestedPollTime - System.currentTimeMillis()) < 10000L) { nextRequestedPollTime = nextActualPollTime; } - // unavailable SGV from pump can be from a channel change due to radio noise // extended unavailable SGV may be due to clash with the current polling time // while we wait for a good SGV event, polling is auto adjusted by offsetting the next poll based on miss count if (MainActivity.countUnavailableSGV > 0) { @@ -398,11 +362,6 @@ public class MedtronicCnlIntentService extends IntentService { MedtronicCnlAlarmManager.setAlarm(nextRequestedPollTime); sendStatus("Next poll due at: " + df.format(nextRequestedPollTime)); - // temporary debug stats for CNL connections - if ((MainActivity.dbgCNL_enterControlMode + MainActivity.dbgCNL_enterPassthroughMode + MainActivity.dbgCNL_openConnection + MainActivity.dbgCNL_beginEHSMSession + MainActivity.dbgCNL_clearMessage + MainActivity.dbgCNL_not0x81) > 0) { - sendStatus("CM: " + MainActivity.dbgCNL_enterControlMode + " PT: " + MainActivity.dbgCNL_enterPassthroughMode + " OC: " + MainActivity.dbgCNL_openConnection + " EH: " + MainActivity.dbgCNL_beginEHSMSession + " U: " + MainActivity.dbgCNL_clearMessage + " X: " + MainActivity.dbgCNL_not0x81); - } - MedtronicCnlAlarmReceiver.completeWakefulIntent(intent); } } @@ -426,7 +385,7 @@ public class MedtronicCnlIntentService extends IntentService { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); if (prefs.getBoolean(getString(R.string.preference_enable_xdrip_plus), false)) { final Intent receiverIntent = new Intent(this, XDripPlusUploadReceiver.class); - final long timestamp = System.currentTimeMillis() + 1000L; //500L; + final long timestamp = System.currentTimeMillis() + 500L; final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int) timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT); Log.d(TAG, "Scheduling xDrip+ send"); wakeUpIntent(getApplicationContext(), timestamp, pendingIntent); @@ -435,7 +394,7 @@ public class MedtronicCnlIntentService extends IntentService { private void uploadToNightscout() { Intent receiverIntent = new Intent(this, NightscoutUploadReceiver.class); - final long timestamp = System.currentTimeMillis() + 2000L; //1000L; + final long timestamp = System.currentTimeMillis() + 1000L; final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int) timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT); wakeUpIntent(getApplicationContext(), timestamp, pendingIntent); } -- GitLab