implement TempBasal pumpSync and confirmation
This commit is contained in:
parent
ebb3030169
commit
3314df7bb7
17 changed files with 222 additions and 112 deletions
|
@ -17,6 +17,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEven
|
||||||
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.BeepType
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.CommandConfirmed
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord
|
||||||
|
@ -28,11 +29,14 @@ import info.nightscout.androidaps.queue.commands.CustomCommand
|
||||||
import info.nightscout.androidaps.utils.TimeChangeType
|
import info.nightscout.androidaps.utils.TimeChangeType
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
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.blockingSubscribeBy
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
import java.lang.IllegalStateException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -44,6 +48,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val history: DashHistory,
|
private val history: DashHistory,
|
||||||
|
private val pumpSync: PumpSync,
|
||||||
injector: HasAndroidInjector,
|
injector: HasAndroidInjector,
|
||||||
aapsLogger: AAPSLogger,
|
aapsLogger: AAPSLogger,
|
||||||
resourceHelper: ResourceHelper,
|
resourceHelper: ResourceHelper,
|
||||||
|
@ -151,12 +156,12 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
|
override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
|
||||||
return executeProgrammingCommand(
|
return executeSimpleProgrammingCommand(
|
||||||
history.createRecord(
|
history.createRecord(
|
||||||
commandType = OmnipodCommandType.SET_BASAL_PROFILE
|
commandType = OmnipodCommandType.SET_BASAL_PROFILE
|
||||||
),
|
),
|
||||||
omnipodManager.setBasalProgram(mapProfileToBasalProgram(profile))
|
omnipodManager.setBasalProgram(mapProfileToBasalProgram(profile))
|
||||||
)
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isThisProfileSet(profile: Profile): Boolean = podStateManager.basalProgram?.let {
|
override fun isThisProfileSet(profile: Profile): Boolean = podStateManager.basalProgram?.let {
|
||||||
|
@ -240,10 +245,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun stopBolusDelivering() {
|
override fun stopBolusDelivering() {
|
||||||
// TODO update Treatments (?)
|
// TODO update Treatments (?)
|
||||||
executeProgrammingCommand(
|
executeSimpleProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.CANCEL_BOLUS),
|
history.createRecord(OmnipodCommandType.CANCEL_BOLUS),
|
||||||
omnipodManager.stopBolus(),
|
omnipodManager.stopBolus(),
|
||||||
)
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTempBasalAbsolute(
|
override fun setTempBasalAbsolute(
|
||||||
|
@ -253,24 +258,83 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
enforceNew: Boolean,
|
enforceNew: Boolean,
|
||||||
tbrType: PumpSync.TemporaryBasalType
|
tbrType: PumpSync.TemporaryBasalType
|
||||||
): PumpEnactResult {
|
): PumpEnactResult {
|
||||||
// TODO update Treatments
|
return Completable.concat(
|
||||||
// TODO check for existing basal
|
listOf(
|
||||||
// check existing basal(locally and maybe? get status)
|
observeNoActiveTempBasal(enforceNew),
|
||||||
// if enforceNew -> cancel it()
|
podStateManager.observeNoActiveCommand().ignoreElements(),
|
||||||
// else -> return error that existing basal is running
|
history.createRecord(
|
||||||
// set new temp basal
|
commandType = OmnipodCommandType.SET_TEMPORARY_BASAL,
|
||||||
// update treatments
|
tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate)
|
||||||
// profit
|
).flatMap { podStateManager.createActiveCommand(it) }
|
||||||
return executeProgrammingCommand(
|
.map { pumpSyncTempBasal(it, tbrType) }
|
||||||
history.createRecord(
|
.ignoreElement(),
|
||||||
commandType = OmnipodCommandType.SET_TEMPORARY_BASAL,
|
omnipodManager.setTempBasal(
|
||||||
tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate)
|
absoluteRate,
|
||||||
),
|
durationInMinutes.toShort()
|
||||||
omnipodManager.setTempBasal(
|
).ignoreElements(),
|
||||||
absoluteRate,
|
history.updateFromState(podStateManager),
|
||||||
durationInMinutes.toShort()
|
podStateManager.updateActiveCommand()
|
||||||
|
.map { handleCommandConfirmation(it) }
|
||||||
|
.ignoreElement()
|
||||||
)
|
)
|
||||||
|
).toPumpEnactResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun pumpSyncTempBasal(
|
||||||
|
activeCommand: OmnipodDashPodStateManager.ActiveCommand,
|
||||||
|
tbrType: PumpSync.TemporaryBasalType
|
||||||
|
): Boolean {
|
||||||
|
val historyEntry = history.getById(activeCommand.historyId)
|
||||||
|
val record = historyEntry.record
|
||||||
|
if (record == null || !(record is TempBasalRecord)) {
|
||||||
|
throw IllegalArgumentException("Illegal recording in history: $record. Expected a temp basal")
|
||||||
|
}
|
||||||
|
val ret = pumpSync.syncTemporaryBasalWithPumpId(
|
||||||
|
timestamp = historyEntry.pumpId(),
|
||||||
|
rate = record.rate,
|
||||||
|
duration = record.duration.toLong(),
|
||||||
|
isAbsolute = true,
|
||||||
|
type = tbrType,
|
||||||
|
pumpId = historyEntry.pumpId(),
|
||||||
|
pumpType = PumpType.OMNIPOD_DASH,
|
||||||
|
pumpSerial = serialNumber()
|
||||||
)
|
)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "Pump sync temp basal: $ret")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeNoActiveTempBasal(enforeNew: Boolean): Completable {
|
||||||
|
return Completable.create { source ->
|
||||||
|
val expectedState = pumpSync.expectedPumpState()
|
||||||
|
when {
|
||||||
|
expectedState.temporaryBasal == null ->
|
||||||
|
source.onComplete()
|
||||||
|
!enforeNew ->
|
||||||
|
source.onError(
|
||||||
|
IllegalStateException(
|
||||||
|
"Temporary basal already active and enforeNew is not set."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else -> // enforceNew == true
|
||||||
|
executeSimpleProgrammingCommand(
|
||||||
|
history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
||||||
|
omnipodManager.stopTempBasal()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeActiveTempBasal(): Completable {
|
||||||
|
return Completable.defer {
|
||||||
|
if (pumpSync.expectedPumpState().temporaryBasal != null)
|
||||||
|
Completable.complete()
|
||||||
|
else
|
||||||
|
Completable.error(
|
||||||
|
java.lang.IllegalStateException(
|
||||||
|
"There is no active basal to cancel"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTempBasalPercent(
|
override fun setTempBasalPercent(
|
||||||
|
@ -292,13 +356,61 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
|
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
|
||||||
// TODO update Treatments
|
return executeSimpleProgrammingCommand(
|
||||||
return executeProgrammingCommand(
|
observeCreateHistoryEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
||||||
history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL),
|
command = omnipodManager.stopTempBasal(),
|
||||||
omnipodManager.stopTempBasal()
|
pre = observeActiveTempBasal(),
|
||||||
|
).toPumpEnactResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Completable.toPumpEnactResult(): PumpEnactResult {
|
||||||
|
return this.toSingleDefault(PumpEnactResult(injector).success(true).enacted(true))
|
||||||
|
.onErrorReturnItem(PumpEnactResult(injector).success(false).enacted(false))
|
||||||
|
.blockingGet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeCancelTempBasal(): Completable {
|
||||||
|
return Completable.concat(
|
||||||
|
listOf(
|
||||||
|
observeActiveTempBasal(),
|
||||||
|
podStateManager.observeNoActiveCommand().ignoreElements(),
|
||||||
|
history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL)
|
||||||
|
.flatMap { podStateManager.createActiveCommand(it) }
|
||||||
|
.ignoreElement(),
|
||||||
|
omnipodManager.stopTempBasal().ignoreElements(),
|
||||||
|
history.updateFromState(podStateManager),
|
||||||
|
podStateManager.updateActiveCommand()
|
||||||
|
.map { handleCommandConfirmation(it) }
|
||||||
|
.ignoreElement()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleCommandConfirmation(confirmation: CommandConfirmed) {
|
||||||
|
val historyEntry = history.getById(confirmation.historyId)
|
||||||
|
when (historyEntry.commandType) {
|
||||||
|
OmnipodCommandType.CANCEL_TEMPORARY_BASAL ->
|
||||||
|
if (confirmation.success) {
|
||||||
|
pumpSync.syncStopTemporaryBasalWithPumpId(
|
||||||
|
historyEntry.createdAt,
|
||||||
|
historyEntry.pumpId(),
|
||||||
|
PumpType.OMNIPOD_DASH,
|
||||||
|
serialNumber()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
OmnipodCommandType.SET_TEMPORARY_BASAL ->
|
||||||
|
if (!confirmation.success) {
|
||||||
|
pumpSync.invalidateTemporaryBasal(historyEntry.pumpId())
|
||||||
|
}
|
||||||
|
|
||||||
|
else ->
|
||||||
|
throw IllegalArgumentException(
|
||||||
|
"Don't know how to sync confirmed command of type: $historyEntry and " +
|
||||||
|
"succes: ${confirmation.success}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun cancelExtendedBolus(): PumpEnactResult {
|
override fun cancelExtendedBolus(): PumpEnactResult {
|
||||||
// TODO i18n
|
// TODO i18n
|
||||||
return PumpEnactResult(injector).success(false).enacted(false)
|
return PumpEnactResult(injector).success(false).enacted(false)
|
||||||
|
@ -414,26 +526,26 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun suspendDelivery(): PumpEnactResult {
|
private fun suspendDelivery(): PumpEnactResult {
|
||||||
return executeProgrammingCommand(
|
return executeSimpleProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
||||||
omnipodManager.suspendDelivery()
|
omnipodManager.suspendDelivery()
|
||||||
)
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resumeDelivery(): PumpEnactResult {
|
private fun resumeDelivery(): PumpEnactResult {
|
||||||
return profileFunction.getProfile()?.let {
|
return profileFunction.getProfile()?.let {
|
||||||
executeProgrammingCommand(
|
executeSimpleProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
history.createRecord(OmnipodCommandType.RESUME_DELIVERY),
|
||||||
omnipodManager.setBasalProgram(mapProfileToBasalProgram(it))
|
omnipodManager.setBasalProgram(mapProfileToBasalProgram(it))
|
||||||
)
|
).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 executeProgrammingCommand(
|
return executeSimpleProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
|
history.createRecord(OmnipodCommandType.DEACTIVATE_POD),
|
||||||
omnipodManager.deactivatePod()
|
omnipodManager.deactivatePod()
|
||||||
)
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleTimeChange(): PumpEnactResult {
|
private fun handleTimeChange(): PumpEnactResult {
|
||||||
|
@ -447,10 +559,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun playTestBeep(): PumpEnactResult {
|
private fun playTestBeep(): PumpEnactResult {
|
||||||
return executeProgrammingCommand(
|
return executeSimpleProgrammingCommand(
|
||||||
history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP),
|
history.createRecord(OmnipodCommandType.PLAY_TEST_BEEP),
|
||||||
omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP)
|
omnipodManager.playBeep(BeepType.LONG_SINGLE_BEEP)
|
||||||
)
|
).toPumpEnactResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {
|
override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {
|
||||||
|
@ -474,50 +586,27 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
commandQueue.customCommand(CommandHandleTimeChange(false), null)
|
commandQueue.customCommand(CommandHandleTimeChange(false), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeAddNewActiveCommandToHistory(observeCreateHistoryEntry: Single<String>): Observable<PodEvent> {
|
private fun executeSimpleProgrammingCommand(
|
||||||
return observeCreateHistoryEntry.flatMapObservable {
|
observeCreateHistoryEntry: Single<String>,
|
||||||
podStateManager.createActiveCommand(it).toObservable<PodEvent>()
|
command: Observable<PodEvent>,
|
||||||
|
pre: Completable = Completable.complete(),
|
||||||
|
): Completable {
|
||||||
|
return Completable.concat(
|
||||||
|
listOf(
|
||||||
|
pre,
|
||||||
|
podStateManager.observeNoActiveCommand().ignoreElements(),
|
||||||
|
observeCreateHistoryEntry
|
||||||
|
.flatMap { podStateManager.createActiveCommand(it) }
|
||||||
|
.ignoreElement(),
|
||||||
|
command.ignoreElements(),
|
||||||
|
history.updateFromState(podStateManager),
|
||||||
|
podStateManager.updateActiveCommand()
|
||||||
|
.map { handleCommandConfirmation(it) }
|
||||||
|
.ignoreElement()
|
||||||
|
)
|
||||||
|
).doOnError { error ->
|
||||||
|
aapsLogger.error(LTag.PUMP, "Error executing command", error)
|
||||||
|
podStateManager.maybeMarkActiveCommandFailed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun executeProgrammingCommand(
|
|
||||||
observeCreateHistoryEntry: Single<String>,
|
|
||||||
command: Observable<PodEvent>
|
|
||||||
): PumpEnactResult {
|
|
||||||
return Single.create<PumpEnactResult> { source ->
|
|
||||||
Observable.concat(
|
|
||||||
listOf(
|
|
||||||
podStateManager.observeNoActiveCommand(),
|
|
||||||
observeAddNewActiveCommandToHistory(observeCreateHistoryEntry),
|
|
||||||
command,
|
|
||||||
history.updateFromState(podStateManager).toObservable(),
|
|
||||||
podStateManager.updateActiveCommand().toObservable(),
|
|
||||||
)
|
|
||||||
).subscribeBy(
|
|
||||||
onNext = { podEvent ->
|
|
||||||
aapsLogger.debug(
|
|
||||||
LTag.PUMP,
|
|
||||||
"Received PodEvent: $podEvent"
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onError = { throwable ->
|
|
||||||
aapsLogger.error(LTag.PUMP, "Error executing command", throwable)
|
|
||||||
// Here we assume that onError will be called only BEFORE we manage to send a command
|
|
||||||
// If it gets called later, we will have the command as "not sent" in history and will not try to
|
|
||||||
// get it's final status, even if it was send
|
|
||||||
|
|
||||||
podStateManager.maybeMarkActiveCommandFailed()
|
|
||||||
source.onSuccess(
|
|
||||||
PumpEnactResult(injector).success(false).enacted(false).comment(throwable.toString())
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onComplete = {
|
|
||||||
aapsLogger.debug("Command completed")
|
|
||||||
source.onSuccess(
|
|
||||||
PumpEnactResult(injector).success(true).enacted(true)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.blockingGet()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,4 @@ sealed class PodEvent {
|
||||||
return "ResponseReceived(command=$command, response=$response)"
|
return "ResponseReceived(command=$command, response=$response)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CommandConfirmed(val historyId: String, val success: Boolean) : PodEvent()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state
|
||||||
|
|
||||||
|
class CommandConfirmed(val historyId: String, val success: Boolean)
|
|
@ -8,9 +8,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
|
||||||
import io.reactivex.Completable
|
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ interface OmnipodDashPodStateManager {
|
||||||
fun updateFromPairing(uniqueId: Id, pairResult: PairResult)
|
fun updateFromPairing(uniqueId: Id, pairResult: PairResult)
|
||||||
fun reset()
|
fun reset()
|
||||||
|
|
||||||
fun createActiveCommand(historyId: String): Completable
|
fun createActiveCommand(historyId: String): Single<ActiveCommand>
|
||||||
fun updateActiveCommand(): Maybe<PodEvent>
|
fun updateActiveCommand(): Maybe<CommandConfirmed>
|
||||||
fun observeNoActiveCommand(): Observable<PodEvent>
|
fun observeNoActiveCommand(): Observable<PodEvent>
|
||||||
fun maybeMarkActiveCommandFailed()
|
fun maybeMarkActiveCommandFailed()
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import io.reactivex.Completable
|
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -183,21 +183,24 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
get() = podState.activeCommand
|
get() = podState.activeCommand
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun createActiveCommand(historyId: String) = Completable.create { source ->
|
override fun createActiveCommand(historyId: String): Single<OmnipodDashPodStateManager.ActiveCommand> {
|
||||||
if (activeCommand == null) {
|
return Single.create { source ->
|
||||||
podState.activeCommand = OmnipodDashPodStateManager.ActiveCommand(
|
if (activeCommand == null) {
|
||||||
podState.messageSequenceNumber,
|
val command = OmnipodDashPodStateManager.ActiveCommand(
|
||||||
createdRealtime = SystemClock.elapsedRealtime(),
|
podState.messageSequenceNumber,
|
||||||
historyId = historyId
|
createdRealtime = SystemClock.elapsedRealtime(),
|
||||||
)
|
historyId = historyId
|
||||||
source.onComplete()
|
|
||||||
} else {
|
|
||||||
source.onError(
|
|
||||||
java.lang.IllegalStateException(
|
|
||||||
"Trying to send a command " +
|
|
||||||
"and the last command was not confirmed"
|
|
||||||
)
|
)
|
||||||
)
|
podState.activeCommand = command
|
||||||
|
source.onSuccess(command)
|
||||||
|
} else {
|
||||||
|
source.onError(
|
||||||
|
java.lang.IllegalStateException(
|
||||||
|
"Trying to send a command " +
|
||||||
|
"and the last command was not confirmed"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +231,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun updateActiveCommand() = Maybe.create<PodEvent> { source ->
|
override fun updateActiveCommand() = Maybe.create<CommandConfirmed> { source ->
|
||||||
podState.activeCommand?.run {
|
podState.activeCommand?.run {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Trying to confirm active command with parameters: $activeCommand " +
|
"Trying to confirm active command with parameters: $activeCommand " +
|
||||||
|
@ -241,12 +244,12 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
else {
|
else {
|
||||||
podState.activeCommand = null
|
podState.activeCommand = null
|
||||||
if (sequenceNumberOfLastProgrammingCommand == sequence)
|
if (sequenceNumberOfLastProgrammingCommand == sequence)
|
||||||
source.onSuccess(PodEvent.CommandConfirmed(historyId, true))
|
source.onSuccess(CommandConfirmed(historyId, true))
|
||||||
else
|
else
|
||||||
source.onSuccess(PodEvent.CommandConfirmed(historyId, false))
|
source.onSuccess(CommandConfirmed(historyId, false))
|
||||||
}
|
}
|
||||||
}
|
} ?: source.onComplete()
|
||||||
?: source.onComplete() // no active programming command
|
// no active programming command
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun increaseEapAkaSequenceNumber(): ByteArray {
|
override fun increaseEapAkaSequenceNumber(): ByteArray {
|
||||||
|
|
|
@ -35,6 +35,14 @@ class DashHistory @Inject constructor(
|
||||||
currentTimeMillis()
|
currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getById(id: String): HistoryRecord {
|
||||||
|
val entry = dao.byIdBlocking(id)
|
||||||
|
if (entry == null) {
|
||||||
|
throw java.lang.IllegalArgumentException("history entry [$id] not found")
|
||||||
|
}
|
||||||
|
return historyMapper.entityToDomain(entry)
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("ReturnCount")
|
@Suppress("ReturnCount")
|
||||||
fun createRecord(
|
fun createRecord(
|
||||||
commandType: OmnipodCommandType,
|
commandType: OmnipodCommandType,
|
||||||
|
@ -77,7 +85,6 @@ class DashHistory @Inject constructor(
|
||||||
fun updateFromState(podState: OmnipodDashPodStateManager) = Completable.defer {
|
fun updateFromState(podState: OmnipodDashPodStateManager) = Completable.defer {
|
||||||
podState.activeCommand?.run {
|
podState.activeCommand?.run {
|
||||||
when {
|
when {
|
||||||
|
|
||||||
createdRealtime <= podState.lastStatusResponseReceived &&
|
createdRealtime <= podState.lastStatusResponseReceived &&
|
||||||
sequence == podState.sequenceNumberOfLastProgrammingCommand ->
|
sequence == podState.sequenceNumberOfLastProgrammingCommand ->
|
||||||
dao.setInitialResult(historyId, InitialResult.SENT)
|
dao.setInitialResult(historyId, InitialResult.SENT)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data
|
||||||
|
|
||||||
|
import com.github.guepardoapps.kulid.ULID
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType
|
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
data class HistoryRecord(
|
data class HistoryRecord(
|
||||||
val id: String, // ULID
|
val id: String, // ULID
|
||||||
|
@ -11,4 +13,9 @@ data class HistoryRecord(
|
||||||
val record: Record?,
|
val record: Record?,
|
||||||
val resolvedResult: ResolvedResult?,
|
val resolvedResult: ResolvedResult?,
|
||||||
val resolvedAt: Long?
|
val resolvedAt: Long?
|
||||||
)
|
) {
|
||||||
|
fun pumpId(): Long {
|
||||||
|
val entropy = ULID.getEntropy(id)
|
||||||
|
return ByteBuffer.wrap(entropy).getLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ enum class BolusType {
|
||||||
companion object {
|
companion object {
|
||||||
fun fromBolusInfoBolusType(type: DetailedBolusInfo.BolusType): BolusType {
|
fun fromBolusInfoBolusType(type: DetailedBolusInfo.BolusType): BolusType {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
DetailedBolusInfo.BolusType.SMB -> SMB;
|
DetailedBolusInfo.BolusType.SMB -> SMB
|
||||||
else -> DEFAULT
|
else -> DEFAULT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ abstract class HistoryRecordDao {
|
||||||
@Query("SELECT * from historyrecords WHERE createdAt <= :since")
|
@Query("SELECT * from historyrecords WHERE createdAt <= :since")
|
||||||
abstract fun allSince(since: Long): Single<List<HistoryRecordEntity>>
|
abstract fun allSince(since: Long): Single<List<HistoryRecordEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM historyrecords WHERE id = :id LIMIT 1")
|
||||||
|
abstract fun byIdBlocking(id: String): HistoryRecordEntity?
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
abstract fun saveBlocking(historyRecordEntity: HistoryRecordEntity)
|
abstract fun saveBlocking(historyRecordEntity: HistoryRecordEntity)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.spongycastle.util.encoders.Hex
|
import org.spongycastle.util.encoders.Hex
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
|
|
||||||
import com.google.crypto.tink.subtle.Hex
|
import com.google.crypto.tink.subtle.Hex
|
||||||
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
|
|
||||||
import com.google.crypto.tink.subtle.Hex
|
import com.google.crypto.tink.subtle.Hex
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
|
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
|
|
||||||
import com.google.crypto.tink.subtle.Hex
|
import com.google.crypto.tink.subtle.Hex
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
|
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.RandomByteGenerator
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.RandomByteGenerator
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.spongycastle.util.encoders.Hex
|
import org.spongycastle.util.encoders.Hex
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
|
||||||
import info.nightscout.androidaps.extensions.toHex
|
import info.nightscout.androidaps.extensions.toHex
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLoggerTest
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.spongycastle.util.encoders.Hex
|
import org.spongycastle.util.encoders.Hex
|
||||||
|
|
Loading…
Reference in a new issue