Merge pull request #2489 from dv1/combov2-fixes-001

combov2: Use dedicated variable for keeping track of suspended state
This commit is contained in:
Milos Kozak 2023-04-04 08:59:28 +02:00 committed by GitHub
commit 5b60b8ab90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -189,6 +189,18 @@ class ComboV2Plugin @Inject constructor (
// allow other components to react to state changes. // allow other components to react to state changes.
private val _driverStateFlow = MutableStateFlow<DriverState>(DriverState.NotInitialized) private val _driverStateFlow = MutableStateFlow<DriverState>(DriverState.NotInitialized)
// If true, the pump was found to be suspended during the connect()
// call. This is separate from driverStateFlow and driverStateUIFlow.
// It is set immediately after connect() (while the other two may be
// set in a separate coroutine), which is important for check
// inside connect() and checks before commands like deliverTreatment()
// are run. This is what drives the isSuspended() call, and is _not_
// to be used for UI update purposes (use driverStateUIFlow for that).
// Like driverStateUIFlow, this state persists even after disconnecting
// from the pump. This is necessary, because AAPS may call isSuspended()
// even when the pump is not connected.
private var pumpIsSuspended = false
// The basal profile that is set to be the pump's current profile. // The basal profile that is set to be the pump's current profile.
// If the pump's actual basal profile deviates from this, it is // If the pump's actual basal profile deviates from this, it is
// overwritten. This check is performed in checkBasalProfile(). // overwritten. This check is performed in checkBasalProfile().
@ -225,15 +237,19 @@ class ComboV2Plugin @Inject constructor (
// Driver is connected, but pump is suspended and // Driver is connected, but pump is suspended and
// cannot currently execute commands. This state is // cannot currently execute commands. This state is
// special in that it technically persists even after // special in that it technically persists even after
// disconnecting. However, it is still important to // disconnecting (because the pump remains suspended
// model it as a driver state to prevent commands // until the user resumes it, not until the connection
// that deliver insulin from being executed (and, // is terminated), but it does not persists the same
// it is needed for the isSuspended() implementation). // way here (it is replaced by Disconnected after
// NOTE: Instead of comparing the driverStateFlow // the connection is terminated). This state is used
// value with this state directly, consider using // for UI updates (see driverStateUIFlow) and for
// isSuspended() instead, since it is based on the // checks during driver state updates and connection
// driverStateUIFlow, and thus retains the Suspended // attempts.
// and Error states even after disconnecting. // NOTE: Do not compare against this state to check
// prior to commands like deliverTreatment() if
// the pump is currently suspended or not. Use
// isSuspended() instead. See the pumpIsSuspended
// documentation for details.
object Suspended : DriverState("suspended") object Suspended : DriverState("suspended")
// Driver is currently executing a command. // Driver is currently executing a command.
// isBusy() will return true in this state. // isBusy() will return true in this state.
@ -453,12 +469,7 @@ class ComboV2Plugin @Inject constructor (
override fun isInitialized(): Boolean = override fun isInitialized(): Boolean =
isPaired() && (driverStateFlow.value != DriverState.NotInitialized) && !pumpErrorObserved isPaired() && (driverStateFlow.value != DriverState.NotInitialized) && !pumpErrorObserved
override fun isSuspended(): Boolean = override fun isSuspended(): Boolean = pumpIsSuspended
when (driverStateUIFlow.value) {
DriverState.Suspended,
DriverState.Error -> true
else -> false
}
override fun isBusy(): Boolean = override fun isBusy(): Boolean =
when (driverStateFlow.value) { when (driverStateFlow.value) {
@ -656,6 +667,14 @@ class ComboV2Plugin @Inject constructor (
// No need to set the driver state here, since the pump's stateFlow will announce that. // No need to set the driver state here, since the pump's stateFlow will announce that.
pump?.let { pump?.let {
pumpIsSuspended = when (it.stateFlow.value) {
ComboCtlPump.State.Suspended,
is ComboCtlPump.State.Error -> true
else -> false
}
aapsLogger.debug(LTag.PUMP, "Pump is suspended: $pumpIsSuspended")
// We can't read the active profile number in the suspended state, since // We can't read the active profile number in the suspended state, since
// the Combo's screen does not show any profile number then. // the Combo's screen does not show any profile number then.
if (!isSuspended()) { if (!isSuspended()) {
@ -1729,6 +1748,12 @@ class ComboV2Plugin @Inject constructor (
// This is a variant of driverStateFlow that retains the Error // This is a variant of driverStateFlow that retains the Error
// and Suspended state even after disconnecting to make sure these // and Suspended state even after disconnecting to make sure these
// states kept being showed to the user post-disconnect. // states kept being showed to the user post-disconnect.
// NOTE: Do not rely on this to check prior to a command if the
// pump is suspended or not, since the driver state UI flow is
// updated in a separate coroutine, and is _only_ meant for UI
// updates. Using this for other purposes can cause race conditions
// to appear, such as when immediately after the Pump.connect() call
// finishes, the state is checked. Use isSuspended() instead.
private val _driverStateUIFlow = MutableStateFlow<DriverState>(DriverState.NotInitialized) private val _driverStateUIFlow = MutableStateFlow<DriverState>(DriverState.NotInitialized)
val driverStateUIFlow = _driverStateUIFlow.asStateFlow() val driverStateUIFlow = _driverStateUIFlow.asStateFlow()