From ad381e3c261b97761548760e7623606ca533b4a6 Mon Sep 17 00:00:00 2001 From: Carlos Rafael Giani Date: Tue, 6 Dec 2022 23:14:54 +0100 Subject: [PATCH] comboctl: main: Improvements to Pump.setTbr() * Don't set a fake 100% TBR again if the current fake 100% TBR is finished within 15 minutes (reduces number of TBR operations and allows the Combo to return to a non-TBR state). * If the expected TBR percentage was a non-100% one, but not we see a non-TBR main screen, check if the expected TBR duration was <= 2 minutes. This covers the edge case when the TBR ends at the same time when we run this check. * Inform callers about the exact outcome of the setTbr() call. It could be that it set the TBR normally. Or, it might have set a fake 100% TBR (if the user requested a 100% TBR and force100Percent was set to false), and so on. Signed-off-by: Carlos Rafael Giani --- .../info/nightscout/comboctl/main/Pump.kt | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/pump/combov2/comboctl/src/commonMain/kotlin/info/nightscout/comboctl/main/Pump.kt b/pump/combov2/comboctl/src/commonMain/kotlin/info/nightscout/comboctl/main/Pump.kt index 0507cfe41b..745e23276c 100644 --- a/pump/combov2/comboctl/src/commonMain/kotlin/info/nightscout/comboctl/main/Pump.kt +++ b/pump/combov2/comboctl/src/commonMain/kotlin/info/nightscout/comboctl/main/Pump.kt @@ -1166,6 +1166,19 @@ class Pump( */ val setTbrProgressFlow = setTbrProgressReporter.progressFlow + /** + * Detail about the outcome of a successful [setTbr] call. + * + * Note that all of these describe a success. In case of failure, + * [setTbr] throws an exception. + */ + enum class SetTbrOutcome { + SET_NORMAL_TBR, + SET_EMULATED_100_TBR, + LETTING_EMULATED_100_TBR_FINISH, + IGNORED_REDUNDANT_100_TBR + } + /** * Sets the Combo's current temporary basal rate (TBR) via the remote terminal (RT) mode. * @@ -1199,6 +1212,9 @@ class Pump( * via the [onEvent] callback. Likewise, when a TBR finishes or is cancelled, * [Event.TbrEnded] is emitted. * + * When this function finishes successfully, it informs about the exact + * outcome through its return value. + * * @param percentage TBR percentage to set. * @param durationInMinutes TBR duration in minutes to set. * This argument is not used if [percentage] is 100. @@ -1209,6 +1225,7 @@ class Pump( * cancelling an ongoing TBR, which produces a W6 warning) or to fake a * 100% TBR by setting 90% / 110% TBRs (see above). * This argument is only used if [percentage] is 100. + * @return The specific outcome if setting the TBR succeeds. * @throws IllegalArgumentException if the percentage is not in the 0-500 range, * or if the percentage value is not an integer multiple of 10, or if * the duration is <15 or not an integer multiple of 15 (see the note @@ -1244,6 +1261,7 @@ class Pump( val currentStatus = statusFlow.value ?: throw IllegalStateException("Cannot start TBR without a known pump status") var expectedTbrPercentage: Int var expectedTbrDuration: Int + val result: SetTbrOutcome // In the code below, we always create a Tbr object _before_ calling // setCurrentTbr to make use of the checks in the Tbr constructor. @@ -1258,6 +1276,20 @@ class Pump( reportOngoingTbrAsStopped() expectedTbrPercentage = 100 expectedTbrDuration = 0 + result = SetTbrOutcome.SET_NORMAL_TBR + } else if ((currentStatus.tbrPercentage in 90..110) && (currentStatus.remainingTbrDurationInMinutes <= 15)) { + // If the current TBR is in the 90-110% range, it is pretty much a fake 100% TBR. + // So, if that fake TBR is done within 15 minutes, we don't actually set anything. + // Instead, we just let it run. That way, the pump can actually reach 100% TBR, + // and the amount of TBR adjustments is reduced. + expectedTbrPercentage = currentStatus.tbrPercentage + expectedTbrDuration = currentStatus.remainingTbrDurationInMinutes + result = SetTbrOutcome.LETTING_EMULATED_100_TBR_FINISH + logger(LogLevel.INFO) { + "Current TBR percentage is in the 90-110% range (${currentStatus.tbrPercentage}%)," + + "and it will finish in ${currentStatus.remainingTbrDurationInMinutes} minute(s); " + + "letting it finish and faking a successful TBR set operation" + } } else { val newPercentage = if (currentStatus.tbrPercentage < 100) 110 else 90 val tbr = Tbr( @@ -1270,6 +1302,7 @@ class Pump( reportStartedTbr(tbr) expectedTbrPercentage = newPercentage expectedTbrDuration = 15 + result = SetTbrOutcome.SET_EMULATED_100_TBR } } else { // Current status shows that there is no TBR ongoing. This is @@ -1278,6 +1311,7 @@ class Pump( expectedTbrPercentage = 100 expectedTbrDuration = 0 logger(LogLevel.INFO) { "TBR was already cancelled" } + result = SetTbrOutcome.IGNORED_REDUNDANT_100_TBR } } else { val tbr = Tbr( @@ -1291,6 +1325,7 @@ class Pump( reportStartedTbr(tbr) expectedTbrPercentage = percentage expectedTbrDuration = durationInMinutes + result = SetTbrOutcome.SET_NORMAL_TBR } // We just set the TBR. Now check the main screen contents to see if @@ -1314,9 +1349,12 @@ class Pump( throw ExtendedOrMultiwaveBolusActiveException(mainScreenContent) is MainScreenContent.Normal -> { - if (expectedTbrPercentage != 100) { + if ((expectedTbrPercentage != 100) && (expectedTbrDuration >= 2)) { // We expected a TBR to be active, but there isn't any; // we aren't seen any TBR main screen contents. + // Only consider this an error if the duration is >2 minutes. + // Otherwise, this was a TBR that was about to end, so it + // might have ended while these checks here were running. throw UnexpectedTbrStateException( expectedTbrPercentage = expectedTbrPercentage, expectedTbrDuration = expectedTbrDuration, @@ -1349,6 +1387,8 @@ class Pump( } } } + + return@executeCommand result } /**