From c564cc22144d962a3392806937de1cbca9327063 Mon Sep 17 00:00:00 2001 From: TebbeUbben Date: Tue, 12 Feb 2019 14:36:56 +0100 Subject: [PATCH 1/3] Reuse socket of failed connection --- .../InsightConnectionService.java | 24 +++++++++++-------- .../exceptions/ConnectionFailedException.java | 9 +++++++ .../utils/ConnectionEstablisher.java | 13 +++++----- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java index ce046420a2..57dc2cfcc0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java @@ -266,7 +266,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab recoveryTimer.interrupt(); recoveryTimer = null; setState(InsightState.DISCONNECTED); - cleanup(); + cleanup(true); } else if (state != InsightState.DISCONNECTED) { long disconnectTimeout = SP.getInt("insight_disconnect_delay", 5); disconnectTimeout = Math.min(disconnectTimeout, 15); @@ -281,7 +281,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab return connectionRequests.contains(lock); } - private void cleanup() { + private void cleanup(boolean closeSocket) { messageQueue.completeActiveRequest(new ConnectionLostException()); messageQueue.completePendingRequests(new ConnectionLostException()); if (recoveryTimer != null) { @@ -301,10 +301,12 @@ public class InsightConnectionService extends Service implements ConnectionEstab outputStreamWriter = null; } if (connectionEstablisher != null) { - connectionEstablisher.close(); + if (closeSocket) { + connectionEstablisher.close(closeSocket); + bluetoothSocket = null; + } connectionEstablisher = null; } - bluetoothSocket = null; if (timeoutTimer != null) { timeoutTimer.interrupt(); timeoutTimer = null; @@ -331,7 +333,9 @@ public class InsightConnectionService extends Service implements ConnectionEstab log.info("Exception occurred: " + e.getClass().getSimpleName()); if (pairingDataStorage.isPaired()) { setState(connectionRequests.size() != 0 ? InsightState.RECOVERING : InsightState.DISCONNECTED); - cleanup(); + if (e instanceof ConnectionFailedException) { + cleanup(((ConnectionFailedException) e).getDurationOfConnectionAttempt() <= 1000); + } else cleanup(true); messageQueue.completeActiveRequest(e); messageQueue.completePendingRequests(e); if (connectionRequests.size() != 0) { @@ -351,7 +355,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab } } else { setState(InsightState.NOT_PAIRED); - cleanup(); + cleanup(true); } for (ExceptionCallback exceptionCallback : exceptionCallbacks) exceptionCallback.onExceptionOccur(e); @@ -362,7 +366,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab sendAppLayerMessage(new DisconnectMessage()); sendSatlMessageAndWait(new info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DisconnectMessage()); } - cleanup(); + cleanup(true); setState(pairingDataStorage.isPaired() ? InsightState.DISCONNECTED : InsightState.NOT_PAIRED); } @@ -377,7 +381,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab if (connectionRequests.size() == 0) throw new IllegalStateException("A connection lock must be hold for pairing"); log.info("Pairing initiated"); - cleanup(); + cleanup(true); pairingDataStorage.setMacAddress(macAddress); connect(); } @@ -743,8 +747,8 @@ public class InsightConnectionService extends Service implements ConnectionEstab } @Override - public synchronized void onConnectionFail(Exception e) { - handleException(new ConnectionFailedException()); + public synchronized void onConnectionFail(Exception e, long duration) { + handleException(new ConnectionFailedException(duration)); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/exceptions/ConnectionFailedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/exceptions/ConnectionFailedException.java index 9c50fee053..dd53005b65 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/exceptions/ConnectionFailedException.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/exceptions/ConnectionFailedException.java @@ -2,4 +2,13 @@ package info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions; public class ConnectionFailedException extends InsightException { + private long durationOfConnectionAttempt; + + public ConnectionFailedException(long durationOfConnectionAttempt) { + this.durationOfConnectionAttempt = durationOfConnectionAttempt; + } + + public long getDurationOfConnectionAttempt() { + return durationOfConnectionAttempt; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/utils/ConnectionEstablisher.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/utils/ConnectionEstablisher.java index ed298fc958..921e2d407c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/utils/ConnectionEstablisher.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/utils/ConnectionEstablisher.java @@ -39,7 +39,7 @@ public class ConnectionEstablisher extends Thread { Method removeBond = bluetoothDevice.getClass().getMethod("removeBond", (Class[]) null); removeBond.invoke(bluetoothDevice, (Object[]) null); } catch (ReflectiveOperationException e) { - if (!isInterrupted()) callback.onConnectionFail(e); + if (!isInterrupted()) callback.onConnectionFail(e, 0); return; } } @@ -49,21 +49,22 @@ public class ConnectionEstablisher extends Thread { callback.onSocketCreated(socket); } } catch (IOException e) { - if (!isInterrupted()) callback.onConnectionFail(e); + if (!isInterrupted()) callback.onConnectionFail(e, 0); return; } + long connectionStart = System.currentTimeMillis(); try { socket.connect(); if (!isInterrupted()) callback.onConnectionSucceed(); } catch (IOException e) { - if (!isInterrupted()) callback.onConnectionFail(e); + if (!isInterrupted()) callback.onConnectionFail(e, System.currentTimeMillis() - connectionStart); } } - public void close() { + public void close(boolean closeSocket) { try { interrupt(); - if (socket != null && socket.isConnected()) socket.close(); + if (closeSocket && socket != null && socket.isConnected()) socket.close(); } catch (IOException ignored) { } } @@ -73,6 +74,6 @@ public class ConnectionEstablisher extends Thread { void onConnectionSucceed(); - void onConnectionFail(Exception e); + void onConnectionFail(Exception e, long duration); } } From a4312acb3e10625cf49ce17b8950e30b948df1a9 Mon Sep 17 00:00:00 2001 From: TebbeUbben Date: Tue, 12 Feb 2019 14:54:27 +0100 Subject: [PATCH 2/3] Incremental recovery duration --- .../LocalInsightFragment.java | 7 ++- .../InsightConnectionService.java | 44 ++++++++++++++----- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/pref_insight_local.xml | 10 ++++- 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java index a79fdad542..34a9597fb2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBas import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus; +import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; @@ -169,7 +170,8 @@ public class LocalInsightFragment extends SubscriberFragment implements View.OnC private void getConnectionStatusItem(List statusItems) { int string = 0; - switch (LocalInsightPlugin.getInstance().getConnectionService().getState()) { + InsightState state = LocalInsightPlugin.getInstance().getConnectionService().getState(); + switch (state) { case NOT_PAIRED: string = R.string.not_paired; break; @@ -199,6 +201,9 @@ public class LocalInsightFragment extends SubscriberFragment implements View.OnC break; } statusItems.add(getStatusItem(MainApp.gs(R.string.insight_status), MainApp.gs(string))); + if (state == InsightState.RECOVERING) { + statusItems.add(getStatusItem(MainApp.gs(R.string.recovery_duration), LocalInsightPlugin.getInstance().getConnectionService().getRecoveryDuration() / 1000 + "s")); + } } private void getLastConnectedItem(List statusItems) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java index 57dc2cfcc0..903a85aaac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java @@ -116,6 +116,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab private List activatedServices = new ArrayList<>(); private long lastDataTime; private long lastConnected; + private long recoveryDuration = 0; KeyPair getKeyPair() { if (keyPair == null) keyPair = Cryptograph.generateRSAKey(); @@ -130,6 +131,22 @@ public class InsightConnectionService extends Service implements ConnectionEstab return randomBytes; } + public synchronized long getRecoveryDuration() { + return recoveryDuration; + } + + private void increaseRecoveryDuration() { + long maxRecoveryDuration = SP.getInt("insight_max_recovery_duration", 20); + maxRecoveryDuration = Math.min(maxRecoveryDuration, 20); + maxRecoveryDuration = Math.max(maxRecoveryDuration, 0); + long minRecoveryDuration = SP.getInt("insight_min_recovery_duration", 5); + minRecoveryDuration = Math.min(minRecoveryDuration, 20); + minRecoveryDuration = Math.max(minRecoveryDuration, 0); + recoveryDuration += 1000; + recoveryDuration = Math.max(recoveryDuration, minRecoveryDuration * 1000); + recoveryDuration = Math.min(recoveryDuration, maxRecoveryDuration * 1000); + } + public long getLastConnected() { return lastConnected; } @@ -255,7 +272,10 @@ public class InsightConnectionService extends Service implements ConnectionEstab disconnectTimer.interrupt(); disconnectTimer = null; } - if (state == InsightState.DISCONNECTED && pairingDataStorage.isPaired()) connect(); + if (state == InsightState.DISCONNECTED && pairingDataStorage.isPaired()) { + recoveryDuration = 0; + connect(); + } } public synchronized void withdrawConnectionRequest(Object lock) { @@ -271,7 +291,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab long disconnectTimeout = SP.getInt("insight_disconnect_delay", 5); disconnectTimeout = Math.min(disconnectTimeout, 15); disconnectTimeout = Math.max(disconnectTimeout, 0); - log.info("Last connection lock released, will disconnect " + disconnectTimeout + " seconds"); + log.info("Last connection lock released, will disconnect in " + disconnectTimeout + " seconds"); disconnectTimer = DelayedActionThread.runDelayed("Disconnect Timer", disconnectTimeout * 1000, this::disconnect); } } @@ -342,15 +362,16 @@ public class InsightConnectionService extends Service implements ConnectionEstab if (!(e instanceof ConnectionFailedException)) { connect(); } else { - int recoveryDuration = SP.getInt("insight_recovery_duration", 5); - recoveryDuration = Math.min(recoveryDuration, 20); - recoveryDuration = Math.max(recoveryDuration, 0); - recoveryTimer = DelayedActionThread.runDelayed("RecoveryTimer", recoveryDuration * 1000, () -> { - recoveryTimer = null; - synchronized (InsightConnectionService.this) { - if (!Thread.currentThread().isInterrupted()) connect(); - } - }); + increaseRecoveryDuration(); + if (recoveryDuration == 0) connect(); + else { + recoveryTimer = DelayedActionThread.runDelayed("RecoveryTimer", recoveryDuration, () -> { + recoveryTimer = null; + synchronized (InsightConnectionService.this) { + if (!Thread.currentThread().isInterrupted()) connect(); + } + }); + } } } } else { @@ -402,6 +423,7 @@ public class InsightConnectionService extends Service implements ConnectionEstab @Override public synchronized void onConnectionSucceed() { try { + recoveryDuration = 0; inputStreamReader = new InputStreamReader(bluetoothSocket.getInputStream(), this); outputStreamWriter = new OutputStreamWriter(bluetoothSocket.getOutputStream(), this); inputStreamReader.start(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 60da39318b..b3cf7b8b47 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1230,7 +1230,6 @@ Log alerts Enable TBR emulation Use extended boluses instead of TBRs to bypass the 250% limit - Recovery duration [s] Disconnect delay [s] Serial number Release software version @@ -1273,6 +1272,9 @@ TDD: %1$.2f Reser.: %1$.2fU Batt.: %1$d%% + Max. recovery duration [s] + Min. recovery duration [s] + Recovery duration %1$d day diff --git a/app/src/main/res/xml/pref_insight_local.xml b/app/src/main/res/xml/pref_insight_local.xml index f1ec6ad94c..58dee3b182 100644 --- a/app/src/main/res/xml/pref_insight_local.xml +++ b/app/src/main/res/xml/pref_insight_local.xml @@ -40,8 +40,14 @@ + android:key="insight_min_recovery_duration" + android:title="@string/min_recovery_duration" /> + + Date: Tue, 12 Feb 2019 14:57:14 +0100 Subject: [PATCH 3/3] Log exceptions that occur in alert service --- .../PumpInsightLocal/InsightAlertService.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java index dbedf83867..676f64bf21 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java @@ -17,6 +17,10 @@ import android.os.Looper; import android.os.Vibrator; import android.support.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.plugins.PumpInsightLocal.activities.InsightAlertActivity; import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.ConfirmAlertMessage; import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SnoozeAlertMessage; @@ -26,10 +30,14 @@ import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertStatus; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType; import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState; +import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InsightException; +import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.AppLayerErrorException; import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator; public class InsightAlertService extends Service implements InsightConnectionService.StateCallback { + private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); + private LocalBinder localBinder = new LocalBinder(); private boolean connectionRequested; private final Object $alertLock = new Object[0]; @@ -164,7 +172,12 @@ public class InsightAlertService extends Service implements InsightConnectionSer } catch (InterruptedException ignored) { connectionService.withdrawConnectionRequest(thread); break; - } catch (Exception ignored) { + } catch (AppLayerErrorException e) { + log.info("Exception while fetching alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while fetching alert: " + e.getClass().getSimpleName()); + } catch (Exception e) { + log.error("Exception while fetching alert", e); } try { Thread.sleep(1000); @@ -207,7 +220,14 @@ public class InsightAlertService extends Service implements InsightConnectionSer SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage(); snoozeAlertMessage.setAlertID(alert.getAlertId()); connectionService.requestMessage(snoozeAlertMessage).await(); + } catch (AppLayerErrorException e) { + log.info("Exception while muting alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (InsightException e) { + log.info("Exception while muting alert: " + e.getClass().getSimpleName()); + ExceptionTranslator.makeToast(InsightAlertService.this, e); } catch (Exception e) { + log.error("Exception while muting alert", e); ExceptionTranslator.makeToast(InsightAlertService.this, e); } }).start(); @@ -219,7 +239,14 @@ public class InsightAlertService extends Service implements InsightConnectionSer ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage(); confirmAlertMessage.setAlertID(alert.getAlertId()); connectionService.requestMessage(confirmAlertMessage).await(); + } catch (AppLayerErrorException e) { + log.info("Exception while confirming alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (InsightException e) { + log.info("Exception while confirming alert: " + e.getClass().getSimpleName()); + ExceptionTranslator.makeToast(InsightAlertService.this, e); } catch (Exception e) { + log.error("Exception while confirming alert", e); ExceptionTranslator.makeToast(InsightAlertService.this, e); } }).start();