Merge remote-tracking branch 'Nightscout/meallink' into Test_MealLink_VWU_Merge

# Conflicts:
#	app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt
#	app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt
#	app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt
This commit is contained in:
Philoul 2021-04-04 13:51:53 +02:00
commit 22c1233201
29 changed files with 559 additions and 245 deletions

View file

@ -2,11 +2,9 @@ package info.nightscout.androidaps.db
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.events.EventFoodDatabaseChanged
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.events.EventTherapyEventChange
import info.nightscout.androidaps.events.EventTreatmentChange
import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -56,5 +54,13 @@ class CompatDBHelper @Inject constructor(
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
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

@ -12,11 +12,7 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogTempbasalBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider
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.interfaces.*
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback
@ -131,12 +127,12 @@ class TempBasalDialog : DialogFragmentWithDate() {
uel.log(Action.TEMP_BASAL, Sources.TempBasalDialog,
ValueWithUnit.Percent(percent),
ValueWithUnit.Minute(durationInMinutes))
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} else {
uel.log(Action.TEMP_BASAL, Sources.TempBasalDialog,
ValueWithUnit.Insulin(absolute),
ValueWithUnit.Minute(durationInMinutes))
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
}
})
}

View file

@ -20,8 +20,8 @@ import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
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.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventNewBG
@ -37,7 +37,6 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotifi
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
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.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -82,7 +81,6 @@ open class LoopPlugin @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val receiverStatusStore: ReceiverStatusStore,
private val fabricPrivacy: FabricPrivacy,
private val nsUpload: NSUpload,
private val dateUtil: DateUtil,
private val uel: UserEntryLogger,
private val repository: AppRepository,
@ -104,6 +102,7 @@ open class LoopPlugin @Inject constructor(
private var carbsSuggestionsSuspendedUntil: Long = 0
private var prevCarbsreq = 0
override var lastRun: LastRun? = null
override fun onStart() {
createNotificationChannel()
super.onStart()
@ -310,155 +309,154 @@ open class LoopPlugin @Inject constructor(
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
resultAfterConstraints.smb = 0.0
}
if (lastRun != null && lastRun!!.constraintsProcessed != null) {
prevCarbsreq = lastRun!!.constraintsProcessed!!.carbsReq
}
if (lastRun == null) lastRun = LastRun()
lastRun!!.request = apsResult
lastRun!!.constraintsProcessed = resultAfterConstraints
lastRun!!.lastAPSRun = DateUtil.now()
lastRun!!.source = (usedAPS as PluginBase).name
lastRun!!.tbrSetByPump = null
lastRun!!.smbSetByPump = null
lastRun!!.lastTBREnact = 0
lastRun!!.lastTBRRequest = 0
lastRun!!.lastSMBEnact = 0
lastRun!!.lastSMBRequest = 0
buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
}
prevCarbsreq = lastRun?.constraintsProcessed?.carbsReq ?: prevCarbsreq
lastRun = (lastRun ?: LastRun()).also { lastRun ->
lastRun.request = apsResult
lastRun.constraintsProcessed = resultAfterConstraints
lastRun.lastAPSRun = DateUtil.now()
lastRun.source = (usedAPS as PluginBase).name
lastRun.tbrSetByPump = null
lastRun.smbSetByPump = null
lastRun.lastTBREnact = 0
lastRun.lastTBRRequest = 0
lastRun.lastSMBEnact = 0
lastRun.lastSMBRequest = 0
buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
}
if (isSuspended) {
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended))
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)))
return
}
if (pump.isSuspended()) {
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.pumpsuspended))
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.pumpsuspended)))
return
}
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
if (closedLoopEnabled.value()) {
if (allowNotification) {
if (resultAfterConstraints.isCarbsRequired
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)) {
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
rxBus.send(EventNewNotification(carbReqLocal))
}
if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) {
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resultAfterConstraints.carbsRequiredText)).subscribe()
}
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
val intentAction5m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction5m.putExtra("ignoreDuration", 5)
val pendingIntent5m = PendingIntent.getBroadcast(context, 1, intentAction5m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore5m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m, "Ignore 5m"), pendingIntent5m)
val intentAction15m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction15m.putExtra("ignoreDuration", 15)
val pendingIntent15m = PendingIntent.getBroadcast(context, 1, intentAction15m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore15m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m, "Ignore 15m"), pendingIntent15m)
val intentAction30m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction30m.putExtra("ignoreDuration", 30)
val pendingIntent30m = PendingIntent.getBroadcast(context, 1, intentAction30m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore30m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m, "Ignore 30m"), pendingIntent30m)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(resourceHelper.gs(R.string.carbssuggestion))
.setContentText(resultAfterConstraints.carbsRequiredText)
.setAutoCancel(true)
.setPriority(Notification.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
.addAction(actionIgnore5m)
.addAction(actionIgnore15m)
.addAction(actionIgnore30m)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (isSuspended) {
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended))
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)))
return
}
if (pump.isSuspended()) {
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.pumpsuspended))
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.pumpsuspended)))
return
}
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
if (closedLoopEnabled.value()) {
if (allowNotification) {
if (resultAfterConstraints.isCarbsRequired
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)) {
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
rxBus.send(EventNewNotification(carbReqLocal))
}
if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) {
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resultAfterConstraints.carbsRequiredText)).subscribe()
}
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
val intentAction5m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction5m.putExtra("ignoreDuration", 5)
val pendingIntent5m = PendingIntent.getBroadcast(context, 1, intentAction5m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore5m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m, "Ignore 5m"), pendingIntent5m)
val intentAction15m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction15m.putExtra("ignoreDuration", 15)
val pendingIntent15m = PendingIntent.getBroadcast(context, 1, intentAction15m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore15m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m, "Ignore 15m"), pendingIntent15m)
val intentAction30m = Intent(context, CarbSuggestionReceiver::class.java)
intentAction30m.putExtra("ignoreDuration", 30)
val pendingIntent30m = PendingIntent.getBroadcast(context, 1, intentAction30m, PendingIntent.FLAG_UPDATE_CURRENT)
val actionIgnore30m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m, "Ignore 30m"), pendingIntent30m)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(resourceHelper.gs(R.string.carbssuggestion))
.setContentText(resultAfterConstraints.carbsRequiredText)
.setAutoCancel(true)
.setPriority(Notification.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
.addAction(actionIgnore5m)
.addAction(actionIgnore15m)
.addAction(actionIgnore30m)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// mId allows you to update the notification later on.
mNotificationManager.notify(Constants.notificationID, builder.build())
rxBus.send(EventNewOpenLoopNotification())
// mId allows you to update the notification later on.
mNotificationManager.notify(Constants.notificationID, builder.build())
rxBus.send(EventNewOpenLoopNotification())
//only send to wear if Native notifications are turned off
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
// Send to Wear
rxBus.send(EventWearInitiateAction("changeRequest"))
//only send to wear if Native notifications are turned off
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
// Send to Wear
rxBus.send(EventWearInitiateAction("changeRequest"))
}
}
} else {
//If carbs were required previously, but are no longer needed, dismiss notifications
if (prevCarbsreq > 0) {
dismissSuggestion()
rxBus.send(EventDismissNotification(Notification.CARBS_REQUIRED))
}
}
} else {
//If carbs were required previously, but are no longer needed, dismiss notifications
if (prevCarbsreq > 0) {
dismissSuggestion()
rxBus.send(EventDismissNotification(Notification.CARBS_REQUIRED))
}
}
}
if (resultAfterConstraints.isChangeRequested
&& !commandQueue.bolusInQueue()
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) {
val waiting = PumpEnactResult(injector)
waiting.queued = true
if (resultAfterConstraints.tempBasalRequested) lastRun!!.tbrSetByPump = waiting
if (resultAfterConstraints.bolusRequested) lastRun!!.smbSetByPump = waiting
rxBus.send(EventLoopUpdateGui())
fabricPrivacy.logCustom("APSRequest")
applyTBRRequest(resultAfterConstraints, profile, object : Callback() {
override fun run() {
if (result.enacted || result.success) {
lastRun!!.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
lastRun!!.lastTBREnact = DateUtil.now()
rxBus.send(EventLoopUpdateGui())
applySMBRequest(resultAfterConstraints, object : Callback() {
override fun run() {
// Callback is only called if a bolus was actually requested
if (result.enacted || result.success) {
lastRun!!.smbSetByPump = result
lastRun!!.lastSMBRequest = lastRun!!.lastAPSRun
lastRun!!.lastSMBEnact = DateUtil.now()
} else {
Thread {
SystemClock.sleep(1000)
invoke("tempBasalFallback", allowNotification, true)
}.start()
if (resultAfterConstraints.isChangeRequested
&& !commandQueue.bolusInQueue()
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) {
val waiting = PumpEnactResult(injector)
waiting.queued = true
if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
if (resultAfterConstraints.bolusRequested) lastRun.smbSetByPump = waiting
rxBus.send(EventLoopUpdateGui())
fabricPrivacy.logCustom("APSRequest")
applyTBRRequest(resultAfterConstraints, profile, object : Callback() {
override fun run() {
if (result.enacted || result.success) {
lastRun.tbrSetByPump = result
lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun.lastTBREnact = DateUtil.now()
rxBus.send(EventLoopUpdateGui())
applySMBRequest(resultAfterConstraints, object : Callback() {
override fun run() {
// Callback is only called if a bolus was actually requested
if (result.enacted || result.success) {
lastRun.smbSetByPump = result
lastRun.lastSMBRequest = lastRun.lastAPSRun
lastRun.lastSMBEnact = DateUtil.now()
} else {
Thread {
SystemClock.sleep(1000)
invoke("tempBasalFallback", allowNotification, true)
}.start()
}
rxBus.send(EventLoopUpdateGui())
}
rxBus.send(EventLoopUpdateGui())
}
})
} else {
lastRun!!.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
})
} else {
lastRun.tbrSetByPump = result
lastRun.lastTBRRequest = lastRun.lastAPSRun
}
rxBus.send(EventLoopUpdateGui())
}
rxBus.send(EventLoopUpdateGui())
}
})
} else {
lastRun!!.tbrSetByPump = null
lastRun!!.smbSetByPump = null
}
} else {
if (resultAfterConstraints.isChangeRequested && allowNotification) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
.setContentText(resultAfterConstraints.toString())
.setAutoCancel(true)
.setPriority(Notification.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (sp.getBoolean(R.string.key_wear_control, false)) {
builder.setLocalOnly(true)
})
} else {
lastRun.tbrSetByPump = null
lastRun.smbSetByPump = null
}
} else {
if (resultAfterConstraints.isChangeRequested && allowNotification) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
.setContentText(resultAfterConstraints.toString())
.setAutoCancel(true)
.setPriority(Notification.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (sp.getBoolean(R.string.key_wear_control, false)) {
builder.setLocalOnly(true)
}
presentSuggestion(builder)
} else if (allowNotification) {
dismissSuggestion()
}
presentSuggestion(builder)
} else if (allowNotification) {
dismissSuggestion()
}
rxBus.send(EventLoopUpdateGui())
}
rxBus.send(EventLoopUpdateGui())
} finally {
aapsLogger.debug(LTag.APS, "invoke end")
}
@ -501,24 +499,28 @@ open class LoopPlugin @Inject constructor(
}
fun acceptChangeRequest() {
val profile = profileFunction.getProfile()
applyTBRRequest(lastRun!!.constraintsProcessed, profile, object : Callback() {
override fun run() {
if (result.enacted) {
lastRun!!.tbrSetByPump = result
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
lastRun!!.lastTBREnact = DateUtil.now()
lastRun!!.lastOpenModeAccept = DateUtil.now()
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
val profile = profileFunction.getProfile() ?: return
lastRun?.let { lastRun ->
lastRun.constraintsProcessed?.let { constraintsProcessed ->
applyTBRRequest(constraintsProcessed, profile, object : Callback() {
override fun run() {
if (result.enacted) {
lastRun.tbrSetByPump = result
lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun.lastTBREnact = DateUtil.now()
lastRun.lastOpenModeAccept = DateUtil.now()
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction,
activePlugin.activePump, receiverStatusStore, runningConfiguration,
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
}
sp.incInt(R.string.key_ObjectivesmanualEnacts)
}
rxBus.send(EventAcceptOpenLoopChange())
}
sp.incInt(R.string.key_ObjectivesmanualEnacts)
}
rxBus.send(EventAcceptOpenLoopChange())
})
}
})
}
fabricPrivacy.logCustom("AcceptTemp")
}
@ -526,8 +528,8 @@ open class LoopPlugin @Inject constructor(
* expect absolute request and allow both absolute and percent response based on pump capabilities
* TODO: update pump drivers to support APS request in %
*/
private fun applyTBRRequest(request: APSResult?, profile: Profile?, callback: Callback?) {
if (!request!!.tempBasalRequested) {
private fun applyTBRRequest(request: APSResult, profile: Profile, callback: Callback?) {
if (!request.tempBasalRequested) {
callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(R.string.nochangerequested))?.run()
return
}
@ -566,7 +568,7 @@ open class LoopPlugin @Inject constructor(
uel.log(Action.TEMP_BASAL, Sources.Loop,
ValueWithUnit.Percent(request.percent),
ValueWithUnit.Minute(request.duration))
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile!!, callback)
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
}
} else {
if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) {
@ -589,7 +591,7 @@ open class LoopPlugin @Inject constructor(
uel.log(Action.TEMP_BASAL, Sources.Loop,
ValueWithUnit.UnitPerHour(request.rate),
ValueWithUnit.Minute(request.duration))
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile!!, callback)
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
}
}
}
@ -640,7 +642,7 @@ open class LoopPlugin @Inject constructor(
val pump = activePlugin.activePump
disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L)
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() {
if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
@ -648,7 +650,7 @@ open class LoopPlugin @Inject constructor(
}
})
} 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() {
if (!result.success) {
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 {
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: 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<*>
for (pdu in pdus) {
val message = SmsMessage.createFromPdu(pdu as ByteArray, format)
@ -636,7 +637,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasalPct, duration) {
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() {
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)
@ -678,7 +679,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasal, duration) {
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() {
if (result.success) {
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 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)
result.success = false
result.comment = resourceHelper.gs(R.string.pumperror)
@ -101,7 +101,7 @@ class MDIPlugin @Inject constructor(
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)
result.success = false
result.comment = resourceHelper.gs(R.string.pumperror)

View file

@ -222,7 +222,7 @@ open class VirtualPumpPlugin @Inject constructor(
}
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)
.date(System.currentTimeMillis())
.absolute(absoluteRate)
@ -242,7 +242,7 @@ open class VirtualPumpPlugin @Inject constructor(
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)
.date(System.currentTimeMillis())
.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.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -280,7 +281,7 @@ open class CommandQueue @Inject constructor(
}
// 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)) {
callback?.result(executingNowError())?.run()
return false
@ -289,13 +290,13 @@ open class CommandQueue @Inject constructor(
removeAll(CommandType.TEMPBASAL)
val rateAfterConstraints = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
// add new command to queue
add(CommandTempBasalAbsolute(injector, rateAfterConstraints, durationInMinutes, enforceNew, profile, callback))
add(CommandTempBasalAbsolute(injector, rateAfterConstraints, durationInMinutes, enforceNew, profile, tbrType, callback))
notifyAboutNewCommand()
return true
}
// 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)) {
callback?.result(executingNowError())?.run()
return false
@ -304,7 +305,7 @@ open class CommandQueue @Inject constructor(
removeAll(CommandType.TEMPBASAL)
val percentAfterConstraints = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value()
// add new command to queue
add(CommandTempBasalPercent(injector, percentAfterConstraints, durationInMinutes, enforceNew, profile, callback))
add(CommandTempBasalPercent(injector, percentAfterConstraints, durationInMinutes, enforceNew, profile, tbrType, callback))
notifyAboutNewCommand()
return true
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.queue.Callback
import javax.inject.Inject
@ -13,13 +14,14 @@ class CommandTempBasalAbsolute(
private val durationInMinutes: Int,
private val enforceNew: Boolean,
private val profile: Profile,
private val tbrType: PumpSync.TemporaryBasalType,
callback: Callback?
) : Command(injector, CommandType.TEMPBASAL, callback) {
@Inject lateinit var activePlugin: ActivePluginProvider
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}")
callback?.result(r)?.run()
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.queue.Callback
import javax.inject.Inject
@ -13,13 +14,14 @@ class CommandTempBasalPercent(
private val durationInMinutes: Int,
private val enforceNew: Boolean,
private val profile: Profile,
private val tbrType: PumpSync.TemporaryBasalType,
callback: Callback?
) : Command(injector, CommandType.TEMPBASAL, callback) {
@Inject lateinit var activePlugin: ActivePluginProvider
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}")
callback?.result(r)?.run()
}

View file

@ -381,7 +381,7 @@ class BolusWizard @Inject constructor(
}
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() {
if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), R.raw.boluserror)
@ -389,7 +389,7 @@ class BolusWizard @Inject constructor(
}
})
} else {
commandQueue.tempBasalPercent(0, 120, true, profile, object : Callback() {
commandQueue.tempBasalPercent(0, 120, true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() {
if (!result.success) {
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.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
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?)
*/
@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.");
int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
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
*/
@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);
}

View file

@ -22,8 +22,8 @@ interface CommandQueueProvider {
fun stopPump(callback: Callback?)
fun startPump(callback: Callback?)
fun setTBROverNotification(callback: Callback?, enable: Boolean)
fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean
fun tempBasalPercent(percent: Int, 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, tbrType: PumpSync.TemporaryBasalType, callback: Callback?): Boolean
fun extendedBolus(insulin: Double, durationInMinutes: Int, callback: Callback?): Boolean
fun cancelTempBasal(enforceNew: Boolean, 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.
* 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.
*/
@ -46,22 +46,95 @@ interface PumpInterface {
*
* @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.
* @return 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 setExtendedBolus(insulin: Double, durationInMinutes: Int): 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
/**
* Manufacturer type. Usually defined by used plugin
*
* @return 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
/**
* Serial number
*
* Real serial number from device or "unique" generated for paired pump if not possible
*/
fun serialNumber(): String
// Pump capabilities

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TemporaryBasal
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:
*
@ -20,6 +21,11 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
* bolus.
*/
interface PumpSync {
/*
* BOLUSES & CARBS
*/
/**
* Create bolus with temporary id
*
@ -42,7 +48,7 @@ interface PumpSync {
* @param pumpSerial pump serial number
* @return true if new record is created
**/
fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String) : Boolean
fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of boluses with temporary id
@ -66,7 +72,7 @@ interface PumpSync {
* @param pumpSerial pump serial number
* @return true if record is successfully updated
**/
fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String) : Boolean
fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of boluses
@ -85,7 +91,7 @@ interface PumpSync {
* @param pumpSerial pump serial number
* @return true if new record is created
**/
fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String) : Boolean
fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of carbs
@ -103,7 +109,11 @@ interface PumpSync {
* @param pumpSerial pump serial number
* @return true if new record is created
**/
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
@ -139,4 +149,69 @@ interface PumpSync {
* @param pumpSerial pump serial number
**/
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.entities.Bolus
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.transactions.*
import info.nightscout.androidaps.interfaces.PumpSync
@ -22,7 +23,7 @@ class PumpSyncImplementation @Inject constructor(
private val disposable = CompositeDisposable()
override fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String) : Boolean {
override fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean {
val bolus = Bolus(
timestamp = timestamp,
amount = amount,
@ -34,10 +35,10 @@ class PumpSyncImplementation @Inject constructor(
)
)
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()
.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
}
}
@ -55,10 +56,10 @@ class PumpSyncImplementation @Inject constructor(
)
)
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()
.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
}
}
@ -75,11 +76,11 @@ class PumpSyncImplementation @Inject constructor(
)
)
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()
.also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated carbs $it") }
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") }
return result.inserted.size > 0
}
}
@ -130,4 +131,42 @@ class PumpSyncImplementation @Inject constructor(
.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
@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
//This should not be needed while using queue because connection should be done before calling this
PumpEnactResult result = new PumpEnactResult(getInjector());
@ -281,7 +281,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
}
// Convert duration from minutes to hours
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) {
// Check if some temp is already in progress

View file

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

View file

@ -218,7 +218,7 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
}
@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;
PumpEnactResult result = new PumpEnactResult(getInjector());
percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value();

View file

@ -205,7 +205,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// This is called from APS
@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
//This should not be needed while using queue because connection should be done before calling this
PumpEnactResult result = new PumpEnactResult(getInjector());
@ -273,7 +273,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
}
// Convert duration from minutes to hours
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) {
// 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
detailedBolusInfo.carbTime = 0
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
if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService?.bolus(detailedBolusInfo.insulin, carbs.toInt(), DateUtil.now() + T.mins(carbTime.toLong()).msecs(), t)
?: false
@ -315,7 +315,7 @@ class DanaRSPlugin @Inject constructor(
// This is called from APS
@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)
val absoluteAfterConstrain = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
val doTempOff = baseBasalRate - absoluteAfterConstrain == 0.0
@ -367,7 +367,7 @@ class DanaRSPlugin @Inject constructor(
// Convert duration from minutes to hours
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $percentRate% for $durationInMinutes minutes (doLowTemp || doHighTemp)")
result = if (percentRate == 0 && durationInMinutes > 30) {
setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew)
setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew, tbrType)
} else {
// use special APS temp basal call ... 100+/15min .... 100-/30min
setHighTempBasalPercent(percentRate)
@ -387,7 +387,7 @@ class DanaRSPlugin @Inject constructor(
}
@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)
var percentAfterConstraint = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value()
if (percentAfterConstraint < 0) {

View file

@ -5,7 +5,6 @@ import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_TEMPORARY_BASALS
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TemporaryBasal
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.Single
@ -18,4 +17,43 @@ internal interface TemporaryBasalDao : TraceableDao<TemporaryBasal> {
@Query("DELETE FROM $TABLE_TEMPORARY_BASALS")
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,
@Embedded
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 utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
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
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());
if (activeBasalRate == null) return result;
if (activeBasalRate.getActiveBasalRate() == 0) return result;
@ -722,13 +722,13 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
result.comment(cancelTBRResult.getComment());
}
} else {
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew);
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew, tbrType);
}
} else {
result.comment(cancelEBResult.getComment());
}
} else {
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew);
return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew, tbrType);
}
try {
fetchStatus();
@ -744,7 +744,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
}
@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());
percent = (int) Math.round(((double) percent) / 10d) * 10;
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.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
@ -247,14 +248,14 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
@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.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@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.");
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.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
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 false and the same rate is requested enacted=false and success=true is returned and TBR is not changed
@NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile,
boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
setRefreshButtonEnabled(false);
@ -1064,14 +1064,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@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) {
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew);
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew, tbrType);
} else {
double absoluteValue = profile.getBasal() * (percent / 100.0d);
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.");
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;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
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.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
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;
}
@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;
}

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
@Override
@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);
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.");
}
@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) {
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew);
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew, tbrType);
} else {
double absoluteValue = profile.getBasal() * (percent / 100.0d);
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.");
return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew);
return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType);
}
}