diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 4ad56cd95d..2a27de2396 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventProfileSwitchChanged +import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -17,7 +18,6 @@ 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.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.BasalProgram 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.PodConstants @@ -39,12 +39,13 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single -import io.reactivex.rxkotlin.blockingSubscribeBy +import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.subscribeBy import org.json.JSONObject import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.random.Random @Singleton class OmnipodDashPumpPlugin @Inject constructor( @@ -55,6 +56,8 @@ class OmnipodDashPumpPlugin @Inject constructor( private val history: DashHistory, private val pumpSync: PumpSync, private val rxBus: RxBusWrapper, +// private val disposable: CompositeDisposable = CompositeDisposable(), + // private val aapsSchedulers: AapsSchedulers, injector: HasAndroidInjector, aapsLogger: AAPSLogger, @@ -121,38 +124,62 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun getPumpStatus(reason: String) { - val throwable = Completable.concat(listOf( - omnipodManager - .getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE) - .ignoreElements(), - history.updateFromState(podStateManager), - podStateManager.updateActiveCommand() - .map { handleCommandConfirmation(it) } - .ignoreElement(), - )).blockingGet() - if (throwable != null){ + val throwable = Completable.concat( + listOf( + omnipodManager + .getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE) + .ignoreElements(), + history.updateFromState(podStateManager), + podStateManager.updateActiveCommand() + .map { handleCommandConfirmation(it) } + .ignoreElement(), + checkPodKaput() + ) + ).blockingGet() + if (throwable != null) { aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable) } else { aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success") - } } + private fun checkPodKaput(): Completable = Completable.defer { + val tbr = pumpSync.expectedPumpState().temporaryBasal + if (podStateManager.isPodKaput && + (tbr == null || tbr.rate != 0.0) + ) { + pumpSync.syncTemporaryBasalWithPumpId( + timestamp = System.currentTimeMillis(), + rate = 0.0, + duration = T.mins(PodConstants.MAX_POD_LIFETIME.standardMinutes).msecs(), + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = Random.Default.nextLong(), // we don't use this, just make sure it's unique + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = serialNumber() + ) + } + Completable.complete() + } + override fun setNewBasalProfile(profile: Profile): PumpEnactResult { val basalProgram = mapProfileToBasalProgram(profile) - return executeSimpleProgrammingCommand( + return executeProgrammingCommand( pre = suspendDeliveryIfActive(), historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE), + activeCommandEntry = { historyId -> + podStateManager.createActiveCommand(historyId, basalProgram = basalProgram) + }, command = omnipodManager.setBasalProgram(basalProgram).ignoreElements(), - basalProgram = basalProgram, post = failWhenUnconfirmed(), ).toPumpEnactResult() } - private fun failWhenUnconfirmed(): Completable = Completable.defer{ + private fun failWhenUnconfirmed(): Completable = Completable.defer { + rxBus.send(EventTempBasalChange()) if (podStateManager.activeCommand != null) { Completable.error(java.lang.IllegalStateException("Command not confirmed")) - }else { + } else { Completable.complete() } } @@ -161,9 +188,9 @@ class OmnipodDashPumpPlugin @Inject constructor( if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED) Completable.complete() else - executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY), - omnipodManager.suspendDelivery() + executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY), + command = omnipodManager.suspendDelivery() .filter { podEvent -> podEvent is PodEvent.CommandSent } .map { pumpSyncTempBasal( @@ -172,11 +199,19 @@ class OmnipodDashPumpPlugin @Inject constructor( PodConstants.MAX_POD_LIFETIME.standardMinutes, PumpSync.TemporaryBasalType.PUMP_SUSPEND ) + rxBus.send(EventTempBasalChange()) } - .ignoreElements(), + .ignoreElements() ) } + /* override fun onStop() { + super.onStop() + disposable.clear() + } + + */ + private fun observeDeliverySuspended(): Completable = Completable.defer { if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED) Completable.complete() @@ -202,7 +237,15 @@ class OmnipodDashPumpPlugin @Inject constructor( } override val baseBasalRate: Double - get() = podStateManager.basalProgram?.rateAt(Date()) ?: 0.0 + get() { + val date = Date() + val ret = podStateManager.basalProgram?.rateAt(date) ?: 0.0 + aapsLogger.info(LTag.PUMP, "baseBasalRate: %ret at $date}") + return if (podStateManager.alarmType != null) { + 0.0 + } else + ret + } override val reservoirLevel: Double get() { @@ -274,10 +317,12 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun stopBolusDelivering() { // TODO update Treatments (?) - executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.CANCEL_BOLUS), - omnipodManager.stopBolus().ignoreElements() + aapsLogger.info(LTag.PUMP, "stopBolusDelivering called") + val ret = executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.CANCEL_BOLUS), + command = omnipodManager.stopBolus().ignoreElements() ).toPumpEnactResult() + aapsLogger.info(LTag.PUMP, "stopBolusDelivering finished with result: $ret") } override fun setTempBasalAbsolute( @@ -288,12 +333,26 @@ class OmnipodDashPumpPlugin @Inject constructor( tbrType: PumpSync.TemporaryBasalType ): PumpEnactResult { val tempBasalBeeps = sp.getBoolean(R.string.key_omnipod_common_tbr_beeps_enabled, false) - - return executeSimpleProgrammingCommand( + aapsLogger.info( + LTag.PUMP, + "setTempBasalAbsolute: $durationInMinutes min :: $absoluteRate U/h :: " + + "enforce: $enforceNew :: tbrType: $tbrType" + ) + return executeProgrammingCommand( historyEntry = history.createRecord( commandType = OmnipodCommandType.SET_TEMPORARY_BASAL, tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate) ), + activeCommandEntry = { historyId -> + podStateManager.createActiveCommand( + historyId, + tempBasal = OmnipodDashPodStateManager.TempBasal( + startTime = System.currentTimeMillis(), + rate = absoluteRate, + durationInMinutes = durationInMinutes.toShort(), + ) + ) + }, command = omnipodManager.setTempBasal( absoluteRate, durationInMinutes.toShort(), @@ -302,7 +361,7 @@ class OmnipodDashPumpPlugin @Inject constructor( .filter { podEvent -> podEvent is PodEvent.CommandSent } .map { pumpSyncTempBasal(it, absoluteRate, durationInMinutes.toLong(), tbrType) } .ignoreElements(), - pre = observeNoActiveTempBasal() + pre = observeNoActiveTempBasal(true), ).toPumpEnactResult() } @@ -338,17 +397,29 @@ class OmnipodDashPumpPlugin @Inject constructor( private fun observeNoActiveTempBasal(): Completable { return Completable.defer { - val expectedState = pumpSync.expectedPumpState() - if (expectedState.temporaryBasal == null) { - aapsLogger.info(LTag.PUMP, "No temporary basal to cancel") - Completable.complete() - } else { - // enforceNew == true - aapsLogger.info(LTag.PUMP, "Canceling existing temp basal") - executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL), - omnipodManager.stopTempBasal().ignoreElements() - ) + when { + podStateManager.deliveryStatus !in + arrayOf(DeliveryStatus.TEMP_BASAL_ACTIVE, DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE) -> { + // TODO: what happens if we try to cancel inexistent temp basal? + aapsLogger.info(LTag.PUMP, "No temporary basal to cancel") + Completable.complete() + } + + !enforceNew -> + Completable.error( + IllegalStateException( + "Temporary basal already active and enforeNew is not set." + ) + ) + + else -> { + // enforceNew == true + aapsLogger.info(LTag.PUMP, "Canceling existing temp basal") + executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL), + command = omnipodManager.stopTempBasal().ignoreElements() + ) + } } } } @@ -386,7 +457,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { - return executeSimpleProgrammingCommand( + return executeProgrammingCommand( historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL), command = omnipodManager.stopTempBasal().ignoreElements(), pre = observeActiveTempBasal(), @@ -395,6 +466,9 @@ class OmnipodDashPumpPlugin @Inject constructor( fun Completable.toPumpEnactResult(): PumpEnactResult { return this.toSingleDefault(PumpEnactResult(injector).success(true).enacted(true)) + .doOnError { throwable -> + aapsLogger.error(LTag.PUMP, "toPumpEnactResult, error executing command: $throwable") + } .onErrorReturnItem(PumpEnactResult(injector).success(false).enacted(false)) .blockingGet() } @@ -483,38 +557,15 @@ class OmnipodDashPumpPlugin @Inject constructor( private fun silenceAlerts(): PumpEnactResult { // TODO filter alert types return podStateManager.activeAlerts?.let { - Single.create { source -> - Observable.concat( - // TODO: is this a programming command? if yes, save to history - omnipodManager.silenceAlerts(it), - history.updateFromState(podStateManager).toObservable(), - podStateManager.updateActiveCommand().toObservable(), - ).subscribeBy( - onNext = { podEvent -> - aapsLogger.debug( - LTag.PUMP, - "Received PodEvent in silenceAlerts: $podEvent" - ) - }, - onError = { throwable -> - aapsLogger.error(LTag.PUMP, "Error in silenceAlerts", throwable) - source.onSuccess( - PumpEnactResult(injector).success(false).comment( - throwable.toString() - ) - ) - }, - onComplete = { - aapsLogger.debug("silenceAlerts completed") - source.onSuccess(PumpEnactResult(injector).success(true)) - } - ) - }.blockingGet() + executeProgrammingCommand( + historyEntry = history.createRecord(commandType = OmnipodCommandType.ACKNOWLEDGE_ALERTS), + command = omnipodManager.silenceAlerts(it).ignoreElements(), + ).toPumpEnactResult() } ?: PumpEnactResult(injector).success(false).enacted(false).comment("No active alerts") // TODO i18n } private fun suspendDelivery(): PumpEnactResult { - return executeSimpleProgrammingCommand( + return executeProgrammingCommand( historyEntry = history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY), command = omnipodManager.suspendDelivery() .filter { podEvent -> podEvent is PodEvent.CommandSent } @@ -540,18 +591,18 @@ class OmnipodDashPumpPlugin @Inject constructor( private fun resumeDelivery(): PumpEnactResult { return profileFunction.getProfile()?.let { - executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.RESUME_DELIVERY), - omnipodManager.setBasalProgram(mapProfileToBasalProgram(it)).ignoreElements(), + executeProgrammingCommand( pre = observeDeliverySuspended(), + historyEntry = history.createRecord(OmnipodCommandType.RESUME_DELIVERY), + command = omnipodManager.setBasalProgram(mapProfileToBasalProgram(it)).ignoreElements() ).toPumpEnactResult() } ?: PumpEnactResult(injector).success(false).enacted(false).comment("No profile active") // TODO i18n } private fun deactivatePod(): PumpEnactResult { - return executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.DEACTIVATE_POD), - omnipodManager.deactivatePod().ignoreElements() + return executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.DEACTIVATE_POD), + command = omnipodManager.deactivatePod().ignoreElements() ).toPumpEnactResult() } @@ -566,9 +617,9 @@ class OmnipodDashPumpPlugin @Inject constructor( } private fun playTestBeep(): PumpEnactResult { - return executeSimpleProgrammingCommand( - history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP), - omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP).ignoreElements() + return executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP), + command = omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP).ignoreElements() ).toPumpEnactResult() } @@ -593,11 +644,12 @@ class OmnipodDashPumpPlugin @Inject constructor( commandQueue.customCommand(CommandHandleTimeChange(false), null) } - private fun executeSimpleProgrammingCommand( - historyEntry: Single, - command: Completable, + private fun executeProgrammingCommand( pre: Completable = Completable.complete(), - basalProgram: BasalProgram? = null, + historyEntry: Single, + activeCommandEntry: (historyId: String) -> Single = + { historyId -> podStateManager.createActiveCommand(historyId) }, + command: Completable, post: Completable = Completable.complete(), ): Completable { return Completable.concat( @@ -605,7 +657,7 @@ class OmnipodDashPumpPlugin @Inject constructor( pre, podStateManager.observeNoActiveCommand().ignoreElements(), historyEntry - .flatMap { podStateManager.createActiveCommand(it, basalProgram) } + .flatMap { activeCommandEntry(it) } .ignoreElement(), command.doOnError { podStateManager.activeCommand?.sendError = it @@ -636,6 +688,7 @@ class OmnipodDashPumpPlugin @Inject constructor( PumpType.OMNIPOD_DASH, serialNumber() ) + podStateManager.tempBasal = null } OmnipodCommandType.SET_BASAL_PROFILE -> { @@ -662,12 +715,16 @@ class OmnipodDashPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMPCOMM, "temporary basal denied. PumpId: ${historyEntry.pumpId()}") if (!confirmation.success) { pumpSync.invalidateTemporaryBasal(historyEntry.pumpId()) + } else { + podStateManager.tempBasal = command.tempBasal } } OmnipodCommandType.SUSPEND_DELIVERY -> { if (!confirmation.success) { pumpSync.invalidateTemporaryBasal(historyEntry.pumpId()) + } else { + podStateManager.tempBasal = null } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt index 128768965e..3819ee8d05 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt @@ -6,15 +6,10 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Ids import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotParseResponseException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.IllegalResponseException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.NakResponseException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.PodAlarmException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.NakResponse import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response import kotlin.reflect.KClass @@ -88,7 +83,7 @@ class Session( val response = parseResponse(decrypted) - if (!responseType.isInstance(response)) { + /*if (!responseType.isInstance(response)) { if (response is AlarmStatusResponse) { throw PodAlarmException(response) } @@ -98,6 +93,8 @@ class Session( throw IllegalResponseException(responseType, response) } + */ + sessionKeys.msgSequenceNumber++ val ack = getAck(responseMsgPacket) aapsLogger.debug(LTag.PUMPBTCOMM, "Sending ACK: ${ack.payload.toHex()} in packet $ack") diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt index 73b70126d6..553051444b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt @@ -23,7 +23,7 @@ class BasalProgram( 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 slot = segments.find { it.startSlotIndex <= slotIndex && slotIndex < it.endSlotIndex } return (slot?.basalRateInHundredthUnitsPerHour ?: 0).toDouble() / 100 } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 2b9dc3dc7e..46e9652aaf 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -28,6 +28,7 @@ interface OmnipodDashPodStateManager { val isActivationCompleted: Boolean val isSuspended: Boolean val isPodRunning: Boolean + val isPodKaput: Boolean var bluetoothConnectionState: BluetoothConnectionState val lastUpdatedSystem: Long // System.currentTimeMillis() @@ -57,8 +58,9 @@ interface OmnipodDashPodStateManager { val deliveryStatus: DeliveryStatus? val minutesSinceActivation: Short? val activeAlerts: EnumSet? + val alarmType: AlarmType? - val tempBasal: TempBasal? + var tempBasal: TempBasal? val tempBasalActive: Boolean var basalProgram: BasalProgram? val activeCommand: ActiveCommand? @@ -73,7 +75,8 @@ interface OmnipodDashPodStateManager { fun updateFromPairing(uniqueId: Id, pairResult: PairResult) fun reset() - fun createActiveCommand(historyId: String, basalProgram: BasalProgram? = null): Single + fun createActiveCommand(historyId: String, basalProgram: BasalProgram? = null, tempBasal: TempBasal? = null): + Single fun updateActiveCommand(): Maybe fun observeNoActiveCommand(): Observable fun getCommandConfirmationFromState(): CommandConfirmationFromState @@ -84,7 +87,8 @@ interface OmnipodDashPodStateManager { var sentRealtime: Long = 0, val historyId: String, var sendError: Throwable?, - var basalProgram: BasalProgram? + var basalProgram: BasalProgram?, + val tempBasal: TempBasal? ) // TODO: set created to "now" on boot data class TempBasal(val startTime: Long, val rate: Double, val durationInMinutes: Short) : Serializable diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 104f4f1cfc..7d2df0242b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -55,6 +55,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( get() = podState.deliveryStatus?.equals(DeliveryStatus.SUSPENDED) ?: false + override val isPodKaput: Boolean + get() = podState.podStatus in arrayOf(PodStatus.ALARM, PodStatus.DEACTIVATED) + override val isPodRunning: Boolean get() = podState.podStatus?.isRunning() ?: false @@ -137,20 +140,27 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( override val activeAlerts: EnumSet? get() = podState.activeAlerts - override val tempBasal: OmnipodDashPodStateManager.TempBasal? + override val alarmType: AlarmType? + get() = podState.alarmType + + override var tempBasal: OmnipodDashPodStateManager.TempBasal? get() = podState.tempBasal + set(tempBasal) { + podState.tempBasal = tempBasal + rxBus.send(EventOmnipodDashPumpValuesChanged()) + store() + } override val tempBasalActive: Boolean - get() = podState.deliveryStatus in - arrayOf( - DeliveryStatus.TEMP_BASAL_ACTIVE, - DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE - ) + get() = !isSuspended && tempBasal?.let { + it.startTime + it.durationInMinutes * 60 * 1000 > System.currentTimeMillis() + } ?: false override var basalProgram: BasalProgram? get() = podState.basalProgram set(basalProgram) { podState.basalProgram = basalProgram + rxBus.send(EventOmnipodDashPumpValuesChanged()) store() } @@ -188,7 +198,11 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( get() = podState.activeCommand @Synchronized - override fun createActiveCommand(historyId: String, basalProgram: BasalProgram?): + override fun createActiveCommand( + historyId: String, + basalProgram: BasalProgram?, + tempBasal: OmnipodDashPodStateManager.TempBasal? + ): Single { return Single.create { source -> if (activeCommand == null) { @@ -198,6 +212,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( historyId = historyId, sendError = null, basalProgram = basalProgram, + tempBasal = tempBasal, ) podState.activeCommand = command source.onSuccess(command) @@ -308,6 +323,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) { + logger.debug(LTag.PUMPBTCOMM, "Default status reponse :$response") podState.deliveryStatus = response.deliveryStatus podState.podStatus = response.podStatus podState.pulsesDelivered = response.totalPulsesDelivered @@ -374,11 +390,23 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override fun updateFromAlarmStatusResponse(response: AlarmStatusResponse) { - // TODO - logger.error( + logger.info( LTag.PUMP, - "Not implemented: OmnipodDashPodStateManagerImpl.updateFromAlarmStatusResponse(AlarmStatusResponse)" + "Received AlarmStatusReponse: $response" ) + podState.deliveryStatus = response.deliveryStatus + podState.podStatus = response.podStatus + podState.pulsesDelivered = response.totalPulsesDelivered + if (response.reservoirPulsesRemaining < 1023) { + podState.pulsesRemaining = response.reservoirPulsesRemaining + } + podState.sequenceNumberOfLastProgrammingCommand = response.sequenceNumberOfLastProgrammingCommand + podState.minutesSinceActivation = response.minutesSinceActivation + podState.activeAlerts = response.activeAlerts + podState.alarmType = response.alarmType + + podState.lastUpdatedSystem = System.currentTimeMillis() + podState.lastStatusResponseReceived = SystemClock.elapsedRealtime() store() rxBus.send(EventOmnipodDashPumpValuesChanged()) @@ -451,6 +479,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var deliveryStatus: DeliveryStatus? = null var minutesSinceActivation: Short? = null var activeAlerts: EnumSet? = null + var alarmType: AlarmType? = null var basalProgram: BasalProgram? = null var tempBasal: OmnipodDashPodStateManager.TempBasal? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt index 9d5db05579..5a12dabb23 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/util/AlertUtil.kt @@ -8,9 +8,10 @@ object AlertUtil { fun decodeAlertSet(encoded: Byte): EnumSet { val encodedInt = encoded.toInt() and 0xff - val alertList = AlertType.values().filter { - (it.value.toInt() and 0xff) and encodedInt != 0 - }.toList() + val alertList = AlertType.values() + .filter { it != AlertType.UNKNOWN } // 0xff && will always be true + .filter { (it.value.toInt() and 0xff) and encodedInt != 0 } + .toList() return if (alertList.isEmpty()) { EnumSet.noneOf(AlertType::class.java) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 16963b3da8..3d0099c1af 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -212,7 +212,6 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } private fun updateUi() { - // TODO update bluetooth status updateBluetoothStatus() updateOmnipodStatus() updatePodActionButtons() @@ -296,6 +295,15 @@ class OmnipodDashOverviewFragment : DaggerFragment() { errors.add(resourceHelper.gs(R.string.omnipod_common_pod_status_pod_fault_description, faultEventCode.value, faultEventCode.name)) } */ + podStateManager.alarmType?.let { + errors.add( + resourceHelper.gs( + R.string.omnipod_common_pod_status_pod_fault_description, + it.value, + it.toString() + ) + ) + } // base basal rate podInfoBinding.baseBasalRate.text = if (podStateManager.basalProgram != null && !podStateManager.isSuspended) { @@ -343,7 +351,9 @@ class OmnipodDashOverviewFragment : DaggerFragment() { ) } - podInfoBinding.podActiveAlerts.text = PLACEHOLDER + podInfoBinding.podActiveAlerts.text = podStateManager.activeAlerts?.let { + it.map { it.toString() }.joinToString(",") + } ?: PLACEHOLDER } if (errors.size == 0) { @@ -503,7 +513,8 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } private fun updateSilenceAlertsButton() { - if (isAutomaticallySilenceAlertsEnabled() && podStateManager.isPodRunning && + if (!isAutomaticallySilenceAlertsEnabled() && + podStateManager.isPodRunning && ( podStateManager.activeAlerts!!.size > 0 || commandQueue.isCustomCommandInQueue(CommandSilenceAlerts::class.java)