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