From 3333d7a6b71a410c90545bd4fe120d84964672eb Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 27 Dec 2017 11:36:01 +0100 Subject: [PATCH] Clean up all the basal rate sanity checks. * Disable loop entirely if no valid basal rate is set on the pump. Neither closed nor open loop mode makes sense without it. * Check active BR before updating the pump profile * Show 'loop disabled' state in Combo fragement. * Cancel active TBR when basal profile switch to profile != 1 is detected or when an unsupported bolus is active. --- Testing-Combo.md | 17 +++++++--- .../plugins/PumpCombo/ComboPlugin.java | 34 ++++++++++++++----- app/src/main/res/values-de/strings.xml | 1 + 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Testing-Combo.md b/Testing-Combo.md index 56e39c07eb..f47aa4e0b2 100644 --- a/Testing-Combo.md +++ b/Testing-Combo.md @@ -74,12 +74,19 @@ - [ ] Check displayed data (state, battery, reservoir, temp basal) is the same as on the pump - [ ] Unsafe usage - - [ ] An extended or multiwave bolus given within the last six hour must raise an alert and - restrict the loop functionality to low-suspend only (setting maxIOB to zero) + - [ ] An active extended or multiwave bolus must raise an alert and + restrict the loop functionality to low-suspend only for the next 6h (setting maxIOB to zero) + and cancel an active TBR. - [ ] Closed loop functionality must resume 6 h after the last ext/multiwave bolus - - [ ] An active ext/multiwave bolus must also raise an alert and restrict the loop - - [ ] If a basal rate other than profile 1 is activated, this must also raise an alert and disable - the restrict the loop + - [ ] If a basal rate other than profile 1 is active on start, the pump must refuse to finish + initialization and disable the loop. When setting the profile to 1 and refreshing, + the pump must finish initialization and enable the loop (the overview screen will + still show "closed loop", but the Combo and Loop tabs will say the loop is disabled + due to a constraint violation). + - [ ] When changing profile to one other than the first after AAPS has started and read the first + basal profile, a warning must be shown, the loop must be disabled and the active TBR be cancelled. + - [ ] A request to change the AAPS profil (e.g. increase to 110%) must be rejected if the pump + doesn't have profile one active. - [ ] Reading/setting basal profile - [ ] AAPS reads basal rate properly - [ ] Test profile with 115% (or something like that) change to ask the diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java index 8187ab55c5..271a0de9a0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java @@ -41,6 +41,7 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; @@ -138,7 +139,9 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf String getStateSummary() { PumpState ps = pump.state; - if (ps.activeAlert != null) { + if (!validBasalRateProfileSelectedOnPump) { + return MainApp.sResources.getString(R.string.loopdisabled); + } else if (ps.activeAlert != null) { return ps.activeAlert.errorCode != null ? "E" + ps.activeAlert.errorCode + ": " + ps.activeAlert.message : "W" + ps.activeAlert.warningCode + ": " + ps.activeAlert.message; @@ -258,6 +261,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf return new PumpEnactResult().success(true).enacted(false); } + CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState); + if (stateResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) { + return new PumpEnactResult().success(false).enacted(false).comment(MainApp.sResources.getString(R.string.combo_force_disabled_notification)); + } + CommandResult setResult = runCommand(MainApp.sResources.getString(R.string.combo_activity_setting_basal_profile), 2, () -> ruffyScripter.setBasalProfile(requestedBasalProfile)); if (!setResult.success) { @@ -357,7 +365,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf Notification.URGENT); n.soundId = R.raw.alarm; MainApp.bus().post(new EventNewNotification(n)); - violationWarningRaisedForViolationAt = lowSuspendOnlyLoopEnforcedUntil; return; } @@ -723,7 +730,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (commandResult.success) { pump.lastSuccessfulCmdTime = System.currentTimeMillis(); - validBasalRateProfileSelectedOnPump = commandResult.state.unsafeUsageDetected != PumpState.UNSUPPORTED_BASAL_RATE_PROFILE; + if (validBasalRateProfileSelectedOnPump && commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) { + validBasalRateProfileSelectedOnPump = false; + Notification n = new Notification(Notification.COMBO_PUMP_ALARM, + MainApp.sResources.getString(R.string.combo_force_disabled_notification), + Notification.URGENT); + n.soundId = R.raw.alarm; + MainApp.bus().post(new EventNewNotification(n)); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null); + } updateLocalData(commandResult); } } finally { @@ -765,7 +780,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf notification.date = new Date(); notification.id = Notification.COMBO_PUMP_ALARM; notification.level = Notification.URGENT; - notification.text = MainApp.sResources.getString(R.string.combo_is_in_error_state); + notification.text = MainApp.sResources.getString(R.string.combo_is_in_error_state, activeAlert.errorCode, activeAlert.message); MainApp.bus().post(new EventNewNotification(notification)); return preCheckResult.success(false); } @@ -829,13 +844,14 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } if (lastViolation > 0) { lowSuspendOnlyLoopEnforcedUntil = lastViolation + 6 * 60 * 60 * 1000; - if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis() && violationWarningRaisedForViolationAt != lowSuspendOnlyLoopEnforcedUntil) { + if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis() && violationWarningRaisedForBolusAt != lowSuspendOnlyLoopEnforcedUntil) { Notification n = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.sResources.getString(R.string.combo_low_suspend_forced_notification), Notification.URGENT); n.soundId = R.raw.alarm; MainApp.bus().post(new EventNewNotification(n)); - violationWarningRaisedForViolationAt = lowSuspendOnlyLoopEnforcedUntil; + violationWarningRaisedForBolusAt = lowSuspendOnlyLoopEnforcedUntil; + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null); } } } @@ -1064,17 +1080,17 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf // Constraints interface private long lowSuspendOnlyLoopEnforcedUntil = 0; - private long violationWarningRaisedForViolationAt = 0; + private long violationWarningRaisedForBolusAt = 0; private boolean validBasalRateProfileSelectedOnPump = false; @Override public boolean isLoopEnabled() { - return true; + return validBasalRateProfileSelectedOnPump; } @Override public boolean isClosedModeEnabled() { - return validBasalRateProfileSelectedOnPump; + return true; } @Override diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 73e1f23de1..4a08c1662c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -726,4 +726,5 @@ Um die TDD-Statistik der Pumpe zu lesen, drücken Sie den TDDS Knopf lange.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden. Sind Sie sich sicher, dass Sie diese Aktion ausführen möchen und verstehen Sie die Konsequenzen die sich daraus ergeben? Diese Aktion wird die gesamte Historik und die Basalrate aus der Pumpe auslesen. Boli und temporäre Basalrate werden zu den Behandlungen hinzugefügt wenn diese noch nicht vorhanden sind. Dies kann zu doppelten Einträge und somit zu falschen IOB-Werten führen, da die Uhr der Pumpe ungenau ist. Diese Aktion sollte NIE durchgeführt werden wenn die Pumpe im Loop verwendet wird. Wenn Sie diese Aktion trotzdem durchführen möchten, drücken Sie lange erneut auf den diesen Knopf.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden. + Dringender Alarm