implement basals

This commit is contained in:
Andrei Vereha 2021-06-05 14:18:04 +02:00
parent 33243a7ed4
commit 7c20bfb7f0
5 changed files with 76 additions and 32 deletions

View file

@ -15,6 +15,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.*
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants
@ -136,35 +137,42 @@ class OmnipodDashPumpPlugin @Inject constructor(
} }
override fun getPumpStatus(reason: String) { override fun getPumpStatus(reason: String) {
Observable.concat( val throwable = Completable.concat(listOf(
omnipodManager.getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE), omnipodManager
history.updateFromState(podStateManager).toObservable(), .getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE)
podStateManager.updateActiveCommand().toObservable(), .ignoreElements(),
).blockingSubscribeBy( history.updateFromState(podStateManager),
onNext = { podEvent -> podStateManager.updateActiveCommand()
aapsLogger.debug( .map { handleCommandConfirmation(it) }
LTag.PUMP, .ignoreElement(),
"Received PodEvent in getPumpStatus: $podEvent" )).blockingGet()
) if (throwable != null){
},
onError = { throwable ->
aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable) aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable)
}, } else {
onComplete = { aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success")
aapsLogger.debug("getPumpStatus completed")
} }
)
} }
override fun setNewBasalProfile(profile: Profile): PumpEnactResult { override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
val basalProgram = mapProfileToBasalProgram(profile)
return executeSimpleProgrammingCommand( return executeSimpleProgrammingCommand(
pre = suspendDeliveryIfActive(), pre = suspendDeliveryIfActive(),
historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE), historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE),
command = omnipodManager.setBasalProgram(mapProfileToBasalProgram(profile)) command = omnipodManager.setBasalProgram(basalProgram).ignoreElements(),
.ignoreElements(), basalProgram = basalProgram,
post = failWhenUnconfirmed(),
).toPumpEnactResult() ).toPumpEnactResult()
} }
private fun failWhenUnconfirmed(): Completable = Completable.defer{
if (podStateManager.activeCommand != null) {
Completable.error(java.lang.IllegalStateException("Command not confirmed"))
}else {
Completable.complete()
}
}
private fun suspendDeliveryIfActive(): Completable = Completable.defer { private fun suspendDeliveryIfActive(): Completable = Completable.defer {
if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED) if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED)
Completable.complete() Completable.complete()
@ -199,8 +207,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
return true return true
} }
// TODO: what do we have to answer here if delivery is suspended? // TODO: what do we have to answer here if delivery is suspended?
val running = pumpSync.expectedPumpState().profile val running = podStateManager.basalProgram
return running?.isEqual(profile) ?: false val equal = (mapProfileToBasalProgram(profile) == running)
aapsLogger.info(LTag.PUMP, "isThisProfileSet: $equal")
return equal
} }
override fun lastDataTime(): Long { override fun lastDataTime(): Long {
@ -615,13 +625,15 @@ class OmnipodDashPumpPlugin @Inject constructor(
historyEntry: Single<String>, historyEntry: Single<String>,
command: Completable, command: Completable,
pre: Completable = Completable.complete(), pre: Completable = Completable.complete(),
basalProgram: BasalProgram? = null,
post: Completable = Completable.complete(),
): Completable { ): Completable {
return Completable.concat( return Completable.concat(
listOf( listOf(
pre, pre,
podStateManager.observeNoActiveCommand().ignoreElements(), podStateManager.observeNoActiveCommand().ignoreElements(),
historyEntry historyEntry
.flatMap { podStateManager.createActiveCommand(it) } .flatMap { podStateManager.createActiveCommand(it, basalProgram) }
.ignoreElement(), .ignoreElement(),
command.doOnError { command.doOnError {
podStateManager.activeCommand?.sendError = it podStateManager.activeCommand?.sendError = it
@ -630,17 +642,18 @@ class OmnipodDashPumpPlugin @Inject constructor(
history.updateFromState(podStateManager), history.updateFromState(podStateManager),
podStateManager.updateActiveCommand() podStateManager.updateActiveCommand()
.map { handleCommandConfirmation(it) } .map { handleCommandConfirmation(it) }
.ignoreElement() .ignoreElement(),
post,
) )
) )
} }
private fun handleCommandConfirmation(confirmation: CommandConfirmed) { private fun handleCommandConfirmation(confirmation: CommandConfirmed) {
val historyEntry = history.getById(confirmation.historyId) val command = confirmation.command
val historyEntry = history.getById(command.historyId)
aapsLogger.debug(LTag.PUMPCOMM, "handling command confirmation: $confirmation") aapsLogger.debug(LTag.PUMPCOMM, "handling command confirmation: $confirmation")
when (historyEntry.commandType) { when (historyEntry.commandType) {
OmnipodCommandType.CANCEL_TEMPORARY_BASAL, OmnipodCommandType.CANCEL_TEMPORARY_BASAL,
OmnipodCommandType.SET_BASAL_PROFILE,
OmnipodCommandType.RESUME_DELIVERY -> OmnipodCommandType.RESUME_DELIVERY ->
// We can't invalidate this command, // We can't invalidate this command,
// and this is why it is pumpSync-ed at this point // and this is why it is pumpSync-ed at this point
@ -653,6 +666,21 @@ class OmnipodDashPumpPlugin @Inject constructor(
) )
} }
OmnipodCommandType.SET_BASAL_PROFILE -> {
if (confirmation.success) {
podStateManager.basalProgram = command.basalProgram
if (podStateManager.basalProgram == null) {
aapsLogger.warn(LTag.PUMP, "Saving null basal profile")
}
pumpSync.syncStopTemporaryBasalWithPumpId(
historyEntry.createdAt,
historyEntry.pumpId(),
PumpType.OMNIPOD_DASH,
serialNumber()
)
}
}
OmnipodCommandType.SET_TEMPORARY_BASAL -> { OmnipodCommandType.SET_TEMPORARY_BASAL -> {
// This treatment was synced before sending the command // This treatment was synced before sending the command
aapsLogger.info(LTag.PUMPCOMM, "temporary basal denied. PumpId: ${historyEntry.pumpId()}") aapsLogger.info(LTag.PUMPCOMM, "temporary basal denied. PumpId: ${historyEntry.pumpId()}")

View file

@ -17,7 +17,16 @@ class BasalProgram(
fun isZeroBasal() = segments.sumBy(Segment::basalRateInHundredthUnitsPerHour) == 0 fun isZeroBasal() = segments.sumBy(Segment::basalRateInHundredthUnitsPerHour) == 0
fun rateAt(date: Date): Double = 0.0 // TODO fun rateAt(date: Date): Double {
val instance = Calendar.getInstance()
instance.time = date
val hourOfDay = instance[Calendar.HOUR_OF_DAY]
val minuteOfHour = instance[Calendar.MINUTE]
val slotIndex = hourOfDay * 2 + minuteOfHour.div(30)
val slot = segments.find { it.startSlotIndex <= slotIndex && slotIndex< it.endSlotIndex }
val ret = (slot?.basalRateInHundredthUnitsPerHour ?: 0).toDouble() / 100
return ret
}
class Segment( class Segment(
val startSlotIndex: Short, val startSlotIndex: Short,

View file

@ -1,3 +1,3 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state
data class CommandConfirmed(val historyId: String, val success: Boolean) data class CommandConfirmed(val command: OmnipodDashPodStateManager.ActiveCommand, val success: Boolean)

View file

@ -257,13 +257,13 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
CommandConfirmationDenied -> { CommandConfirmationDenied -> {
podState.activeCommand = null podState.activeCommand = null
source.onSuccess(CommandConfirmed(activeCommand.historyId, false)) source.onSuccess(CommandConfirmed(activeCommand, false))
} }
CommandConfirmationSuccess -> { CommandConfirmationSuccess -> {
podState.activeCommand = null podState.activeCommand = null
source.onSuccess(CommandConfirmed(activeCommand.historyId, true)) source.onSuccess(CommandConfirmed(activeCommand, true))
} }
NoActiveCommand -> { NoActiveCommand -> {

View file

@ -298,8 +298,15 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
*/ */
// base basal rate // base basal rate
// TODO: check if delivery is suspended podInfoBinding.baseBasalRate.text = if (podStateManager.basalProgram != null && !podStateManager.isSuspended) {
podInfoBinding.baseBasalRate.text = PLACEHOLDER resourceHelper.gs(
R.string.pump_basebasalrate,
omnipodDashPumpPlugin.model()
.determineCorrectBasalSize(podStateManager.basalProgram!!.rateAt(Date()))
)
} else {
PLACEHOLDER
}
// total delivered // total delivered
podInfoBinding.totalDelivered.text = podInfoBinding.totalDelivered.text =