prepare TemporaryBasal

This commit is contained in:
Milos Kozak 2021-04-01 23:46:21 +02:00
parent 9f66f88832
commit e26e023ebf
30 changed files with 560 additions and 246 deletions

View file

@ -2,11 +2,9 @@ package info.nightscout.androidaps.db
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.* import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.events.EventFoodDatabaseChanged import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.events.EventTempTargetChange import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.events.EventTherapyEventChange
import info.nightscout.androidaps.events.EventTreatmentChange
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -56,5 +54,13 @@ class CompatDBHelper @Inject constructor(
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged") aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventTreatmentChange()) rxBus.send(EventTreatmentChange())
} }
it.filterIsInstance<TemporaryBasal>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventTempBasalChange")
rxBus.send(EventTempBasalChange())
}
it.filterIsInstance<ExtendedBolus>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventExtendedBolusChange")
rxBus.send(EventExtendedBolusChange())
}
} }
} }

View file

@ -10,11 +10,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogTempbasalBinding import info.nightscout.androidaps.databinding.DialogTempbasalBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
@ -127,10 +123,10 @@ class TempBasalDialog : DialogFragmentWithDate() {
} }
if (isPercentPump) { if (isPercentPump) {
uel.log(Action.TEMP_BASAL, ValueWithUnit(percent, Units.Percent), ValueWithUnit(durationInMinutes, Units.M)) uel.log(Action.TEMP_BASAL, ValueWithUnit(percent, Units.Percent), ValueWithUnit(durationInMinutes, Units.M))
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback) commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} else { } else {
uel.log(Action.TEMP_BASAL, ValueWithUnit(absolute, Units.U), ValueWithUnit(durationInMinutes, Units.M)) uel.log(Action.TEMP_BASAL, ValueWithUnit(absolute, Units.U), ValueWithUnit(durationInMinutes, Units.M))
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback) commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
}) })
} }

View file

@ -17,8 +17,8 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
@ -33,7 +33,6 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotifi
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -78,7 +77,6 @@ open class LoopPlugin @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val receiverStatusStore: ReceiverStatusStore, private val receiverStatusStore: ReceiverStatusStore,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val nsUpload: NSUpload,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val repository: AppRepository, private val repository: AppRepository,
private val runningConfiguration: RunningConfiguration private val runningConfiguration: RunningConfiguration
@ -99,6 +97,7 @@ open class LoopPlugin @Inject constructor(
private var carbsSuggestionsSuspendedUntil: Long = 0 private var carbsSuggestionsSuspendedUntil: Long = 0
private var prevCarbsreq = 0 private var prevCarbsreq = 0
override var lastRun: LastRun? = null override var lastRun: LastRun? = null
override fun onStart() { override fun onStart() {
createNotificationChannel() createNotificationChannel()
super.onStart() super.onStart()
@ -305,20 +304,18 @@ open class LoopPlugin @Inject constructor(
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval") aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
resultAfterConstraints.smb = 0.0 resultAfterConstraints.smb = 0.0
} }
if (lastRun != null && lastRun!!.constraintsProcessed != null) { prevCarbsreq = lastRun?.constraintsProcessed?.carbsReq ?: prevCarbsreq
prevCarbsreq = lastRun!!.constraintsProcessed!!.carbsReq lastRun = (lastRun ?: LastRun()).also { lastRun ->
} lastRun.request = apsResult
if (lastRun == null) lastRun = LastRun() lastRun.constraintsProcessed = resultAfterConstraints
lastRun!!.request = apsResult lastRun.lastAPSRun = DateUtil.now()
lastRun!!.constraintsProcessed = resultAfterConstraints lastRun.source = (usedAPS as PluginBase).name
lastRun!!.lastAPSRun = DateUtil.now() lastRun.tbrSetByPump = null
lastRun!!.source = (usedAPS as PluginBase).name lastRun.smbSetByPump = null
lastRun!!.tbrSetByPump = null lastRun.lastTBREnact = 0
lastRun!!.smbSetByPump = null lastRun.lastTBRRequest = 0
lastRun!!.lastTBREnact = 0 lastRun.lastSMBEnact = 0
lastRun!!.lastTBRRequest = 0 lastRun.lastSMBRequest = 0
lastRun!!.lastSMBEnact = 0
lastRun!!.lastSMBRequest = 0
buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction, buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration, activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also { BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
@ -397,24 +394,24 @@ open class LoopPlugin @Inject constructor(
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) { && !commandQueue.isRunning(Command.CommandType.BOLUS)) {
val waiting = PumpEnactResult(injector) val waiting = PumpEnactResult(injector)
waiting.queued = true waiting.queued = true
if (resultAfterConstraints.tempBasalRequested) lastRun!!.tbrSetByPump = waiting if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
if (resultAfterConstraints.bolusRequested) lastRun!!.smbSetByPump = waiting if (resultAfterConstraints.bolusRequested) lastRun.smbSetByPump = waiting
rxBus.send(EventLoopUpdateGui()) rxBus.send(EventLoopUpdateGui())
fabricPrivacy.logCustom("APSRequest") fabricPrivacy.logCustom("APSRequest")
applyTBRRequest(resultAfterConstraints, profile, object : Callback() { applyTBRRequest(resultAfterConstraints, profile, object : Callback() {
override fun run() { override fun run() {
if (result.enacted || result.success) { if (result.enacted || result.success) {
lastRun!!.tbrSetByPump = result lastRun.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun!!.lastTBREnact = DateUtil.now() lastRun.lastTBREnact = DateUtil.now()
rxBus.send(EventLoopUpdateGui()) rxBus.send(EventLoopUpdateGui())
applySMBRequest(resultAfterConstraints, object : Callback() { applySMBRequest(resultAfterConstraints, object : Callback() {
override fun run() { override fun run() {
// Callback is only called if a bolus was actually requested // Callback is only called if a bolus was actually requested
if (result.enacted || result.success) { if (result.enacted || result.success) {
lastRun!!.smbSetByPump = result lastRun.smbSetByPump = result
lastRun!!.lastSMBRequest = lastRun!!.lastAPSRun lastRun.lastSMBRequest = lastRun.lastAPSRun
lastRun!!.lastSMBEnact = DateUtil.now() lastRun.lastSMBEnact = DateUtil.now()
} else { } else {
Thread { Thread {
SystemClock.sleep(1000) SystemClock.sleep(1000)
@ -425,15 +422,15 @@ open class LoopPlugin @Inject constructor(
} }
}) })
} else { } else {
lastRun!!.tbrSetByPump = result lastRun.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun lastRun.lastTBRRequest = lastRun.lastAPSRun
} }
rxBus.send(EventLoopUpdateGui()) rxBus.send(EventLoopUpdateGui())
} }
}) })
} else { } else {
lastRun!!.tbrSetByPump = null lastRun.tbrSetByPump = null
lastRun!!.smbSetByPump = null lastRun.smbSetByPump = null
} }
} else { } else {
if (resultAfterConstraints.isChangeRequested && allowNotification) { if (resultAfterConstraints.isChangeRequested && allowNotification) {
@ -454,6 +451,7 @@ open class LoopPlugin @Inject constructor(
} }
} }
rxBus.send(EventLoopUpdateGui()) rxBus.send(EventLoopUpdateGui())
}
} finally { } finally {
aapsLogger.debug(LTag.APS, "invoke end") aapsLogger.debug(LTag.APS, "invoke end")
} }
@ -496,14 +494,16 @@ open class LoopPlugin @Inject constructor(
} }
fun acceptChangeRequest() { fun acceptChangeRequest() {
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile() ?: return
applyTBRRequest(lastRun!!.constraintsProcessed, profile, object : Callback() { lastRun?.let { lastRun ->
lastRun.constraintsProcessed?.let { constraintsProcessed ->
applyTBRRequest(constraintsProcessed, profile, object : Callback() {
override fun run() { override fun run() {
if (result.enacted) { if (result.enacted) {
lastRun!!.tbrSetByPump = result lastRun.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun!!.lastTBREnact = DateUtil.now() lastRun.lastTBREnact = DateUtil.now()
lastRun!!.lastOpenModeAccept = DateUtil.now() lastRun.lastOpenModeAccept = DateUtil.now()
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction, buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration, activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also { BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
@ -514,6 +514,8 @@ open class LoopPlugin @Inject constructor(
rxBus.send(EventAcceptOpenLoopChange()) rxBus.send(EventAcceptOpenLoopChange())
} }
}) })
}
}
fabricPrivacy.logCustom("AcceptTemp") fabricPrivacy.logCustom("AcceptTemp")
} }
@ -521,8 +523,8 @@ open class LoopPlugin @Inject constructor(
* expect absolute request and allow both absolute and percent response based on pump capabilities * expect absolute request and allow both absolute and percent response based on pump capabilities
* TODO: update pump drivers to support APS request in % * TODO: update pump drivers to support APS request in %
*/ */
private fun applyTBRRequest(request: APSResult?, profile: Profile?, callback: Callback?) { private fun applyTBRRequest(request: APSResult, profile: Profile, callback: Callback?) {
if (!request!!.tempBasalRequested) { if (!request.tempBasalRequested) {
callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(R.string.nochangerequested))?.run() callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(R.string.nochangerequested))?.run()
return return
} }
@ -557,7 +559,7 @@ open class LoopPlugin @Inject constructor(
.comment(R.string.let_temp_basal_run))?.run() .comment(R.string.let_temp_basal_run))?.run()
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()") aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile!!, callback) commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
} else { } else {
if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) { if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) {
@ -576,7 +578,7 @@ open class LoopPlugin @Inject constructor(
.comment(R.string.let_temp_basal_run))?.run() .comment(R.string.let_temp_basal_run))?.run()
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()") aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile!!, callback) commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
} }
} }
@ -625,7 +627,7 @@ open class LoopPlugin @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L) disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L)
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile!!, object : Callback() { commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile!!, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
@ -633,7 +635,7 @@ open class LoopPlugin @Inject constructor(
} }
}) })
} else { } else {
commandQueue.tempBasalPercent(0, durationInMinutes, true, profile!!, object : Callback() { commandQueue.tempBasalPercent(0, durationInMinutes, true, profile!!, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)

View file

@ -182,7 +182,8 @@ class SmsCommunicatorPlugin @Inject constructor(
override fun doWork(): Result { override fun doWork(): Result {
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1)) val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure(workDataOf("Error" to "missing input data")) ?: return Result.failure(workDataOf("Error" to "missing input data"))
val format = bundle.getString("format") ?: return Result.failure(workDataOf("Error" to "missing format in input data")) val format = bundle.getString("format")
?: return Result.failure(workDataOf("Error" to "missing format in input data"))
val pdus = bundle["pdus"] as Array<*> val pdus = bundle["pdus"] as Array<*>
for (pdu in pdus) { for (pdu in pdus) {
val message = SmsMessage.createFromPdu(pdu as ByteArray, format) val message = SmsMessage.createFromPdu(pdu as ByteArray, format)
@ -633,7 +634,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasalPct, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasalPct, duration) {
override fun run() { override fun run() {
commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, object : Callback() { commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration)
@ -670,7 +671,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasal, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasal, duration) {
override fun run() { override fun run() {
commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, object : Callback() { commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration)

View file

@ -93,7 +93,7 @@ class MDIPlugin @Inject constructor(
} }
override fun stopBolusDelivering() {} override fun stopBolusDelivering() {}
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
val result = PumpEnactResult(injector) val result = PumpEnactResult(injector)
result.success = false result.success = false
result.comment = resourceHelper.gs(R.string.pumperror) result.comment = resourceHelper.gs(R.string.pumperror)
@ -101,7 +101,7 @@ class MDIPlugin @Inject constructor(
return result return result
} }
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
val result = PumpEnactResult(injector) val result = PumpEnactResult(injector)
result.success = false result.success = false
result.comment = resourceHelper.gs(R.string.pumperror) result.comment = resourceHelper.gs(R.string.pumperror)

View file

@ -222,7 +222,7 @@ open class VirtualPumpPlugin @Inject constructor(
} }
override fun stopBolusDelivering() {} override fun stopBolusDelivering() {}
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
val tempBasal = TemporaryBasal(injector) val tempBasal = TemporaryBasal(injector)
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
.absolute(absoluteRate) .absolute(absoluteRate)
@ -242,7 +242,7 @@ open class VirtualPumpPlugin @Inject constructor(
return result return result
} }
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
val tempBasal = TemporaryBasal(injector) val tempBasal = TemporaryBasal(injector)
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
.percent(percent) .percent(percent)

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -280,7 +281,7 @@ open class CommandQueue @Inject constructor(
} }
// returns true if command is queued // returns true if command is queued
override fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean { override fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, tbrType: PumpSync.TemporaryBasalType, callback: Callback?): Boolean {
if (!enforceNew && isRunning(CommandType.TEMPBASAL)) { if (!enforceNew && isRunning(CommandType.TEMPBASAL)) {
callback?.result(executingNowError())?.run() callback?.result(executingNowError())?.run()
return false return false
@ -289,13 +290,13 @@ open class CommandQueue @Inject constructor(
removeAll(CommandType.TEMPBASAL) removeAll(CommandType.TEMPBASAL)
val rateAfterConstraints = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value() val rateAfterConstraints = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
// add new command to queue // add new command to queue
add(CommandTempBasalAbsolute(injector, rateAfterConstraints, durationInMinutes, enforceNew, profile, callback)) add(CommandTempBasalAbsolute(injector, rateAfterConstraints, durationInMinutes, enforceNew, profile, tbrType, callback))
notifyAboutNewCommand() notifyAboutNewCommand()
return true return true
} }
// returns true if command is queued // returns true if command is queued
override fun tempBasalPercent(percent: Int, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean { override fun tempBasalPercent(percent: Int, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, tbrType: PumpSync.TemporaryBasalType, callback: Callback?): Boolean {
if (!enforceNew && isRunning(CommandType.TEMPBASAL)) { if (!enforceNew && isRunning(CommandType.TEMPBASAL)) {
callback?.result(executingNowError())?.run() callback?.result(executingNowError())?.run()
return false return false
@ -304,7 +305,7 @@ open class CommandQueue @Inject constructor(
removeAll(CommandType.TEMPBASAL) removeAll(CommandType.TEMPBASAL)
val percentAfterConstraints = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value() val percentAfterConstraints = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value()
// add new command to queue // add new command to queue
add(CommandTempBasalPercent(injector, percentAfterConstraints, durationInMinutes, enforceNew, profile, callback)) add(CommandTempBasalPercent(injector, percentAfterConstraints, durationInMinutes, enforceNew, profile, tbrType, callback))
notifyAboutNewCommand() notifyAboutNewCommand()
return true return true
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import javax.inject.Inject import javax.inject.Inject
@ -13,13 +14,14 @@ class CommandTempBasalAbsolute(
private val durationInMinutes: Int, private val durationInMinutes: Int,
private val enforceNew: Boolean, private val enforceNew: Boolean,
private val profile: Profile, private val profile: Profile,
private val tbrType: PumpSync.TemporaryBasalType,
callback: Callback? callback: Callback?
) : Command(injector, CommandType.TEMPBASAL, callback) { ) : Command(injector, CommandType.TEMPBASAL, callback) {
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
override fun execute() { override fun execute() {
val r = activePlugin.activePump.setTempBasalAbsolute(absoluteRate, durationInMinutes, profile, enforceNew) val r = activePlugin.activePump.setTempBasalAbsolute(absoluteRate, durationInMinutes, profile, enforceNew, tbrType)
aapsLogger.debug(LTag.PUMPQUEUE, "Result rate: $absoluteRate durationInMinutes: $durationInMinutes success: ${r.success} enacted: ${r.enacted}") aapsLogger.debug(LTag.PUMPQUEUE, "Result rate: $absoluteRate durationInMinutes: $durationInMinutes success: ${r.success} enacted: ${r.enacted}")
callback?.result(r)?.run() callback?.result(r)?.run()
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import javax.inject.Inject import javax.inject.Inject
@ -13,13 +14,14 @@ class CommandTempBasalPercent(
private val durationInMinutes: Int, private val durationInMinutes: Int,
private val enforceNew: Boolean, private val enforceNew: Boolean,
private val profile: Profile, private val profile: Profile,
private val tbrType: PumpSync.TemporaryBasalType,
callback: Callback? callback: Callback?
) : Command(injector, CommandType.TEMPBASAL, callback) { ) : Command(injector, CommandType.TEMPBASAL, callback) {
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePluginProvider
override fun execute() { override fun execute() {
val r = activePlugin.activePump.setTempBasalPercent(percent, durationInMinutes, profile, enforceNew) val r = activePlugin.activePump.setTempBasalPercent(percent, durationInMinutes, profile, enforceNew, tbrType)
aapsLogger.debug(LTag.PUMPQUEUE, "Result percent: $percent durationInMinutes: $durationInMinutes success: ${r.success} enacted: ${r.enacted}") aapsLogger.debug(LTag.PUMPQUEUE, "Result percent: $percent durationInMinutes: $durationInMinutes success: ${r.success} enacted: ${r.enacted}")
callback?.result(r)?.run() callback?.result(r)?.run()
} }

View file

@ -373,7 +373,7 @@ class BolusWizard @Inject constructor(
} }
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
commandQueue.tempBasalAbsolute(0.0, 120, true, profile, object : Callback() { commandQueue.tempBasalAbsolute(0.0, 120, true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), R.raw.boluserror) ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), R.raw.boluserror)
@ -382,7 +382,7 @@ class BolusWizard @Inject constructor(
}) })
} else { } else {
commandQueue.tempBasalPercent(0, 120, true, profile, object : Callback() { commandQueue.tempBasalPercent(0, 120, true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(ctx, ErrorHelperActivity::class.java) val i = Intent(ctx, ErrorHelperActivity::class.java)

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
@ -711,7 +712,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
* the new value (and thus still has the old duration of e.g. 1 min) expires?) * the new value (and thus still has the old duration of e.g. 1 min) expires?)
*/ */
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean force) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean force, PumpSync.TemporaryBasalType tbrType) {
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute called with a rate of " + absoluteRate + " for " + durationInMinutes + " min."); getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute called with a rate of " + absoluteRate + " for " + durationInMinutes + " min.");
int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
int roundedPercentage = (int) (Math.round(absoluteRate / getBaseBasalRate() * 10) * 10); int roundedPercentage = (int) (Math.round(absoluteRate / getBaseBasalRate() * 10) * 10);
@ -729,7 +730,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
* is or isn't running at the moment * is or isn't running at the moment
*/ */
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean forceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean forceNew, PumpSync.TemporaryBasalType tbrType) {
return setTempBasalPercent(percent, durationInMinutes); return setTempBasalPercent(percent, durationInMinutes);
} }

View file

@ -22,8 +22,8 @@ interface CommandQueueProvider {
fun stopPump(callback: Callback?) fun stopPump(callback: Callback?)
fun startPump(callback: Callback?) fun startPump(callback: Callback?)
fun setTBROverNotification(callback: Callback?, enable: Boolean) fun setTBROverNotification(callback: Callback?, enable: Boolean)
fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, tbrType: PumpSync.TemporaryBasalType, callback: Callback?): Boolean
fun tempBasalPercent(percent: Int, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean fun tempBasalPercent(percent: Int, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, tbrType: PumpSync.TemporaryBasalType, callback: Callback?): Boolean
fun extendedBolus(insulin: Double, durationInMinutes: Int, callback: Callback?): Boolean fun extendedBolus(insulin: Double, durationInMinutes: Int, callback: Callback?): Boolean
fun cancelTempBasal(enforceNew: Boolean, callback: Callback?): Boolean fun cancelTempBasal(enforceNew: Boolean, callback: Callback?): Boolean
fun cancelExtended(callback: Callback?): Boolean fun cancelExtended(callback: Callback?): Boolean

View file

@ -13,7 +13,7 @@ import org.json.JSONObject
/** /**
* This interface defines the communication from AAPS-core to pump drivers. * This interface defines the communication from AAPS-core to pump drivers.
* Pump drivers communicate data changes back to AAPS-core using {@link info.nightscout.androidaps.interfaces.PumpSync}. * Pump drivers communicate data changes back to AAPS-core using [info.nightscout.androidaps.interfaces.PumpSync].
* *
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
*/ */
@ -46,22 +46,95 @@ interface PumpInterface {
* *
* @param detailedBolusInfo it's the caller's responsibility to ensure the request can be satisfied by the pump, * @param detailedBolusInfo it's the caller's responsibility to ensure the request can be satisfied by the pump,
* e.g. DBI will not contain carbs if the pump can't store carbs. * e.g. DBI will not contain carbs if the pump can't store carbs.
* @return PumpEnactResult
*/ */
fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult
fun stopBolusDelivering()
fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult
fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult
fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy /**
//when the cancel request is requested by the user (forced), the pump should always do a real cancel * Stopping of performed bolus requested by user
*/
fun stopBolusDelivering()
/**
* Request a TRB in absolute units [U/h]
*
* Driver is responsible for conversion to % if absolute rate is not supported by pump
*
* @param absoluteRate rate in U/h
* @param durationInMinutes duration
* @param profile only help for for U/h -> % transformation
* @param enforceNew if true drive should force new TBR (ie. stop current,
* and set new even if the same rate is requested
* @param tbrType tbrType for storing to DB [NORMAL,EMULATED_PUMP_SUSPEND,PUMP_SUSPEND,SUPERBOLUS]
* @return PumpEnactResult.success if TBR set,
* PumpEnactResult.enacted if new TBR set
* (if the same TBR rate is requested && enforceNew == false driver can keep
* running TBR. In this case return will be success = true, enacted = false)
*/
fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult
/**
* Request a TRB in %
*
* Driver is responsible for conversion to u/h if % is not supported by pump
*
* @param percent rate in % (100% is equal to not running TBR, 0% is zero temping)
* @param durationInMinutes duration
* @param profile only help for for U/h -> % transformation
* @param enforceNew if true drive should force new TBR (ie. stop current,
* and set new even if the same rate is requested
* @param tbrType tbrType for storing to DB [NORMAL,EMULATED_PUMP_SUSPEND,PUMP_SUSPEND,SUPERBOLUS]
* @return PumpEnactResult.success if TBR set,
* PumpEnactResult.enacted if new TBR set
* (if the same TBR rate is requested && enforceNew == false driver can keep
* running TBR. In this case return will be success = true, enacted = false)
*/
fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult
/**
* Cancel current TBR if a TBR is running
*
* some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
* when the cancel request is requested by the user (forced), the pump should always do a real cancel
*
* @param enforceNew if true disable workaround above
* @return PumpEnactResult.success if TBR is canceled
*/
fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult
fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult
fun cancelExtendedBolus(): PumpEnactResult fun cancelExtendedBolus(): PumpEnactResult
// Status to be passed to NS /**
* Status to be passed to NS
*
* This info is displayed when user hover over pump pill in NS
*
* @return JSON with information
*/
fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject
/**
* Manufacturer type. Usually defined by used plugin
*
* @return ManufacturerType
*/
fun manufacturer(): ManufacturerType fun manufacturer(): ManufacturerType
/**
* Pump model
*
* If new model is covered by driver, model and it's capabilities must be added to [info.nightscout.androidaps.plugins.pump.common.defs.PumpType]
*
* @return PumpType
*/
fun model(): PumpType fun model(): PumpType
/**
* Serial number
*
* Real serial number from device or "unique" generated for paired pump if not possible
*/
fun serialNumber(): String fun serialNumber(): String
// Pump capabilities // Pump capabilities

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.interfaces package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
/** /**
* This interface allows pump drivers to push data changes (creation and update of treatments) back to AAPS-core. * This interface allows pump drivers to push data changes (creation and update of treatments, temporary basals and extended boluses) back to AAPS-core.
* *
* Intended use cases for handling bolus treatments: * Intended use cases for handling bolus treatments:
* *
@ -20,6 +21,11 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
* bolus. * bolus.
*/ */
interface PumpSync { interface PumpSync {
/*
* BOLUSES & CARBS
*/
/** /**
* Create bolus with temporary id * Create bolus with temporary id
* *
@ -105,6 +111,10 @@ interface PumpSync {
**/ **/
fun syncCarbsWithTimestamp(timestamp: Long, amount: Double, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean fun syncCarbsWithTimestamp(timestamp: Long, amount: Double, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean
/*
* THERAPY EVENTS
*/
/** /**
* Synchronization of events like CANNULA_CHANGE * Synchronization of events like CANNULA_CHANGE
* *
@ -139,4 +149,69 @@ interface PumpSync {
* @param pumpSerial pump serial number * @param pumpSerial pump serial number
**/ **/
fun insertAnnouncement(error: String, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String) fun insertAnnouncement(error: String, pumpId: Long? = null, pumpType: PumpType, pumpSerial: String)
/*
* TEMPORARY BASALS
*/
enum class TemporaryBasalType {
NORMAL,
EMULATED_PUMP_SUSPEND, // Initiated by AAPS as zero TBR
PUMP_SUSPEND, // Initiated on PUMP
SUPERBOLUS;
fun toDbType(): TemporaryBasal.Type =
when (this) {
NORMAL -> TemporaryBasal.Type.NORMAL
EMULATED_PUMP_SUSPEND -> TemporaryBasal.Type.EMULATED_PUMP_SUSPEND
PUMP_SUSPEND -> TemporaryBasal.Type.PUMP_SUSPEND
SUPERBOLUS -> TemporaryBasal.Type.SUPERBOLUS
}
}
/**
* Synchronization of temporary basals
*
* Search for combination of pumpId, PumpType, pumpSerial
*
* If exists, timestamp, duration, rate and type (if provided) is updated
* If db record doesn't exist, new record is created.
* If overlap another running TBR, running is cut off
* isValid field is preserved
*
* @param timestamp timestamp of event from pump history
* @param rate TBR rate in U/h or % (value of 100% is equal to no TBR)
* @param duration duration in milliseconds
* @param isAbsolute is TBR in U/h or % ?
* @param type type of TBR, from request sent to the driver
* @param pumpId pump id from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @return true if new record is created
**/
fun syncTemporaryBasalWithPumpId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, type: TemporaryBasalType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of temporary basals end event
* (for pumps having separate event for end of TBR or not having history)
* (not useful for pump modifying duration in history log)
*
* Search first for a TBR with combination of endPumpId, pumpType, pumpSerial
* if found assume, some running TBR has been already cut off and ignore data. False is returned
*
* Search for running TBR with combination of pumpType, pumpSerial
*
* If exists,
* currently running record is cut off by provided timestamp (ie duration is adjusted)
* endPumpId is stored to running record
* If db record doesn't exist data is ignored and false returned
*
* @param timestamp timestamp of event from pump history
* @param endPumpId pump id of ending event from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @return true if running record is found and ended by changing duration
**/
fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
} }

View file

@ -5,6 +5,7 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.Carbs import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.* import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
@ -34,10 +35,10 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(InsertPumpBolusWithTempIdTransaction(bolus)) repository.runTransactionForResult(InsertPumpBolusWithTempIdTransaction(bolus))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -55,10 +56,10 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(SyncPumpBolusWithTempIdTransaction(bolus, type?.toDBbBolusType())) repository.runTransactionForResult(SyncPumpBolusWithTempIdTransaction(bolus, type?.toDBbBolusType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated carbs $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") }
return result.updated.size > 0 return result.updated.size > 0
} }
} }
@ -75,11 +76,11 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType())) repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated carbs $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -130,4 +131,42 @@ class PumpSyncImplementation @Inject constructor(
.subscribe() .subscribe()
} }
/*
* TEMPORARY BASALS
*/
override fun syncTemporaryBasalWithPumpId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, type: PumpSync.TemporaryBasalType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
val temporaryBasal = TemporaryBasal(
timestamp = timestamp,
rate = rate,
duration = duration,
type = type?.toDbType() ?: TemporaryBasal.Type.NORMAL,
isAbsolute = isAbsolute,
interfaceIDs_backing = InterfaceIDs(
pumpId = pumpId,
pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial
)
)
repository.runTransactionForResult(SyncPumpTemporaryBasalTransaction(temporaryBasal, type?.toDbType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while temporary basal", it) }
.blockingGet()
.also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temporary basal $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temporary basal $it") }
return result.inserted.size > 0
}
}
override fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
repository.runTransactionForResult(SyncPumpCancelTemporaryBasalIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it) }
.blockingGet()
.also { result ->
result.updated.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated temporary basal $it")
}
return result.updated.size > 0
}
}
} }

View file

@ -213,7 +213,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// This is called from APS // This is called from APS
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this //This should not be needed while using queue because connection should be done before calling this
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
@ -281,7 +281,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
} }
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, profile, false); return setTempBasalPercent(percentRate, durationInMinutes, profile, false, tbrType);
} }
if (doExtendedTemp) { if (doExtendedTemp) {
// Check if some temp is already in progress // Check if some temp is already in progress

View file

@ -218,7 +218,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
// This is called from APS // This is called from APS
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
@ -262,7 +262,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
if (percentRate == 0 && durationInMinutes > 30) { if (percentRate == 0 && durationInMinutes > 30) {
result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew); result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew, tbrType);
} else { } else {
// use special APS temp basal call ... 100+/15min .... 100-/30min // use special APS temp basal call ... 100+/15min .... 100-/30min
result = setHighTempBasalPercent(percentRate, durationInMinutes); result = setHighTempBasalPercent(percentRate, durationInMinutes);
@ -281,7 +281,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
} }
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
DanaPump pump = danaPump; DanaPump pump = danaPump;
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value();

View file

@ -218,7 +218,7 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
} }
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
DanaPump pump = danaPump; DanaPump pump = danaPump;
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value();

View file

@ -205,7 +205,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// This is called from APS // This is called from APS
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this //This should not be needed while using queue because connection should be done before calling this
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
@ -273,7 +273,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
} }
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, profile, false); return setTempBasalPercent(percentRate, durationInMinutes, profile, false, tbrType);
} }
if (doExtendedTemp) { if (doExtendedTemp) {
// Check if some temp is already in progress // Check if some temp is already in progress

View file

@ -278,7 +278,7 @@ class DanaRSPlugin @Inject constructor(
if (carbTime == 0) carbTime-- // better set 1 min back to prevents clash with insulin if (carbTime == 0) carbTime-- // better set 1 min back to prevents clash with insulin
detailedBolusInfo.carbTime = 0 detailedBolusInfo.carbTime = 0
detailedBolusInfoStorage.add(detailedBolusInfo) // will be picked up on reading history detailedBolusInfoStorage.add(detailedBolusInfo) // will be picked up on reading history
val t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB); val t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB)
var connectionOK = false var connectionOK = false
if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService?.bolus(detailedBolusInfo.insulin, carbs.toInt(), DateUtil.now() + T.mins(carbTime.toLong()).msecs(), t) if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService?.bolus(detailedBolusInfo.insulin, carbs.toInt(), DateUtil.now() + T.mins(carbTime.toLong()).msecs(), t)
?: false ?: false
@ -315,7 +315,7 @@ class DanaRSPlugin @Inject constructor(
// This is called from APS // This is called from APS
@Synchronized @Synchronized
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
var result = PumpEnactResult(injector) var result = PumpEnactResult(injector)
val absoluteAfterConstrain = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value() val absoluteAfterConstrain = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
val doTempOff = baseBasalRate - absoluteAfterConstrain == 0.0 val doTempOff = baseBasalRate - absoluteAfterConstrain == 0.0
@ -367,7 +367,7 @@ class DanaRSPlugin @Inject constructor(
// Convert duration from minutes to hours // Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $percentRate% for $durationInMinutes minutes (doLowTemp || doHighTemp)") aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $percentRate% for $durationInMinutes minutes (doLowTemp || doHighTemp)")
result = if (percentRate == 0 && durationInMinutes > 30) { result = if (percentRate == 0 && durationInMinutes > 30) {
setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew) setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew, tbrType)
} else { } else {
// use special APS temp basal call ... 100+/15min .... 100-/30min // use special APS temp basal call ... 100+/15min .... 100-/30min
setHighTempBasalPercent(percentRate) setHighTempBasalPercent(percentRate)
@ -387,7 +387,7 @@ class DanaRSPlugin @Inject constructor(
} }
@Synchronized @Synchronized
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult { override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult {
val result = PumpEnactResult(injector) val result = PumpEnactResult(injector)
var percentAfterConstraint = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value() var percentAfterConstraint = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value()
if (percentAfterConstraint < 0) { if (percentAfterConstraint < 0) {

View file

@ -6,7 +6,7 @@ import androidx.room.TypeConverters
import info.nightscout.androidaps.database.daos.* import info.nightscout.androidaps.database.daos.*
import info.nightscout.androidaps.database.entities.* import info.nightscout.androidaps.database.entities.*
const val DATABASE_VERSION = 10 const val DATABASE_VERSION = 11
@Database(version = DATABASE_VERSION, @Database(version = DATABASE_VERSION,
entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class, entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,

View file

@ -5,7 +5,6 @@ import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_TEMPORARY_BASALS import info.nightscout.androidaps.database.TABLE_TEMPORARY_BASALS
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.database.entities.TemporaryBasal
import io.reactivex.Flowable
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.Single import io.reactivex.Single
@ -18,4 +17,43 @@ internal interface TemporaryBasalDao : TraceableDao<TemporaryBasal> {
@Query("DELETE FROM $TABLE_TEMPORARY_BASALS") @Query("DELETE FROM $TABLE_TEMPORARY_BASALS")
override fun deleteAllEntries() override fun deleteAllEntries()
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE pumpId = :pumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL")
fun findByPumpIds(pumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TemporaryBasal?
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE endPumpId = :endPumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL")
fun findByPumpEndIds(endPumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TemporaryBasal?
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE nightscoutId = :nsId AND referenceId IS NULL")
fun findByNSId(nsId: String): TemporaryBasal?
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryBasalActiveAt(timestamp: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): Maybe<TemporaryBasal>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryBasalActiveAt(timestamp: Long): Maybe<TemporaryBasal>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun getTemporaryBasalDataFromTime(timestamp: Long): Single<List<TemporaryBasal>>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY timestamp ASC")
fun getTemporaryBasalDataIncludingInvalidFromTime(timestamp: Long): Single<List<TemporaryBasal>>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun getTemporaryBasalData(): Single<List<TemporaryBasal>>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
fun getLastHistoryRecord(id: Long): TemporaryBasal?
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_TEMPORARY_BASALS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<TemporaryBasal>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<TemporaryBasal>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<TemporaryBasal>
} }

View file

@ -22,6 +22,7 @@ data class TemporaryBasal(
override var referenceId: Long? = null, override var referenceId: Long? = null,
@Embedded @Embedded
override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(), override var interfaceIDs_backing: InterfaceIDs? = InterfaceIDs(),
var endPumpId: Long? = null, // Some pumps provide separate start and end events in history. Even event pump id can be stored here
override var timestamp: Long, override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(), override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
var type: Type, var type: Type,

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.interfaces.end
class SyncPumpCancelTemporaryBasalIfAnyTransaction(
private val timestamp: Long, private val endPumpId: Long, private val pumpType: InterfaceIDs.PumpType, private val pumpSerial: String
) : Transaction<SyncPumpCancelTemporaryBasalIfAnyTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
val existing = database.temporaryBasalDao.findByPumpEndIds(endPumpId, pumpType, pumpSerial)
if (existing != null) // assume TBR has been cut already
return result
val current = database.temporaryBasalDao.getTemporaryBasalActiveAt(timestamp, pumpType, pumpSerial).blockingGet()
if (current != null) {
current.end = timestamp
current.endPumpId = endPumpId
database.temporaryBasalDao.updateExistingEntry(current)
result.updated.add(current)
}
return result
}
class TransactionResult {
val updated = mutableListOf<TemporaryBasal>()
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.interfaces.end
/**
* Creates or updates the Temporary basal from pump synchronization
*/
class SyncPumpTemporaryBasalTransaction(
private val temporaryBasal: TemporaryBasal,
private val type: TemporaryBasal.Type? // extra parameter because field is not nullable in TemporaryBasal.class
) : Transaction<SyncPumpTemporaryBasalTransaction.TransactionResult>() {
override fun run(): TransactionResult {
temporaryBasal.interfaceIDs.pumpId ?: temporaryBasal.interfaceIDs.pumpType ?: temporaryBasal.interfaceIDs.pumpSerial ?:
throw IllegalStateException("Some pump ID is null")
val result = TransactionResult()
val current = database.temporaryBasalDao.findByPumpIds(temporaryBasal.interfaceIDs.pumpId!!, temporaryBasal.interfaceIDs.pumpType!!, temporaryBasal.interfaceIDs.pumpSerial!!)
if (current != null) {
current.timestamp = temporaryBasal.timestamp
current.rate = temporaryBasal.rate
current.duration = temporaryBasal.duration
current.type = type ?: current.type
database.temporaryBasalDao.updateExistingEntry(current)
result.updated.add(current)
} else {
val running = database.temporaryBasalDao.getTemporaryBasalActiveAt(temporaryBasal.timestamp, temporaryBasal.interfaceIDs.pumpType!!, temporaryBasal.interfaceIDs.pumpSerial!!).blockingGet()
if (running != null) {
running.end = temporaryBasal.timestamp
database.temporaryBasalDao.updateExistingEntry(running)
result.updated.add(running)
}
database.temporaryBasalDao.insertNewEntry(temporaryBasal)
result.inserted.add(temporaryBasal)
}
return result
}
class TransactionResult {
val inserted = mutableListOf<TemporaryBasal>()
val updated = mutableListOf<TemporaryBasal>()
}
}

View file

@ -694,7 +694,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
} }
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
if (activeBasalRate == null) return result; if (activeBasalRate == null) return result;
if (activeBasalRate.getActiveBasalRate() == 0) return result; if (activeBasalRate.getActiveBasalRate() == 0) return result;
@ -722,13 +722,13 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
result.comment(cancelTBRResult.getComment()); result.comment(cancelTBRResult.getComment());
} }
} else { } else {
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew); return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew, tbrType);
} }
} else { } else {
result.comment(cancelEBResult.getComment()); result.comment(cancelEBResult.getComment());
} }
} else { } else {
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew); return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew, tbrType);
} }
try { try {
fetchStatus(); fetchStatus();
@ -744,7 +744,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
} }
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
percent = (int) Math.round(((double) percent) / 10d) * 10; percent = (int) Math.round(((double) percent) / 10d) * 10;
if (percent == 100) return cancelTempBasal(true); if (percent == 100) return cancelTempBasal(true);

View file

@ -27,6 +27,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
@ -247,14 +248,14 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute [PumpPluginAbstract] - Not implemented."); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver); return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
} }
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent [PumpPluginAbstract] - Not implemented."); aapsLogger.debug(LTag.PUMP, "setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver); return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
} }

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
@ -952,8 +953,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged),
// if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile, public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
boolean enforceNew) {
setRefreshButtonEnabled(false); setRefreshButtonEnabled(false);
@ -1064,14 +1064,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@NonNull @Override @NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
if (percent == 0) { if (percent == 0) {
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew); return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew, tbrType);
} else { } else {
double absoluteValue = profile.getBasal() * (percent / 100.0d); double absoluteValue = profile.getBasal() * (percent / 100.0d);
absoluteValue = pumpDescription.getPumpType().determineCorrectBasalSize(absoluteValue); absoluteValue = pumpDescription.getPumpType().determineCorrectBasalSize(absoluteValue);
aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct."); aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct.");
return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew); return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType);
} }
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash; package info.nightscout.androidaps.plugins.pump.omnipod.dash;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -21,6 +22,7 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.common.ManufacturerType; import info.nightscout.androidaps.plugins.common.ManufacturerType;
@ -131,11 +133,11 @@ public class OmnipodDashPumpPlugin extends PumpPluginBase implements PumpInterfa
} }
@NotNull @Override public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NotNull Profile profile, boolean enforceNew) { @NotNull @Override public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NotNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
return null; return null;
} }
@NotNull @Override public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NotNull Profile profile, boolean enforceNew) { @NotNull @Override public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NotNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
return null; return null;
} }

View file

@ -660,7 +660,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
// if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed
@Override @Override
@NonNull @NonNull
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes); aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes);
if (durationInMinutes <= 0 || durationInMinutes % BASAL_STEP_DURATION.getStandardMinutes() != 0) { if (durationInMinutes <= 0 || durationInMinutes % BASAL_STEP_DURATION.getStandardMinutes() != 0) {
@ -1026,14 +1026,14 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
aapsLogger.debug(LTag.PUMP, "stopConnecting [PumpPluginAbstract] - default (empty) implementation."); aapsLogger.debug(LTag.PUMP, "stopConnecting [PumpPluginAbstract] - default (empty) implementation.");
} }
@NonNull @Override public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew) { @NonNull @Override public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
if (percent == 0) { if (percent == 0) {
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew); return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew, tbrType);
} else { } else {
double absoluteValue = profile.getBasal() * (percent / 100.0d); double absoluteValue = profile.getBasal() * (percent / 100.0d);
absoluteValue = pumpDescription.getPumpType().determineCorrectBasalSize(absoluteValue); absoluteValue = pumpDescription.getPumpType().determineCorrectBasalSize(absoluteValue);
aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [OmnipodPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct."); aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [OmnipodPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct.");
return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew); return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType);
} }
} }