From 14c39ee05eb8d400cf54c71fd756ec7d20896a35 Mon Sep 17 00:00:00 2001 From: Carlos Rafael Giani Date: Tue, 6 Dec 2022 21:56:42 +0100 Subject: [PATCH 1/3] Fix comboctl unit test integration Signed-off-by: Carlos Rafael Giani --- pump/combov2/comboctl/build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pump/combov2/comboctl/build.gradle b/pump/combov2/comboctl/build.gradle index ba5ea343da..645f764f7c 100644 --- a/pump/combov2/comboctl/build.gradle +++ b/pump/combov2/comboctl/build.gradle @@ -1,8 +1,14 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' +plugins { + id 'com.android.library' + id 'kotlin-android' + id 'kotlin-kapt' + id 'com.hiya.jacoco-android' +} apply from: "${project.rootDir}/core/main/android_dependencies.gradle" +apply from: "${project.rootDir}/core/main/android_module_dependencies.gradle" apply from: "${project.rootDir}/core/main/test_dependencies.gradle" +apply from: "${project.rootDir}/core/main/jacoco_global.gradle" android { namespace 'info.nightscout.comboctl' From ad381e3c261b97761548760e7623606ca533b4a6 Mon Sep 17 00:00:00 2001 From: Carlos Rafael Giani Date: Tue, 6 Dec 2022 23:14:54 +0100 Subject: [PATCH 2/3] 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 } /** From 9fdc89ee72cc1c9610e75e8dd1272757f14f5d08 Mon Sep 17 00:00:00 2001 From: Carlos Rafael Giani Date: Tue, 6 Dec 2022 23:23:52 +0100 Subject: [PATCH 3/3] combov2: Use more specific PumpEnactResult comment after setTbr() finishes Signed-off-by: Carlos Rafael Giani --- .../nightscout/pump/combov2/ComboV2Plugin.kt | 31 ++++++++++++++----- pump/combov2/src/main/res/values/strings.xml | 3 ++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pump/combov2/src/main/kotlin/info/nightscout/pump/combov2/ComboV2Plugin.kt b/pump/combov2/src/main/kotlin/info/nightscout/pump/combov2/ComboV2Plugin.kt index b2e19253db..6a71eef58a 100644 --- a/pump/combov2/src/main/kotlin/info/nightscout/pump/combov2/ComboV2Plugin.kt +++ b/pump/combov2/src/main/kotlin/info/nightscout/pump/combov2/ComboV2Plugin.kt @@ -1091,17 +1091,34 @@ class ComboV2Plugin @Inject constructor ( return pumpEnactResult } - private fun setTbrInternal(percentage: Int, durationInMinutes: Int, tbrType: ComboCtlTbr.Type, force100Percent: Boolean, pumpEnactResult: PumpEnactResult) { + private fun setTbrInternal( + percentage: Int, + durationInMinutes: Int, + tbrType: ComboCtlTbr.Type, + force100Percent: Boolean, + pumpEnactResult: PumpEnactResult + ) { runBlocking { try { executeCommand { - pump!!.setTbr(percentage, durationInMinutes, tbrType, force100Percent) - } + val setTbrOutcome = pump!!.setTbr(percentage, durationInMinutes, tbrType, force100Percent) - pumpEnactResult.apply { - success = true - enacted = true - comment = rh.gs(R.string.combov2_setting_tbr_succeeded) + val tbrComment = when (setTbrOutcome) { + ComboCtlPump.SetTbrOutcome.SET_NORMAL_TBR -> + rh.gs(R.string.combov2_setting_tbr_succeeded) + ComboCtlPump.SetTbrOutcome.SET_EMULATED_100_TBR -> + rh.gs(R.string.combov2_set_emulated_100_tbr) + ComboCtlPump.SetTbrOutcome.LETTING_EMULATED_100_TBR_FINISH -> + rh.gs(R.string.combov2_letting_emulated_100_tbr_finish) + ComboCtlPump.SetTbrOutcome.IGNORED_REDUNDANT_100_TBR -> + rh.gs(R.string.combov2_ignoring_redundant_100_tbr) + } + + pumpEnactResult.apply { + success = true + enacted = true + comment = tbrComment + } } } catch (e: QuantityNotChangingException) { aapsLogger.error(LTag.PUMP, "TBR percentage adjustment hit a limit: $e") diff --git a/pump/combov2/src/main/res/values/strings.xml b/pump/combov2/src/main/res/values/strings.xml index 0e0516736b..ca0047ff78 100644 --- a/pump/combov2/src/main/res/values/strings.xml +++ b/pump/combov2/src/main/res/values/strings.xml @@ -107,6 +107,9 @@ buttons at the same time to cancel pairing)\n Pump reservoir level is low Setting TBR succeeded Setting TBR failed + Set emulated 100% TBR + Letting ongoing emulated 100% TBR finish + Ignoring redundant 100% TBR request Unexpected limit encountered while adjusting TBR: target percentage was %1$d%%, hit a limit at %1$d%% Cannot set absolute TBR if base basal rate is zero Pair AndroidAPS and Android with a currently unpaired Accu-Chek Combo pump