commit
8b87919b05
7 changed files with 207 additions and 108 deletions
|
@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
|
import info.nightscout.androidaps.events.EventTempBasalChange
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
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.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
|
||||||
|
@ -39,12 +39,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.blockingSubscribeBy
|
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class OmnipodDashPumpPlugin @Inject constructor(
|
class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
@ -55,6 +56,8 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
private val history: DashHistory,
|
private val history: DashHistory,
|
||||||
private val pumpSync: PumpSync,
|
private val pumpSync: PumpSync,
|
||||||
private val rxBus: RxBusWrapper,
|
private val rxBus: RxBusWrapper,
|
||||||
|
// private val disposable: CompositeDisposable = CompositeDisposable(),
|
||||||
|
// private val aapsSchedulers: AapsSchedulers,
|
||||||
|
|
||||||
injector: HasAndroidInjector,
|
injector: HasAndroidInjector,
|
||||||
aapsLogger: AAPSLogger,
|
aapsLogger: AAPSLogger,
|
||||||
|
@ -121,7 +124,8 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPumpStatus(reason: String) {
|
override fun getPumpStatus(reason: String) {
|
||||||
val throwable = Completable.concat(listOf(
|
val throwable = Completable.concat(
|
||||||
|
listOf(
|
||||||
omnipodManager
|
omnipodManager
|
||||||
.getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE)
|
.getStatus(ResponseType.StatusResponseType.DEFAULT_STATUS_RESPONSE)
|
||||||
.ignoreElements(),
|
.ignoreElements(),
|
||||||
|
@ -129,27 +133,50 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
podStateManager.updateActiveCommand()
|
podStateManager.updateActiveCommand()
|
||||||
.map { handleCommandConfirmation(it) }
|
.map { handleCommandConfirmation(it) }
|
||||||
.ignoreElement(),
|
.ignoreElement(),
|
||||||
)).blockingGet()
|
checkPodKaput()
|
||||||
|
)
|
||||||
|
).blockingGet()
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable)
|
aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable)
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success")
|
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 {
|
override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
|
||||||
val basalProgram = mapProfileToBasalProgram(profile)
|
val basalProgram = mapProfileToBasalProgram(profile)
|
||||||
return executeSimpleProgrammingCommand(
|
return executeProgrammingCommand(
|
||||||
pre = suspendDeliveryIfActive(),
|
pre = suspendDeliveryIfActive(),
|
||||||
historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE),
|
historyEntry = history.createRecord(commandType = OmnipodCommandType.SET_BASAL_PROFILE),
|
||||||
|
activeCommandEntry = { historyId ->
|
||||||
|
podStateManager.createActiveCommand(historyId, basalProgram = basalProgram)
|
||||||
|
},
|
||||||
command = omnipodManager.setBasalProgram(basalProgram).ignoreElements(),
|
command = omnipodManager.setBasalProgram(basalProgram).ignoreElements(),
|
||||||
basalProgram = basalProgram,
|
|
||||||
post = failWhenUnconfirmed(),
|
post = failWhenUnconfirmed(),
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun failWhenUnconfirmed(): Completable = Completable.defer {
|
private fun failWhenUnconfirmed(): Completable = Completable.defer {
|
||||||
|
rxBus.send(EventTempBasalChange())
|
||||||
if (podStateManager.activeCommand != null) {
|
if (podStateManager.activeCommand != null) {
|
||||||
Completable.error(java.lang.IllegalStateException("Command not confirmed"))
|
Completable.error(java.lang.IllegalStateException("Command not confirmed"))
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,9 +188,9 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED)
|
if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED)
|
||||||
Completable.complete()
|
Completable.complete()
|
||||||
else
|
else
|
||||||
executeSimpleProgrammingCommand(
|
executeProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY),
|
historyEntry = history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY),
|
||||||
omnipodManager.suspendDelivery()
|
command = omnipodManager.suspendDelivery()
|
||||||
.filter { podEvent -> podEvent is PodEvent.CommandSent }
|
.filter { podEvent -> podEvent is PodEvent.CommandSent }
|
||||||
.map {
|
.map {
|
||||||
pumpSyncTempBasal(
|
pumpSyncTempBasal(
|
||||||
|
@ -172,11 +199,19 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
PodConstants.MAX_POD_LIFETIME.standardMinutes,
|
PodConstants.MAX_POD_LIFETIME.standardMinutes,
|
||||||
PumpSync.TemporaryBasalType.PUMP_SUSPEND
|
PumpSync.TemporaryBasalType.PUMP_SUSPEND
|
||||||
)
|
)
|
||||||
|
rxBus.send(EventTempBasalChange())
|
||||||
}
|
}
|
||||||
.ignoreElements(),
|
.ignoreElements()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
private fun observeDeliverySuspended(): Completable = Completable.defer {
|
private fun observeDeliverySuspended(): Completable = Completable.defer {
|
||||||
if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED)
|
if (podStateManager.deliveryStatus == DeliveryStatus.SUSPENDED)
|
||||||
Completable.complete()
|
Completable.complete()
|
||||||
|
@ -202,7 +237,15 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override val baseBasalRate: Double
|
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
|
override val reservoirLevel: Double
|
||||||
get() {
|
get() {
|
||||||
|
@ -274,10 +317,12 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun stopBolusDelivering() {
|
override fun stopBolusDelivering() {
|
||||||
// TODO update Treatments (?)
|
// TODO update Treatments (?)
|
||||||
executeSimpleProgrammingCommand(
|
aapsLogger.info(LTag.PUMP, "stopBolusDelivering called")
|
||||||
history.createRecord(OmnipodCommandType.CANCEL_BOLUS),
|
val ret = executeProgrammingCommand(
|
||||||
omnipodManager.stopBolus().ignoreElements()
|
historyEntry = history.createRecord(OmnipodCommandType.CANCEL_BOLUS),
|
||||||
|
command = omnipodManager.stopBolus().ignoreElements()
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
|
aapsLogger.info(LTag.PUMP, "stopBolusDelivering finished with result: $ret")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTempBasalAbsolute(
|
override fun setTempBasalAbsolute(
|
||||||
|
@ -288,12 +333,26 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
tbrType: PumpSync.TemporaryBasalType
|
tbrType: PumpSync.TemporaryBasalType
|
||||||
): PumpEnactResult {
|
): PumpEnactResult {
|
||||||
val tempBasalBeeps = sp.getBoolean(R.string.key_omnipod_common_tbr_beeps_enabled, false)
|
val tempBasalBeeps = sp.getBoolean(R.string.key_omnipod_common_tbr_beeps_enabled, false)
|
||||||
|
aapsLogger.info(
|
||||||
return executeSimpleProgrammingCommand(
|
LTag.PUMP,
|
||||||
|
"setTempBasalAbsolute: $durationInMinutes min :: $absoluteRate U/h :: " +
|
||||||
|
"enforce: $enforceNew :: tbrType: $tbrType"
|
||||||
|
)
|
||||||
|
return executeProgrammingCommand(
|
||||||
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)
|
||||||
),
|
),
|
||||||
|
activeCommandEntry = { historyId ->
|
||||||
|
podStateManager.createActiveCommand(
|
||||||
|
historyId,
|
||||||
|
tempBasal = OmnipodDashPodStateManager.TempBasal(
|
||||||
|
startTime = System.currentTimeMillis(),
|
||||||
|
rate = absoluteRate,
|
||||||
|
durationInMinutes = durationInMinutes.toShort(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
command = omnipodManager.setTempBasal(
|
command = omnipodManager.setTempBasal(
|
||||||
absoluteRate,
|
absoluteRate,
|
||||||
durationInMinutes.toShort(),
|
durationInMinutes.toShort(),
|
||||||
|
@ -302,7 +361,7 @@ 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()
|
pre = observeNoActiveTempBasal(true),
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,20 +397,32 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
private fun observeNoActiveTempBasal(): Completable {
|
private fun observeNoActiveTempBasal(): Completable {
|
||||||
return Completable.defer {
|
return Completable.defer {
|
||||||
val expectedState = pumpSync.expectedPumpState()
|
when {
|
||||||
if (expectedState.temporaryBasal == null) {
|
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")
|
aapsLogger.info(LTag.PUMP, "No temporary basal to cancel")
|
||||||
Completable.complete()
|
Completable.complete()
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
!enforceNew ->
|
||||||
|
Completable.error(
|
||||||
|
IllegalStateException(
|
||||||
|
"Temporary basal already active and enforeNew is not set."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> {
|
||||||
// enforceNew == true
|
// enforceNew == true
|
||||||
aapsLogger.info(LTag.PUMP, "Canceling existing temp basal")
|
aapsLogger.info(LTag.PUMP, "Canceling existing temp basal")
|
||||||
executeSimpleProgrammingCommand(
|
executeProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
||||||
omnipodManager.stopTempBasal().ignoreElements()
|
command = omnipodManager.stopTempBasal().ignoreElements()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun observeActiveTempBasal(): Completable {
|
private fun observeActiveTempBasal(): Completable {
|
||||||
|
|
||||||
|
@ -386,7 +457,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
|
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
|
||||||
return executeSimpleProgrammingCommand(
|
return executeProgrammingCommand(
|
||||||
historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
||||||
command = omnipodManager.stopTempBasal().ignoreElements(),
|
command = omnipodManager.stopTempBasal().ignoreElements(),
|
||||||
pre = observeActiveTempBasal(),
|
pre = observeActiveTempBasal(),
|
||||||
|
@ -395,6 +466,9 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
fun Completable.toPumpEnactResult(): PumpEnactResult {
|
fun Completable.toPumpEnactResult(): PumpEnactResult {
|
||||||
return this.toSingleDefault(PumpEnactResult(injector).success(true).enacted(true))
|
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))
|
.onErrorReturnItem(PumpEnactResult(injector).success(false).enacted(false))
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
}
|
}
|
||||||
|
@ -483,38 +557,15 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
private fun silenceAlerts(): PumpEnactResult {
|
private fun silenceAlerts(): PumpEnactResult {
|
||||||
// TODO filter alert types
|
// TODO filter alert types
|
||||||
return podStateManager.activeAlerts?.let {
|
return podStateManager.activeAlerts?.let {
|
||||||
Single.create<PumpEnactResult> { source ->
|
executeProgrammingCommand(
|
||||||
Observable.concat(
|
historyEntry = history.createRecord(commandType = OmnipodCommandType.ACKNOWLEDGE_ALERTS),
|
||||||
// TODO: is this a programming command? if yes, save to history
|
command = omnipodManager.silenceAlerts(it).ignoreElements(),
|
||||||
omnipodManager.silenceAlerts(it),
|
).toPumpEnactResult()
|
||||||
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()
|
|
||||||
} ?: PumpEnactResult(injector).success(false).enacted(false).comment("No active alerts") // TODO i18n
|
} ?: PumpEnactResult(injector).success(false).enacted(false).comment("No active alerts") // TODO i18n
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun suspendDelivery(): PumpEnactResult {
|
private fun suspendDelivery(): PumpEnactResult {
|
||||||
return executeSimpleProgrammingCommand(
|
return executeProgrammingCommand(
|
||||||
historyEntry = history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY),
|
historyEntry = history.createRecord(OmnipodCommandType.SUSPEND_DELIVERY),
|
||||||
command = omnipodManager.suspendDelivery()
|
command = omnipodManager.suspendDelivery()
|
||||||
.filter { podEvent -> podEvent is PodEvent.CommandSent }
|
.filter { podEvent -> podEvent is PodEvent.CommandSent }
|
||||||
|
@ -540,18 +591,18 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
private fun resumeDelivery(): PumpEnactResult {
|
private fun resumeDelivery(): PumpEnactResult {
|
||||||
return profileFunction.getProfile()?.let {
|
return profileFunction.getProfile()?.let {
|
||||||
executeSimpleProgrammingCommand(
|
executeProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
|
||||||
omnipodManager.setBasalProgram(mapProfileToBasalProgram(it)).ignoreElements(),
|
|
||||||
pre = observeDeliverySuspended(),
|
pre = observeDeliverySuspended(),
|
||||||
|
historyEntry = history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
||||||
|
command = omnipodManager.setBasalProgram(mapProfileToBasalProgram(it)).ignoreElements()
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
} ?: PumpEnactResult(injector).success(false).enacted(false).comment("No profile active") // TODO i18n
|
} ?: PumpEnactResult(injector).success(false).enacted(false).comment("No profile active") // TODO i18n
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deactivatePod(): PumpEnactResult {
|
private fun deactivatePod(): PumpEnactResult {
|
||||||
return executeSimpleProgrammingCommand(
|
return executeProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
|
historyEntry = history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
|
||||||
omnipodManager.deactivatePod().ignoreElements()
|
command = omnipodManager.deactivatePod().ignoreElements()
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,9 +617,9 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun playTestBeep(): PumpEnactResult {
|
private fun playTestBeep(): PumpEnactResult {
|
||||||
return executeSimpleProgrammingCommand(
|
return executeProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP),
|
historyEntry = history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP),
|
||||||
omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP).ignoreElements()
|
command = omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP).ignoreElements()
|
||||||
).toPumpEnactResult()
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,11 +644,12 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
commandQueue.customCommand(CommandHandleTimeChange(false), null)
|
commandQueue.customCommand(CommandHandleTimeChange(false), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun executeSimpleProgrammingCommand(
|
private fun executeProgrammingCommand(
|
||||||
historyEntry: Single<String>,
|
|
||||||
command: Completable,
|
|
||||||
pre: Completable = Completable.complete(),
|
pre: Completable = Completable.complete(),
|
||||||
basalProgram: BasalProgram? = null,
|
historyEntry: Single<String>,
|
||||||
|
activeCommandEntry: (historyId: String) -> Single<OmnipodDashPodStateManager.ActiveCommand> =
|
||||||
|
{ historyId -> podStateManager.createActiveCommand(historyId) },
|
||||||
|
command: Completable,
|
||||||
post: Completable = Completable.complete(),
|
post: Completable = Completable.complete(),
|
||||||
): Completable {
|
): Completable {
|
||||||
return Completable.concat(
|
return Completable.concat(
|
||||||
|
@ -605,7 +657,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
pre,
|
pre,
|
||||||
podStateManager.observeNoActiveCommand().ignoreElements(),
|
podStateManager.observeNoActiveCommand().ignoreElements(),
|
||||||
historyEntry
|
historyEntry
|
||||||
.flatMap { podStateManager.createActiveCommand(it, basalProgram) }
|
.flatMap { activeCommandEntry(it) }
|
||||||
.ignoreElement(),
|
.ignoreElement(),
|
||||||
command.doOnError {
|
command.doOnError {
|
||||||
podStateManager.activeCommand?.sendError = it
|
podStateManager.activeCommand?.sendError = it
|
||||||
|
@ -636,6 +688,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
PumpType.OMNIPOD_DASH,
|
PumpType.OMNIPOD_DASH,
|
||||||
serialNumber()
|
serialNumber()
|
||||||
)
|
)
|
||||||
|
podStateManager.tempBasal = null
|
||||||
}
|
}
|
||||||
|
|
||||||
OmnipodCommandType.SET_BASAL_PROFILE -> {
|
OmnipodCommandType.SET_BASAL_PROFILE -> {
|
||||||
|
@ -662,12 +715,16 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
aapsLogger.info(LTag.PUMPCOMM, "temporary basal denied. PumpId: ${historyEntry.pumpId()}")
|
aapsLogger.info(LTag.PUMPCOMM, "temporary basal denied. PumpId: ${historyEntry.pumpId()}")
|
||||||
if (!confirmation.success) {
|
if (!confirmation.success) {
|
||||||
pumpSync.invalidateTemporaryBasal(historyEntry.pumpId())
|
pumpSync.invalidateTemporaryBasal(historyEntry.pumpId())
|
||||||
|
} else {
|
||||||
|
podStateManager.tempBasal = command.tempBasal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OmnipodCommandType.SUSPEND_DELIVERY -> {
|
OmnipodCommandType.SUSPEND_DELIVERY -> {
|
||||||
if (!confirmation.success) {
|
if (!confirmation.success) {
|
||||||
pumpSync.invalidateTemporaryBasal(historyEntry.pumpId())
|
pumpSync.invalidateTemporaryBasal(historyEntry.pumpId())
|
||||||
|
} else {
|
||||||
|
podStateManager.tempBasal = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.Ids
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt
|
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.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.*
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageType
|
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.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.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 info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@ -88,7 +83,7 @@ class Session(
|
||||||
|
|
||||||
val response = parseResponse(decrypted)
|
val response = parseResponse(decrypted)
|
||||||
|
|
||||||
if (!responseType.isInstance(response)) {
|
/*if (!responseType.isInstance(response)) {
|
||||||
if (response is AlarmStatusResponse) {
|
if (response is AlarmStatusResponse) {
|
||||||
throw PodAlarmException(response)
|
throw PodAlarmException(response)
|
||||||
}
|
}
|
||||||
|
@ -98,6 +93,8 @@ class Session(
|
||||||
throw IllegalResponseException(responseType, response)
|
throw IllegalResponseException(responseType, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
sessionKeys.msgSequenceNumber++
|
sessionKeys.msgSequenceNumber++
|
||||||
val ack = getAck(responseMsgPacket)
|
val ack = getAck(responseMsgPacket)
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending ACK: ${ack.payload.toHex()} in packet $ack")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending ACK: ${ack.payload.toHex()} in packet $ack")
|
||||||
|
|
|
@ -28,6 +28,7 @@ interface OmnipodDashPodStateManager {
|
||||||
val isActivationCompleted: Boolean
|
val isActivationCompleted: Boolean
|
||||||
val isSuspended: Boolean
|
val isSuspended: Boolean
|
||||||
val isPodRunning: Boolean
|
val isPodRunning: Boolean
|
||||||
|
val isPodKaput: Boolean
|
||||||
var bluetoothConnectionState: BluetoothConnectionState
|
var bluetoothConnectionState: BluetoothConnectionState
|
||||||
|
|
||||||
val lastUpdatedSystem: Long // System.currentTimeMillis()
|
val lastUpdatedSystem: Long // System.currentTimeMillis()
|
||||||
|
@ -57,8 +58,9 @@ interface OmnipodDashPodStateManager {
|
||||||
val deliveryStatus: DeliveryStatus?
|
val deliveryStatus: DeliveryStatus?
|
||||||
val minutesSinceActivation: Short?
|
val minutesSinceActivation: Short?
|
||||||
val activeAlerts: EnumSet<AlertType>?
|
val activeAlerts: EnumSet<AlertType>?
|
||||||
|
val alarmType: AlarmType?
|
||||||
|
|
||||||
val tempBasal: TempBasal?
|
var tempBasal: TempBasal?
|
||||||
val tempBasalActive: Boolean
|
val tempBasalActive: Boolean
|
||||||
var basalProgram: BasalProgram?
|
var basalProgram: BasalProgram?
|
||||||
val activeCommand: ActiveCommand?
|
val activeCommand: ActiveCommand?
|
||||||
|
@ -73,7 +75,8 @@ interface OmnipodDashPodStateManager {
|
||||||
fun updateFromPairing(uniqueId: Id, pairResult: PairResult)
|
fun updateFromPairing(uniqueId: Id, pairResult: PairResult)
|
||||||
fun reset()
|
fun reset()
|
||||||
|
|
||||||
fun createActiveCommand(historyId: String, basalProgram: BasalProgram? = null): Single<ActiveCommand>
|
fun createActiveCommand(historyId: String, basalProgram: BasalProgram? = null, tempBasal: TempBasal? = null):
|
||||||
|
Single<ActiveCommand>
|
||||||
fun updateActiveCommand(): Maybe<CommandConfirmed>
|
fun updateActiveCommand(): Maybe<CommandConfirmed>
|
||||||
fun observeNoActiveCommand(): Observable<PodEvent>
|
fun observeNoActiveCommand(): Observable<PodEvent>
|
||||||
fun getCommandConfirmationFromState(): CommandConfirmationFromState
|
fun getCommandConfirmationFromState(): CommandConfirmationFromState
|
||||||
|
@ -84,7 +87,8 @@ interface OmnipodDashPodStateManager {
|
||||||
var sentRealtime: Long = 0,
|
var sentRealtime: Long = 0,
|
||||||
val historyId: String,
|
val historyId: String,
|
||||||
var sendError: Throwable?,
|
var sendError: Throwable?,
|
||||||
var basalProgram: BasalProgram?
|
var basalProgram: BasalProgram?,
|
||||||
|
val tempBasal: TempBasal?
|
||||||
)
|
)
|
||||||
// TODO: set created to "now" on boot
|
// TODO: set created to "now" on boot
|
||||||
data class TempBasal(val startTime: Long, val rate: Double, val durationInMinutes: Short) : Serializable
|
data class TempBasal(val startTime: Long, val rate: Double, val durationInMinutes: Short) : Serializable
|
||||||
|
|
|
@ -55,6 +55,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
get() = podState.deliveryStatus?.equals(DeliveryStatus.SUSPENDED)
|
get() = podState.deliveryStatus?.equals(DeliveryStatus.SUSPENDED)
|
||||||
?: false
|
?: false
|
||||||
|
|
||||||
|
override val isPodKaput: Boolean
|
||||||
|
get() = podState.podStatus in arrayOf(PodStatus.ALARM, PodStatus.DEACTIVATED)
|
||||||
|
|
||||||
override val isPodRunning: Boolean
|
override val isPodRunning: Boolean
|
||||||
get() = podState.podStatus?.isRunning() ?: false
|
get() = podState.podStatus?.isRunning() ?: false
|
||||||
|
|
||||||
|
@ -137,20 +140,27 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
override val activeAlerts: EnumSet<AlertType>?
|
override val activeAlerts: EnumSet<AlertType>?
|
||||||
get() = podState.activeAlerts
|
get() = podState.activeAlerts
|
||||||
|
|
||||||
override val tempBasal: OmnipodDashPodStateManager.TempBasal?
|
override val alarmType: AlarmType?
|
||||||
|
get() = podState.alarmType
|
||||||
|
|
||||||
|
override var tempBasal: OmnipodDashPodStateManager.TempBasal?
|
||||||
get() = podState.tempBasal
|
get() = podState.tempBasal
|
||||||
|
set(tempBasal) {
|
||||||
|
podState.tempBasal = tempBasal
|
||||||
|
rxBus.send(EventOmnipodDashPumpValuesChanged())
|
||||||
|
store()
|
||||||
|
}
|
||||||
|
|
||||||
override val tempBasalActive: Boolean
|
override val tempBasalActive: Boolean
|
||||||
get() = podState.deliveryStatus in
|
get() = !isSuspended && tempBasal?.let {
|
||||||
arrayOf(
|
it.startTime + it.durationInMinutes * 60 * 1000 > System.currentTimeMillis()
|
||||||
DeliveryStatus.TEMP_BASAL_ACTIVE,
|
} ?: false
|
||||||
DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE
|
|
||||||
)
|
|
||||||
|
|
||||||
override var basalProgram: BasalProgram?
|
override var basalProgram: BasalProgram?
|
||||||
get() = podState.basalProgram
|
get() = podState.basalProgram
|
||||||
set(basalProgram) {
|
set(basalProgram) {
|
||||||
podState.basalProgram = basalProgram
|
podState.basalProgram = basalProgram
|
||||||
|
rxBus.send(EventOmnipodDashPumpValuesChanged())
|
||||||
store()
|
store()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +198,11 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
get() = podState.activeCommand
|
get() = podState.activeCommand
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun createActiveCommand(historyId: String, basalProgram: BasalProgram?):
|
override fun createActiveCommand(
|
||||||
|
historyId: String,
|
||||||
|
basalProgram: BasalProgram?,
|
||||||
|
tempBasal: OmnipodDashPodStateManager.TempBasal?
|
||||||
|
):
|
||||||
Single<OmnipodDashPodStateManager.ActiveCommand> {
|
Single<OmnipodDashPodStateManager.ActiveCommand> {
|
||||||
return Single.create { source ->
|
return Single.create { source ->
|
||||||
if (activeCommand == null) {
|
if (activeCommand == null) {
|
||||||
|
@ -198,6 +212,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
historyId = historyId,
|
historyId = historyId,
|
||||||
sendError = null,
|
sendError = null,
|
||||||
basalProgram = basalProgram,
|
basalProgram = basalProgram,
|
||||||
|
tempBasal = tempBasal,
|
||||||
)
|
)
|
||||||
podState.activeCommand = command
|
podState.activeCommand = command
|
||||||
source.onSuccess(command)
|
source.onSuccess(command)
|
||||||
|
@ -308,6 +323,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) {
|
override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) {
|
||||||
|
logger.debug(LTag.PUMPBTCOMM, "Default status reponse :$response")
|
||||||
podState.deliveryStatus = response.deliveryStatus
|
podState.deliveryStatus = response.deliveryStatus
|
||||||
podState.podStatus = response.podStatus
|
podState.podStatus = response.podStatus
|
||||||
podState.pulsesDelivered = response.totalPulsesDelivered
|
podState.pulsesDelivered = response.totalPulsesDelivered
|
||||||
|
@ -374,11 +390,23 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFromAlarmStatusResponse(response: AlarmStatusResponse) {
|
override fun updateFromAlarmStatusResponse(response: AlarmStatusResponse) {
|
||||||
// TODO
|
logger.info(
|
||||||
logger.error(
|
|
||||||
LTag.PUMP,
|
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()
|
store()
|
||||||
rxBus.send(EventOmnipodDashPumpValuesChanged())
|
rxBus.send(EventOmnipodDashPumpValuesChanged())
|
||||||
|
@ -451,6 +479,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
var deliveryStatus: DeliveryStatus? = null
|
var deliveryStatus: DeliveryStatus? = null
|
||||||
var minutesSinceActivation: Short? = null
|
var minutesSinceActivation: Short? = null
|
||||||
var activeAlerts: EnumSet<AlertType>? = null
|
var activeAlerts: EnumSet<AlertType>? = null
|
||||||
|
var alarmType: AlarmType? = null
|
||||||
|
|
||||||
var basalProgram: BasalProgram? = null
|
var basalProgram: BasalProgram? = null
|
||||||
var tempBasal: OmnipodDashPodStateManager.TempBasal? = null
|
var tempBasal: OmnipodDashPodStateManager.TempBasal? = null
|
||||||
|
|
|
@ -8,9 +8,10 @@ object AlertUtil {
|
||||||
fun decodeAlertSet(encoded: Byte): EnumSet<AlertType> {
|
fun decodeAlertSet(encoded: Byte): EnumSet<AlertType> {
|
||||||
val encodedInt = encoded.toInt() and 0xff
|
val encodedInt = encoded.toInt() and 0xff
|
||||||
|
|
||||||
val alertList = AlertType.values().filter {
|
val alertList = AlertType.values()
|
||||||
(it.value.toInt() and 0xff) and encodedInt != 0
|
.filter { it != AlertType.UNKNOWN } // 0xff && <something> will always be true
|
||||||
}.toList()
|
.filter { (it.value.toInt() and 0xff) and encodedInt != 0 }
|
||||||
|
.toList()
|
||||||
|
|
||||||
return if (alertList.isEmpty()) {
|
return if (alertList.isEmpty()) {
|
||||||
EnumSet.noneOf(AlertType::class.java)
|
EnumSet.noneOf(AlertType::class.java)
|
||||||
|
|
|
@ -212,7 +212,6 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUi() {
|
private fun updateUi() {
|
||||||
// TODO update bluetooth status
|
|
||||||
updateBluetoothStatus()
|
updateBluetoothStatus()
|
||||||
updateOmnipodStatus()
|
updateOmnipodStatus()
|
||||||
updatePodActionButtons()
|
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))
|
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
|
// base basal rate
|
||||||
podInfoBinding.baseBasalRate.text = if (podStateManager.basalProgram != null && !podStateManager.isSuspended) {
|
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) {
|
if (errors.size == 0) {
|
||||||
|
@ -503,7 +513,8 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSilenceAlertsButton() {
|
private fun updateSilenceAlertsButton() {
|
||||||
if (isAutomaticallySilenceAlertsEnabled() && podStateManager.isPodRunning &&
|
if (!isAutomaticallySilenceAlertsEnabled() &&
|
||||||
|
podStateManager.isPodRunning &&
|
||||||
(
|
(
|
||||||
podStateManager.activeAlerts!!.size > 0 ||
|
podStateManager.activeAlerts!!.size > 0 ||
|
||||||
commandQueue.isCustomCommandInQueue(CommandSilenceAlerts::class.java)
|
commandQueue.isCustomCommandInQueue(CommandSilenceAlerts::class.java)
|
||||||
|
|
Loading…
Reference in a new issue