bolus: send progress

This commit is contained in:
Andrei Vereha 2021-06-06 12:24:32 +02:00
parent 79b4a5d656
commit b80327c9bf

View file

@ -12,6 +12,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.* import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.*
@ -39,12 +40,13 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy import io.reactivex.rxkotlin.subscribeBy
import org.json.JSONObject import org.json.JSONObject
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.math.ceil
@Singleton @Singleton
class OmnipodDashPumpPlugin @Inject constructor( class OmnipodDashPumpPlugin @Inject constructor(
@ -240,59 +242,103 @@ class OmnipodDashPumpPlugin @Inject constructor(
get() = 0 get() = 0
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
// TODO update Treatments (?)
// TODO bolus progress
// TODO report actual delivered amount after Pod Alarm and bolus cancellation // TODO report actual delivered amount after Pod Alarm and bolus cancellation
return Single.create<PumpEnactResult> { source ->
val bolusBeeps = sp.getBoolean(R.string.key_omnipod_common_bolus_beeps_enabled, false) val bolusBeeps = sp.getBoolean(R.string.key_omnipod_common_bolus_beeps_enabled, false)
Observable.concat( if (detailedBolusInfo.carbs > 0 || detailedBolusInfo.insulin == 0.0) {
history.createRecord( return PumpEnactResult(injector)
.success(false)
.enacted(false)
.bolusDelivered(0.0)
.carbsDelivered(0.0)
.comment("Invalid input");
}
val requestedBolusAmount = detailedBolusInfo.insulin
var delieveredBolusAmount = 0.0
aapsLogger.info(
LTag.PUMP,
"deliverTreatment: units: ${requestedBolusAmount}"
)
return executeProgrammingCommand(
pre = observeNoActiveTempBasal(true),
historyEntry = history.createRecord(
commandType = OmnipodCommandType.SET_BOLUS, commandType = OmnipodCommandType.SET_BOLUS,
bolusRecord = BolusRecord( bolusRecord = BolusRecord(
detailedBolusInfo.insulin, requestedBolusAmount,
BolusType.fromBolusInfoBolusType(detailedBolusInfo.bolusType), BolusType.fromBolusInfoBolusType(detailedBolusInfo.bolusType)
)
), ),
).flatMapObservable { recordId -> command = omnipodManager.bolus(
podStateManager.createActiveCommand(recordId).toObservable()
},
omnipodManager.bolus(
detailedBolusInfo.insulin, detailedBolusInfo.insulin,
bolusBeeps, bolusBeeps,
bolusBeeps bolusBeeps
), ).filter { podEvent -> podEvent is PodEvent.CommandSent }
history.updateFromState(podStateManager).toObservable(), .map { pumpSyncBolusStart(it, requestedBolusAmount, detailedBolusInfo.bolusType) }
podStateManager.updateActiveCommand().toObservable(), .ignoreElements(),
).subscribeBy( post = waitForBolusDeliveryToComplete(5, requestedBolusAmount, detailedBolusInfo.bolusType)
onNext = { podEvent -> ).toSingleDefault(PumpEnactResult(injector).success(true).enacted(true).bolusDelivered(delieveredBolusAmount))
aapsLogger.debug( .onErrorReturnItem(PumpEnactResult(injector).success(false).enacted(false))
LTag.PUMP, .blockingGet()
"Received PodEvent in deliverTreatment: $podEvent" }
)
}, private fun waitForBolusDeliveryToComplete(
onError = { throwable -> maxRetriesAtTheEnd: Int,
aapsLogger.error(LTag.PUMP, "Error in deliverTreatment", throwable) requestedBolusAmount: Double,
source.onSuccess( bolusType: DetailedBolusInfo.BolusType
PumpEnactResult(injector).success(false).enacted(false).comment( ): Completable {
throwable.toString() // TODO: wait for bolus delivery to start!
) // For now, we assume it started with success
)
}, val estimatedDeliveryTimeSeconds = ceil(requestedBolusAmount / 0.05).toLong() * 2
onComplete = { aapsLogger.info(LTag.PUMP, "estimatedDeliveryTimeSeconds: $estimatedDeliveryTimeSeconds")
aapsLogger.debug("deliverTreatment completed") return Completable.concat(listOf(
source.onSuccess( Observable.interval(1, TimeUnit.SECONDS)
PumpEnactResult(injector).success(true).enacted(true) .take(estimatedDeliveryTimeSeconds)
.bolusDelivered(detailedBolusInfo.insulin) .doOnNext {
.carbsDelivered(detailedBolusInfo.carbs) if (bolusType == DetailedBolusInfo.BolusType.SMB) {
return@doOnNext
}
val progressUpdateEvent = EventOverviewBolusProgress
val percent = (100 * it) / estimatedDeliveryTimeSeconds
progressUpdateEvent.status = resourceHelper.gs(R.string.bolusdelivering, requestedBolusAmount)
progressUpdateEvent.percent = percent.toInt()
rxBus.send(progressUpdateEvent)
}.ignoreElements(),
Observable.interval(5, TimeUnit.SECONDS).ignoreElements()
// TODO check delivery status. for now, we are just sleeping for 5 sec
))
}
private fun pumpSyncBolusStart(
podEvent: PodEvent,
requestedBolusAmount: Double,
bolusType: DetailedBolusInfo.BolusType
): Boolean {
val activeCommand = podStateManager.activeCommand
if (activeCommand == null || podEvent !is PodEvent.CommandSent) {
throw IllegalArgumentException(
"No active command or illegal podEvent: " +
"activeCommand=$activeCommand" +
"podEvent=$podEvent"
) )
} }
val historyEntry = history.getById(activeCommand.historyId)
val ret = pumpSync.syncBolusWithPumpId(
timestamp = historyEntry.createdAt,
amount = requestedBolusAmount,
type = bolusType,
pumpId = historyEntry.pumpId(),
pumpType = PumpType.OMNIPOD_DASH,
pumpSerial = serialNumber()
) )
}.blockingGet() aapsLogger.debug(LTag.PUMP, "pumpSyncBolusStart: $ret")
return ret
} }
override fun stopBolusDelivering() { override fun stopBolusDelivering() {
// TODO update Treatments (?) // TODO update Treatments (?)
aapsLogger.info(LTag.PUMP, "stopBolusDelivering called")
executeProgrammingCommand( executeProgrammingCommand(
historyEntry = history.createRecord(OmnipodCommandType.CANCEL_BOLUS), historyEntry = history.createRecord(OmnipodCommandType.CANCEL_BOLUS),
command = omnipodManager.stopBolus().ignoreElements() command = omnipodManager.stopBolus().ignoreElements()
@ -312,7 +358,9 @@ class OmnipodDashPumpPlugin @Inject constructor(
"setTempBasalAbsolute: $durationInMinutes min :: $absoluteRate U/h :: " + "setTempBasalAbsolute: $durationInMinutes min :: $absoluteRate U/h :: " +
"enforce: $enforceNew :: tbrType: $tbrType" "enforce: $enforceNew :: tbrType: $tbrType"
) )
return executeProgrammingCommand( return executeProgrammingCommand(
pre = observeNoActiveTempBasal(true),
historyEntry = history.createRecord( historyEntry = history.createRecord(
commandType = OmnipodCommandType.SET_TEMPORARY_BASAL, commandType = OmnipodCommandType.SET_TEMPORARY_BASAL,
tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate) tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate)
@ -335,7 +383,6 @@ class OmnipodDashPumpPlugin @Inject constructor(
.filter { podEvent -> podEvent is PodEvent.CommandSent } .filter { podEvent -> podEvent is PodEvent.CommandSent }
.map { pumpSyncTempBasal(it, absoluteRate, durationInMinutes.toLong(), tbrType) } .map { pumpSyncTempBasal(it, absoluteRate, durationInMinutes.toLong(), tbrType) }
.ignoreElements(), .ignoreElements(),
pre = observeNoActiveTempBasal(true),
).toPumpEnactResult() ).toPumpEnactResult()
} }
@ -365,7 +412,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
pumpType = PumpType.OMNIPOD_DASH, pumpType = PumpType.OMNIPOD_DASH,
pumpSerial = serialNumber() pumpSerial = serialNumber()
) )
aapsLogger.debug(LTag.PUMP, "Pump sync temp basal: $ret") aapsLogger.debug(LTag.PUMP, "pumpSyncTempBasal: $ret")
return ret return ret
} }
@ -722,6 +769,19 @@ class OmnipodDashPumpPlugin @Inject constructor(
} }
} }
OmnipodCommandType.SET_BOLUS -> {
if (!confirmation.success) {
pumpSync.syncBolusWithPumpId(
timestamp = historyEntry.createdAt,
amount = 0.0,
pumpId = historyEntry.pumpId(),
pumpType = PumpType.OMNIPOD_DASH,
pumpSerial = serialNumber(),
type = null // TODO: set the correct bolus type here!!!
)
}
}
else -> else ->
aapsLogger.warn( aapsLogger.warn(
LTag.PUMP, LTag.PUMP,