DetailedBolusInfo, MealLink UI

This commit is contained in:
Milos Kozak 2021-03-25 17:48:07 +01:00
parent 616871c95c
commit 7f0fe881b6
94 changed files with 1741 additions and 1358 deletions

View file

@ -111,7 +111,7 @@ android {
defaultConfig { defaultConfig {
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
version "2.8.2.1-dev-e" version "2.8.2.1-dev-e1"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -1,14 +1,12 @@
package info.nightscout.androidaps.db package info.nightscout.androidaps.db
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.events.EventFoodDatabaseChanged import info.nightscout.androidaps.events.EventFoodDatabaseChanged
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.events.EventTempTargetChange import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.events.EventTherapyEventChange 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
@ -50,5 +48,13 @@ class CompatDBHelper @Inject constructor(
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged") aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventFoodDatabaseChanged()) rxBus.send(EventFoodDatabaseChanged())
} }
it.filterIsInstance<Carbs>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventTreatmentChange(null))
}
it.filterIsInstance<Bolus>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventTreatmentChange(null))
}
} }
} }

View file

@ -66,7 +66,7 @@ abstract class FragmentsModule {
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment @ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment @ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsMealLinkFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment @ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -8,13 +9,15 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Units
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogCarbsBinding import info.nightscout.androidaps.databinding.DialogCarbsBinding
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
@ -24,8 +27,9 @@ import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.utils.extensions.formatColor
@ -40,7 +44,7 @@ import kotlin.math.max
class CarbsDialog : DialogFragmentWithDate() { class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@ -48,9 +52,9 @@ class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var carbsGenerator: CarbsGenerator
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer @Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var commandQueue: CommandQueue
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
companion object { companion object {
@ -76,15 +80,15 @@ class CarbsDialog : DialogFragmentWithDate() {
val time = binding.time.value.toInt() val time = binding.time.value.toInt()
if (time > 12 * 60 || time < -12 * 60) { if (time > 12 * 60 || time < -12 * 60) {
binding.time.value = 0.0 binding.time.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.constraintapllied))
} }
if (binding.duration.value > 10) { if (binding.duration.value > 10) {
binding.duration.value = 0.0 binding.duration.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.constraintapllied))
} }
if (binding.carbs.value.toInt() > maxCarbs) { if (binding.carbs.value.toInt() > maxCarbs) {
binding.carbs.value = 0.0 binding.carbs.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.carbsconstraintapplied))
} }
} }
@ -270,13 +274,39 @@ class CarbsDialog : DialogFragmentWithDate() {
} }
} }
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
if (duration == 0) { val detailedBolusInfo = DetailedBolusInfo()
carbsGenerator.createCarb(carbsAfterConstraints, time, TherapyEvent.Type.CARBS_CORRECTION, notes) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
detailedBolusInfo.context = context
detailedBolusInfo.notes = notes
detailedBolusInfo.carbsDuration = T.mins(duration.toLong()).msecs()
if (duration != 0 || timeOffset != 0) {
detailedBolusInfo.carbsTimestamp = time
disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction())
.subscribe({ result ->
result.inserted.forEach {
uel.log(Action.CARBS, notes,
ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged),
ValueWithUnit(carbsAfterConstraints, Units.G),
ValueWithUnit(timeOffset, Units.M, timeOffset != 0),
ValueWithUnit(duration, Units.H, duration != 0)
)
nsUpload.uploadMealLinkRecord(it)
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it)
})
} else { } else {
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes) commandQueue.bolus(detailedBolusInfo, object : Callback() {
nsUpload.uploadEvent(TherapyEvent.Type.NOTE.text, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset)) override fun run() {
if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror)
} else
uel.log(Action.BOLUS, notes, ValueWithUnit(carbsAfterConstraints, Units.G))
}
})
} }
uel.log(Action.CARBS, notes, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(carbsAfterConstraints, Units.G), ValueWithUnit(timeOffset, Units.M, timeOffset != 0), ValueWithUnit(duration, Units.H, duration != 0))
} }
if (useAlarm && carbs > 0 && timeOffset > 0) { if (useAlarm && carbs > 0 && timeOffset > 0) {
carbTimer.scheduleReminder(dateUtil._now() + T.mins(timeOffset.toLong()).msecs()) carbTimer.scheduleReminder(dateUtil._now() + T.mins(timeOffset.toLong()).msecs())

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -10,13 +11,14 @@ import androidx.annotation.StringRes
import com.google.common.base.Joiner import com.google.common.base.Joiner
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
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.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Units
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogCareBinding import info.nightscout.androidaps.databinding.DialogCareBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -38,7 +40,7 @@ import javax.inject.Inject
class CareDialog : DialogFragmentWithDate() { class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var injector: HasAndroidInjector @Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload

View file

@ -10,7 +10,6 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Units import info.nightscout.androidaps.database.entities.UserEntry.Units
@ -183,7 +182,7 @@ class FillDialog : DialogFragmentWithDate() {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = insulin detailedBolusInfo.insulin = insulin
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.bolusType = Bolus.Type.PRIMING detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {

View file

@ -16,7 +16,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Units import info.nightscout.androidaps.database.entities.UserEntry.Units
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
@ -206,22 +205,32 @@ class InsulinDialog : DialogFragmentWithDate() {
} }
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
if (recordOnlyChecked) { if (recordOnlyChecked) {
uel.log(Action.BOLUS_RECORD, notes, ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(timeOffset, Units.M, timeOffset != 0)) detailedBolusInfo.bolusTimestamp = time
detailedBolusInfo.timestamp = time disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction())
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) .subscribe({ result ->
result.inserted.forEach {
uel.log(Action.BOLUS_RECORD, notes,
ValueWithUnit(it.bolus?.amount ?: 0.0, Units.U),
ValueWithUnit(timeOffset, Units.M, timeOffset != 0)
)
nsUpload.uploadMealLinkRecord(it)
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it)
})
} else { } else {
uel.log(Action.BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U))
detailedBolusInfo.timestamp = DateUtil.now()
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
} } else
uel.log(Action.BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U))
} }
}) })
} }

View file

@ -12,7 +12,7 @@ import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Units import info.nightscout.androidaps.database.entities.UserEntry.Units
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
@ -20,8 +20,10 @@ import info.nightscout.androidaps.databinding.DialogTreatmentBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider 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.logging.LTag
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.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
@ -30,6 +32,8 @@ import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -44,6 +48,10 @@ class TreatmentDialog : DialogFragmentWithDate() {
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {} override fun afterTextChanged(s: Editable) {}
@ -131,10 +139,9 @@ class TreatmentDialog : DialogFragmentWithDate() {
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) { if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.TREATMENT, ValueWithUnit(insulin, Units.U, insulin != 0.0), ValueWithUnit(carbs, Units.G, carbs != 0))
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = TherapyEvent.Type.CARBS_CORRECTION if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CARBS_CORRECTION
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble() detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
detailedBolusInfo.context = context detailedBolusInfo.context = context
@ -143,11 +150,27 @@ class TreatmentDialog : DialogFragmentWithDate() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
} } else
uel.log(Action.TREATMENT,
ValueWithUnit(insulin, Units.U, insulin != 0.0),
ValueWithUnit(carbs, Units.G, carbs != 0)
)
} }
}) })
} else } else {
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction())
.subscribe({ result ->
result.inserted.forEach {
uel.log(Action.TREATMENT,
ValueWithUnit(insulin, Units.U, insulin != 0.0),
ValueWithUnit(carbs, Units.G, carbs != 0)
)
nsUpload.uploadMealLinkRecord(it)
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it)
})
}
}) })
} }
} else } else

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -16,7 +17,6 @@ import androidx.fragment.app.FragmentManager
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
@ -32,7 +32,11 @@ import info.nightscout.androidaps.logging.LTag
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.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.extensions.valueToUnits import info.nightscout.androidaps.utils.extensions.valueToUnits
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -51,7 +55,7 @@ class WizardDialog : DaggerDialogFragment() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -180,7 +184,7 @@ class WizardDialog : DaggerDialogFragment() {
// profile spinner // profile spinner
binding.profile.onItemSelectedListener = object : OnItemSelectedListener { binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofileselected))
binding.ok.visibility = View.GONE binding.ok.visibility = View.GONE
} }
@ -245,7 +249,7 @@ class WizardDialog : DaggerDialogFragment() {
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileInterface.profile
if (profile == null || profileStore == null) { if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofile)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile))
dismiss() dismiss()
return return
} }
@ -309,7 +313,7 @@ class WizardDialog : DaggerDialogFragment() {
val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
if (abs(carbs - carbsAfterConstraint) > 0.01) { if (abs(carbs - carbsAfterConstraint) > 0.01) {
binding.carbsInput.value = 0.0 binding.carbsInput.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.carbsconstraintapplied))
return return
} }
@ -326,8 +330,8 @@ class WizardDialog : DaggerDialogFragment() {
val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text) val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text)
wizard = BolusWizard(mainApp).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, wizard = BolusWizard(injector).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble(), sp.getInt(R.string.key_boluswizard_percentage, 100),
binding.bgcheckbox.isChecked, binding.bgcheckbox.isChecked,
binding.cobcheckbox.isChecked, binding.cobcheckbox.isChecked,
binding.bolusiobcheckbox.isChecked, binding.bolusiobcheckbox.isChecked,

View file

@ -9,12 +9,12 @@ import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.databinding.DialogWizardinfoBinding import info.nightscout.androidaps.databinding.DialogWizardinfoBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
class WizardInfoDialog : DaggerDialogFragment() { class WizardInfoDialog : DaggerDialogFragment() {
@ -22,10 +22,12 @@ class WizardInfoDialog : DaggerDialogFragment() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
private var json: JSONObject? = null private lateinit var data: BolusCalculatorResult
private lateinit var notes: String
fun setData(json: JSONObject) { fun setData(bolusCalculatorResult: BolusCalculatorResult, notes: String) {
this.json = json this.data = bolusCalculatorResult
this.notes = notes
} }
private var _binding: DialogWizardinfoBinding? = null private var _binding: DialogWizardinfoBinding? = null
@ -49,44 +51,42 @@ class WizardInfoDialog : DaggerDialogFragment() {
binding.close.setOnClickListener { dismiss() } binding.close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val bgString = val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "bg"))
else DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg"))
// BG // BG
binding.bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf")) binding.bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, data.isf)
binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg")) binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.glucoseInsulin)
binding.bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused") binding.bgcheckbox.isChecked = data.wasGlucoseUsed
binding.ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused") binding.ttcheckbox.isChecked = data.wasTempTargetUsed
// Trend // Trend
binding.bgtrend.text = JsonHelper.safeGetString(json, "trend") binding.bgtrend.text = DecimalFormatter.to1Decimal(data.glucoseTrend)
binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend")) binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.trendInsulin)
binding.bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused") binding.bgtrendcheckbox.isChecked = data.wasTrendUsed
// COB // COB
binding.cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic")) binding.cob.text = resourceHelper.gs(R.string.format_cob_ic, data.cob, data.ic)
binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob")) binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.cobInsulin)
binding.cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused") binding.cobcheckbox.isChecked = data.wasCOBUsed
// Bolus IOB // Bolus IOB
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob")) binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.bolusIOB)
binding.bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused") binding.bolusiobcheckbox.isChecked = data.wasBolusIOBUsed
// Basal IOB // Basal IOB
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob")) binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.basalIOB)
binding.basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused") binding.basaliobcheckbox.isChecked = data.wasBasalIOBUsed
// Superbolus // Superbolus
binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus")) binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.superbolusInsulin)
binding.sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused") binding.sbcheckbox.isChecked = data.wasSuperbolusUsed
// Carbs // Carbs
binding.carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic")) binding.carbs.text = resourceHelper.gs(R.string.format_carbs_ic, data.carbs, data.ic)
binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs")) binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.carbsInsulin)
// Correction // Correction
binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection")) binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.otherCorrection)
// Profile // Profile
binding.profile.text = JsonHelper.safeGetString(json, "profile") binding.profile.text = data.profileName
// Notes // Notes
binding.notes.text = JsonHelper.safeGetString(json, "notes") binding.notes.text = notes
// Percentage // Percentage
binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, (JsonHelper.safeGetInt(json, "percentageCorrection", 100))) binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, data.percentageCorrection)
// Total // Total
binding.totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin")) binding.totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.totalInsulin)
} }
override fun onStart() { override fun onStart() {

View file

@ -16,7 +16,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile 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.Bolus
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
@ -596,9 +595,9 @@ open class LoopPlugin @Inject constructor(
// deliver SMB // deliver SMB
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.lastBolusTime detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.lastBolusTime
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = request.smb detailedBolusInfo.insulin = request.smb
detailedBolusInfo.bolusType = Bolus.Type.SMB detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.SMB
detailedBolusInfo.deliverAtTheLatest = request.deliverAt detailedBolusInfo.deliverAtTheLatest = request.deliverAt
aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()") aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()")
commandQueue.bolus(detailedBolusInfo, callback) commandQueue.bolus(detailedBolusInfo, callback)

View file

@ -124,7 +124,7 @@ class SafetyPlugin @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
// check for pump max // check for pump max
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this) absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
} }
@ -147,7 +147,7 @@ class SafetyPlugin @Inject constructor(
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
percentRate[aapsLogger, percentRateAfterConst, String.format(resourceHelper.gs(R.string.limitingpercentrate), percentRateAfterConst, resourceHelper.gs(R.string.pumplimit))] = this percentRate[aapsLogger, percentRateAfterConst, String.format(resourceHelper.gs(R.string.limitingpercentrate), percentRateAfterConst, resourceHelper.gs(R.string.pumplimit))] = this
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this) percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
} }
return percentRate return percentRate

View file

@ -643,7 +643,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
pump.isSuspended() -> { pump.isSuspended() -> {
binding.infoLayout.apsMode.setImageResource(if (pump.model() == PumpType.Omnipod_Eros || pump.model() == PumpType.Omnipod_Dash) { binding.infoLayout.apsMode.setImageResource(if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended. // For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab // The only way to 'reconnect' it, is through the Omnipod tab
R.drawable.ic_loop_disconnected R.drawable.ic_loop_disconnected

View file

@ -43,7 +43,7 @@ class StatusLightHandler @Inject constructor(
handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0) handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0)
} }
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
if (pump.model() == PumpType.Omnipod_Eros || pump.model() == PumpType.Omnipod_Dash) { if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U")
} else { } else {
handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U")
@ -55,15 +55,15 @@ class StatusLightHandler @Inject constructor(
} }
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
if (pump.model() == PumpType.Omnipod_Dash) { if (pump.model() == PumpType.OMNIPOD_DASH) {
// Omnipod Dash does not report its battery level // Omnipod Dash does not report its battery level
careportal_battery_level?.text = resourceHelper.gs(R.string.notavailable) careportal_battery_level?.text = resourceHelper.gs(R.string.notavailable)
careportal_battery_level?.setTextColor(Color.WHITE) careportal_battery_level?.setTextColor(Color.WHITE)
} else if (pump.model() == PumpType.Omnipod_Eros && pump is OmnipodErosPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below } else if (pump.model() == PumpType.OMNIPOD_EROS && pump is OmnipodErosPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below
// The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do. // The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do.
// Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a" // Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a"
handleOmnipodErosBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel) handleOmnipodErosBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel)
} else if (pump.model() != PumpType.AccuChekCombo) { } else if (pump.model() != PumpType.ACCU_CHEK_COMBO) {
handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%") handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%")
} }
} }

View file

@ -637,7 +637,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}) })
} else if (divided[1].endsWith("%")) { } else if (divided[1].endsWith("%")) {
var tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(divided[1], "%")) var tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(divided[1], "%"))
val durationStep = activePlugin.activePump.model().tbrSettings.durationStep val durationStep = activePlugin.activePump.model().tbrSettings?.durationStep ?: 60
var duration = 30 var duration = 30
if (divided.size > 2) duration = SafeParse.stringToInt(divided[2]) if (divided.size > 2) duration = SafeParse.stringToInt(divided[2])
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
@ -674,7 +674,7 @@ class SmsCommunicatorPlugin @Inject constructor(
} }
} else { } else {
var tempBasal = SafeParse.stringToDouble(divided[1]) var tempBasal = SafeParse.stringToDouble(divided[1])
val durationStep = activePlugin.activePump.model().tbrSettings.durationStep val durationStep = activePlugin.activePump.model().tbrSettings?.durationStep ?: 60
var duration = 30 var duration = 30
if (divided.size > 2) duration = SafeParse.stringToInt(divided[2]) if (divided.size > 2) duration = SafeParse.stringToInt(divided[2])
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()

View file

@ -4,7 +4,6 @@ import android.content.Context
import android.os.PowerManager import android.os.PowerManager
import android.os.SystemClock import android.os.SystemClock
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -17,8 +16,8 @@ import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReply
import info.nightscout.androidaps.plugins.general.tidepool.messages.OpenDatasetRequestMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.OpenDatasetRequestMessage
import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
@ -34,7 +33,7 @@ import javax.inject.Singleton
class TidepoolUploader @Inject constructor( class TidepoolUploader @Inject constructor(
private val aapsLogger: AAPSLogger, private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val mainApp: MainApp, private val ctx: Context,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val uploadChunk: UploadChunk, private val uploadChunk: UploadChunk,
@ -45,6 +44,7 @@ class TidepoolUploader @Inject constructor(
private var wl: PowerManager.WakeLock? = null private var wl: PowerManager.WakeLock? = null
companion object { companion object {
private const val INTEGRATION_BASE_URL = "https://int-api.tidepool.org" private const val INTEGRATION_BASE_URL = "https://int-api.tidepool.org"
private const val PRODUCTION_BASE_URL = "https://api.tidepool.org" private const val PRODUCTION_BASE_URL = "https://api.tidepool.org"
internal const val VERSION = "0.0.1" internal const val VERSION = "0.0.1"
@ -285,7 +285,7 @@ class TidepoolUploader @Inject constructor(
@Synchronized @Synchronized
private fun extendWakeLock(ms: Long) { private fun extendWakeLock(ms: Long) {
if (wl == null) { if (wl == null) {
val pm = mainApp.getSystemService(Context.POWER_SERVICE) as PowerManager val pm = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:TidepoolUploader") wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:TidepoolUploader")
wl?.acquire(ms) wl?.acquire(ms)
} else { } else {

View file

@ -15,9 +15,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.interfaces.end import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
@ -33,7 +31,6 @@ import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAc
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.extensions.valueToUnits import info.nightscout.androidaps.utils.extensions.valueToUnits
@ -77,7 +74,6 @@ class ActionStringHandler @Inject constructor(
private val danaRv2Plugin: DanaRv2Plugin, private val danaRv2Plugin: DanaRv2Plugin,
private val danaRSPlugin: DanaRSPlugin, private val danaRSPlugin: DanaRSPlugin,
private val danaPump: DanaPump, private val danaPump: DanaPump,
private val carbsGenerator: CarbsGenerator,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val config: Config, private val config: Config,
private val databaseHelper: DatabaseHelperInterface, private val databaseHelper: DatabaseHelperInterface,
@ -221,7 +217,7 @@ class ActionStringHandler @Inject constructor(
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget, val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget,
carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()), carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()),
0.0, percentage.toDouble(), useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false) 0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) {
sendError("Insulin constraint violation!" + sendError("Insulin constraint violation!" +
"\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!") "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!")
@ -516,13 +512,13 @@ class ActionStringHandler @Inject constructor(
generateTempTarget(duration, low, high) generateTempTarget(duration, low, high)
} else if ("wizard2" == act[0]) { } else if ("wizard2" == act[0]) {
if (lastBolusWizard != null) { //use last calculation as confirmed string matches if (lastBolusWizard != null) { //use last calculation as confirmed string matches
doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs) doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs, null, 0)
lastBolusWizard = null lastBolusWizard = null
} }
} else if ("bolus" == act[0]) { } else if ("bolus" == act[0]) {
val insulin = SafeParse.stringToDouble(act[1]) val insulin = SafeParse.stringToDouble(act[1])
val carbs = SafeParse.stringToInt(act[2]) val carbs = SafeParse.stringToInt(act[2])
doBolus(insulin, carbs) doBolus(insulin, carbs, null, 0)
} else if ("cppset" == act[0]) { } else if ("cppset" == act[0]) {
val timeshift = SafeParse.stringToInt(act[1]) val timeshift = SafeParse.stringToInt(act[1])
val percentage = SafeParse.stringToInt(act[2]) val percentage = SafeParse.stringToInt(act[2])
@ -542,16 +538,6 @@ class ActionStringHandler @Inject constructor(
lastBolusWizard = null lastBolusWizard = null
} }
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
if (carbs > 0) {
if (duration == 0) {
carbsGenerator.createCarb(carbs, time, TherapyEvent.Type.CARBS_CORRECTION, "watch")
} else {
carbsGenerator.generateCarbs(carbs, time, duration, "watch eCarbs")
}
}
}
private fun setCPP(timeshift: Int, percentage: Int) { private fun setCPP(timeshift: Int, percentage: Int) {
var msg = "" var msg = ""
//check for validity //check for validity
@ -604,7 +590,7 @@ class ActionStringHandler @Inject constructor(
private fun doFillBolus(amount: Double) { private fun doFillBolus(amount: Double) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = amount detailedBolusInfo.insulin = amount
detailedBolusInfo.bolusType = Bolus.Type.PRIMING detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -616,13 +602,19 @@ class ActionStringHandler @Inject constructor(
}) })
} }
private fun doBolus(amount: Double, carbs: Int) { private fun doECarbs(carbs: Int, time: Long, duration: Int) {
doBolus(0.0, carbs, time, duration)
}
private fun doBolus(amount: Double, carbs: Int, carbsTime: Long?, carbsDuration: Int) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = amount detailedBolusInfo.insulin = amount
detailedBolusInfo.carbs = carbs.toDouble() detailedBolusInfo.carbs = carbs.toDouble()
detailedBolusInfo.bolusType = Bolus.Type.NORMAL detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.NORMAL
detailedBolusInfo.carbsTimestamp = carbsTime
detailedBolusInfo.carbsDuration = carbsDuration.toLong()
val storesCarbs = activePlugin.activePump.pumpDescription.storesCarbInfo val storesCarbs = activePlugin.activePump.pumpDescription.storesCarbInfo
if (detailedBolusInfo.insulin > 0 || storesCarbs) { if (detailedBolusInfo.insulin > 0 || (storesCarbs && carbsDuration == 0)) {
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {

View file

@ -1,9 +1,9 @@
package info.nightscout.androidaps.plugins.general.wear package info.nightscout.androidaps.plugins.general.wear
import android.content.Context
import android.content.Intent import android.content.Intent
import dagger.Lazy import dagger.Lazy
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
@ -16,7 +16,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -32,7 +31,7 @@ class WearPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val aapsSchedulers: AapsSchedulers, private val aapsSchedulers: AapsSchedulers,
private val sp: SP, private val sp: SP,
private val mainApp: MainApp, private val ctx: Context,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val loopPlugin: Lazy<LoopPlugin>, private val loopPlugin: Lazy<LoopPlugin>,
private val rxBus: RxBusWrapper private val rxBus: RxBusWrapper
@ -96,10 +95,10 @@ class WearPlugin @Inject constructor(
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ event: EventBolusRequested -> .subscribe({ event: EventBolusRequested ->
val status = String.format(resourceHelper.gs(R.string.bolusrequested), event.amount) val status = String.format(resourceHelper.gs(R.string.bolusrequested), event.amount)
val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
intent.putExtra("progresspercent", 0) intent.putExtra("progresspercent", 0)
intent.putExtra("progressstatus", status) intent.putExtra("progressstatus", status)
mainApp.startService(intent) ctx.startService(intent)
}, fabricPrivacy::logException)) }, fabricPrivacy::logException))
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventDismissBolusProgressIfRunning::class.java) .toObservable(EventDismissBolusProgressIfRunning::class.java)
@ -111,20 +110,20 @@ class WearPlugin @Inject constructor(
} else { } else {
resourceHelper.gs(R.string.nosuccess) resourceHelper.gs(R.string.nosuccess)
} }
val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
intent.putExtra("progresspercent", 100) intent.putExtra("progresspercent", 100)
intent.putExtra("progressstatus", status) intent.putExtra("progressstatus", status)
mainApp.startService(intent) ctx.startService(intent)
}, fabricPrivacy::logException)) }, fabricPrivacy::logException))
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventOverviewBolusProgress::class.java) .toObservable(EventOverviewBolusProgress::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ event: EventOverviewBolusProgress -> .subscribe({ event: EventOverviewBolusProgress ->
if (!event.isSMB() || sp.getBoolean("wear_notifySMB", true)) { if (!event.isSMB() || sp.getBoolean("wear_notifySMB", true)) {
val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
intent.putExtra("progresspercent", event.percent) intent.putExtra("progresspercent", event.percent)
intent.putExtra("progressstatus", event.status) intent.putExtra("progressstatus", event.status)
mainApp.startService(intent) ctx.startService(intent)
} }
}, fabricPrivacy::logException)) }, fabricPrivacy::logException))
} }
@ -139,47 +138,47 @@ class WearPlugin @Inject constructor(
if (isEnabled(getType())) { if (isEnabled(getType())) {
// only start service when this plugin is enabled // only start service when this plugin is enabled
if (bgValue) { if (bgValue) {
mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java)) ctx.startService(Intent(ctx, WatchUpdaterService::class.java))
} }
if (basals) { if (basals) {
mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BASALS)) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BASALS))
} }
if (status) { if (status) {
mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_STATUS)) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_STATUS))
} }
} }
} }
fun resendDataToWatch() { fun resendDataToWatch() {
//Log.d(TAG, "WR: WearPlugin:resendDataToWatch"); //Log.d(TAG, "WR: WearPlugin:resendDataToWatch");
mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND)) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND))
} }
fun openSettings() { fun openSettings() {
//Log.d(TAG, "WR: WearPlugin:openSettings"); //Log.d(TAG, "WR: WearPlugin:openSettings");
mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS)) ctx.startService(Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS))
} }
fun requestNotificationCancel(actionString: String?) { //Log.d(TAG, "WR: WearPlugin:requestNotificationCancel"); fun requestNotificationCancel(actionString: String?) { //Log.d(TAG, "WR: WearPlugin:requestNotificationCancel");
val intent = Intent(mainApp, WatchUpdaterService::class.java) val intent = Intent(ctx, WatchUpdaterService::class.java)
.setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION) .setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION)
intent.putExtra("actionstring", actionString) intent.putExtra("actionstring", actionString)
mainApp.startService(intent) ctx.startService(intent)
} }
fun requestActionConfirmation(title: String, message: String, actionString: String) { fun requestActionConfirmation(title: String, message: String, actionString: String) {
val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST)
intent.putExtra("title", title) intent.putExtra("title", title)
intent.putExtra("message", message) intent.putExtra("message", message)
intent.putExtra("actionstring", actionString) intent.putExtra("actionstring", actionString)
mainApp.startService(intent) ctx.startService(intent)
} }
fun requestChangeConfirmation(title: String, message: String, actionString: String) { fun requestChangeConfirmation(title: String, message: String, actionString: String) {
val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST)
intent.putExtra("title", title) intent.putExtra("title", title)
intent.putExtra("message", message) intent.putExtra("message", message)
intent.putExtra("actionstring", actionString) intent.putExtra("actionstring", actionString)
mainApp.startService(intent) ctx.startService(intent)
} }
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.insulin
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Iob import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.db.Treatment import info.nightscout.androidaps.db.Treatment
import info.nightscout.androidaps.interfaces.InsulinInterface import info.nightscout.androidaps.interfaces.InsulinInterface
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
@ -14,6 +15,8 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
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
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.exp
import kotlin.math.pow
/** /**
* Created by adrian on 13.08.2017. * Created by adrian on 13.08.2017.
@ -84,6 +87,26 @@ abstract class InsulinOrefBasePlugin(
return result return result
} }
override fun iobCalcForTreatment(bolus: Bolus, time: Long, dia: Double): Iob {
val result = Iob()
val peak = peak
if (bolus.amount != 0.0) {
val bolusTime = bolus.timestamp
val t = (time - bolusTime) / 1000.0 / 60.0
val td = dia * 60 //getDIA() always >= MIN_DIA
val tp = peak.toDouble()
// force the IOB to 0 if over DIA hours have passed
if (t < td) {
val tau = tp * (1 - tp / td) / (1 - 2 * tp / td)
val a = 2 * tau / td
val S = 1 / (1 - a + (1 + a) * exp(-td / tau))
result.activityContrib = bolus.amount * (S / tau.pow(2.0)) * t * (1 - t / td) * exp(-t / tau)
result.iobContrib = bolus.amount * (1 - S * (1 - a) * ((t.pow(2.0) / (tau * td * (1 - a)) - t / tau - 1) * Math.exp(-t / tau) + 1))
}
}
return result
}
override val comment override val comment
get(): String { get(): String {
var comment = commentStandardText() var comment = commentStandardText()

View file

@ -40,7 +40,7 @@ import javax.inject.Singleton
import kotlin.math.min import kotlin.math.min
@Singleton @Singleton
open class VirtualPumpPlugin @Inject constructor( class VirtualPumpPlugin @Inject constructor(
injector: HasAndroidInjector, injector: HasAndroidInjector,
aapsLogger: AAPSLogger, aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
@ -347,7 +347,7 @@ open class VirtualPumpPlugin @Inject constructor(
} }
override fun manufacturer(): ManufacturerType { override fun manufacturer(): ManufacturerType {
return pumpDescription.pumpType.manufacturer return pumpDescription.pumpType.manufacturer ?: ManufacturerType.AndroidAPS
} }
override fun model(): PumpType { override fun model(): PumpType {
@ -367,7 +367,7 @@ open class VirtualPumpPlugin @Inject constructor(
} }
fun refreshConfiguration() { fun refreshConfiguration() {
val pumpType = sp.getString(R.string.key_virtualpump_type, PumpType.GenericAAPS.description) val pumpType = sp.getString(R.string.key_virtualpump_type, PumpType.GENERIC_AAPS.description)
val pumpTypeNew = PumpType.getByDescription(pumpType) val pumpTypeNew = PumpType.getByDescription(pumpType)
aapsLogger.debug(LTag.PUMP, "Pump in configuration: $pumpType, PumpType object: $pumpTypeNew") aapsLogger.debug(LTag.PUMP, "Pump in configuration: $pumpType, PumpType object: $pumpTypeNew")
if (this.pumpType == pumpTypeNew) return if (this.pumpType == pumpTypeNew) return

View file

@ -1,58 +0,0 @@
package info.nightscout.androidaps.plugins.treatments
import android.content.Context
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.roundToInt
@Singleton
class CarbsGenerator @Inject constructor(
private val resourceHelper: ResourceHelper,
private val activePlugin: ActivePluginProvider,
private val commandQueue: CommandQueueProvider,
private val context: Context
) {
fun generateCarbs(amount: Int, startTime: Long, duration: Int, notes: String) {
var remainingCarbs = amount.toLong()
val ticks = duration * 4 //duration guaranteed to be integer greater zero
for (i in 0 until ticks) {
val carbTime = startTime + i * 15 * 60 * 1000
val smallCarbAmount = (1.0 * remainingCarbs / (ticks - i)).roundToInt() //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs
remainingCarbs -= smallCarbAmount.toLong()
if (smallCarbAmount > 0) createCarb(smallCarbAmount, carbTime, TherapyEvent.Type.MEAL_BOLUS, notes)
}
}
fun createCarb(carbs: Int, time: Long, eventType: TherapyEvent.Type, notes: String) {
val carbInfo = DetailedBolusInfo()
carbInfo.timestamp = time
carbInfo.eventType = eventType
carbInfo.carbs = carbs.toDouble()
carbInfo.context = context
carbInfo.notes = notes
if (activePlugin.activePump.pumpDescription.storesCarbInfo && carbInfo.timestamp <= DateUtil.now() && carbInfo.timestamp > DateUtil.now() - T.mins(2).msecs()) {
commandQueue.bolus(carbInfo, object : Callback() {
override fun run() {
if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror)
}
}
})
} else {
// Don't send to pump if it is in the future or more than 5 minutes in the past
// as pumps might return those as as "now" when reading the history.
activePlugin.activeTreatments.addToHistoryTreatment(carbInfo, false)
}
}
}

View file

@ -11,7 +11,6 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventExtendedBolusChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.treatments.fragments.* import info.nightscout.androidaps.plugins.treatments.fragments.*
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -51,7 +50,7 @@ class TreatmentsFragment : DaggerFragment() {
binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility() binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
binding.treatments.setOnClickListener { binding.treatments.setOnClickListener {
setFragment(TreatmentsBolusFragment()) setFragment(TreatmentsMealLinkFragment())
setBackgroundColorOnSelected(it) setBackgroundColorOnSelected(it)
} }
binding.extendedBoluses.setOnClickListener { binding.extendedBoluses.setOnClickListener {
@ -78,7 +77,7 @@ class TreatmentsFragment : DaggerFragment() {
setFragment(TreatmentsUserEntryFragment()) setFragment(TreatmentsUserEntryFragment())
setBackgroundColorOnSelected(it) setBackgroundColorOnSelected(it)
} }
setFragment(TreatmentsBolusFragment()) setFragment(TreatmentsMealLinkFragment())
setBackgroundColorOnSelected(binding.treatments) setBackgroundColorOnSelected(binding.treatments)
} }

View file

@ -26,8 +26,6 @@ import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.embedments.InterfaceIDs;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
@ -55,6 +53,7 @@ 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.notifications.Notification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
@ -626,11 +625,11 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
Treatment treatment = new Treatment(); Treatment treatment = new Treatment();
treatment.date = detailedBolusInfo.timestamp; treatment.date = detailedBolusInfo.timestamp;
treatment.source = (detailedBolusInfo.getPumpType() == InterfaceIDs.PumpType.USER) ? Source.USER : Source.PUMP; treatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP;
treatment.pumpId = detailedBolusInfo.getBolusPumpId(); treatment.pumpId = detailedBolusInfo.getBolusPumpId();
treatment.insulin = detailedBolusInfo.insulin; treatment.insulin = detailedBolusInfo.insulin;
treatment.isValid = detailedBolusInfo.getBolusType() != Bolus.Type.PRIMING; treatment.isValid = detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING;
treatment.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; treatment.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
if (detailedBolusInfo.carbTime == 0) if (detailedBolusInfo.carbTime == 0)
treatment.carbs = detailedBolusInfo.carbs; treatment.carbs = detailedBolusInfo.carbs;
treatment.mealBolus = treatment.carbs > 0; treatment.mealBolus = treatment.carbs > 0;
@ -650,7 +649,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
if (detailedBolusInfo.carbTime != 0) { if (detailedBolusInfo.carbTime != 0) {
Treatment carbsTreatment = new Treatment(); Treatment carbsTreatment = new Treatment();
carbsTreatment.source = (detailedBolusInfo.getPumpType() == InterfaceIDs.PumpType.USER) ? Source.USER : Source.PUMP; carbsTreatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP;
carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId(); // but this should never happen carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId(); // but this should never happen
carbsTreatment.date = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records carbsTreatment.date = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records
carbsTreatment.carbs = detailedBolusInfo.carbs; carbsTreatment.carbs = detailedBolusInfo.carbs;
@ -663,7 +662,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
getService().createOrUpdateMedtronic(carbsTreatment, false); getService().createOrUpdateMedtronic(carbsTreatment, false);
//log.debug("Adding new Treatment record" + carbsTreatment); //log.debug("Adding new Treatment record" + carbsTreatment);
} }
if (newRecordCreated && detailedBolusInfo.getBolusType() != Bolus.Type.PRIMING) if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING)
nsUpload.uploadTreatmentRecord(detailedBolusInfo); nsUpload.uploadTreatmentRecord(detailedBolusInfo);
if (!allowUpdate && !creatOrUpdateResult.getSuccess()) { if (!allowUpdate && !creatOrUpdateResult.getSuccess()) {

View file

@ -1,210 +0,0 @@
package info.nightscout.androidaps.plugins.treatments.fragments
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsBolusFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsBolusItemBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.Treatment
import info.nightscout.androidaps.dialogs.WizardInfoDialog
import info.nightscout.androidaps.events.EventTreatmentChange
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.UploadQueueInterface
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsBolusFragment.RecyclerViewAdapter.TreatmentsViewHolder
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Inject
class TreatmentsBolusFragment : DaggerFragment() {
private val disposable = CompositeDisposable()
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger
private var _binding: TreatmentsBolusFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
TreatmentsBolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.recyclerview.adapter = RecyclerViewAdapter(treatmentsPlugin.treatmentsFromHistory)
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") {
uel.log(Action.TREATMENTS_NS_REFRESH)
treatmentsPlugin.service.resetTreatments()
rxBus.send(EventNSClientRestart())
}
}
}
binding.deleteFutureTreatments.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.deletefuturetreatments) + "?", Runnable {
uel.log(Action.DELETE_FUTURE_TREATMENTS)
val futureTreatments = treatmentsPlugin.service.getTreatmentDataFromTime(DateUtil.now() + 1000, true)
for (treatment in futureTreatments) {
if (NSUpload.isIdValid(treatment._id))
nsUpload.removeCareportalEntryFromNS(treatment._id)
else
uploadQueue.removeByMongoId("dbAdd", treatment._id)
treatmentsPlugin.service.delete(treatment)
}
updateGui()
})
}
}
val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE
}
@Synchronized
override fun onResume() {
super.onResume()
disposable.add(rxBus
.toObservable(EventTreatmentChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
)
disposable.add(rxBus
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
)
updateGui()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
inner class RecyclerViewAdapter internal constructor(var treatments: List<Treatment>) : RecyclerView.Adapter<TreatmentsViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TreatmentsViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_item, viewGroup, false)
return TreatmentsViewHolder(v)
}
override fun onBindViewHolder(holder: TreatmentsViewHolder, position: Int) {
val profile = profileFunction.getProfile() ?: return
val t = treatments[position]
holder.binding.date.text = dateUtil.dateAndTimeString(t.date)
holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, t.insulin)
holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, t.carbs.toInt())
val iob = t.iobCalc(System.currentTimeMillis(), profile.dia)
holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib)
holder.binding.mealOrCorrection.text = if (t.isSMB) "SMB" else if (t.mealBolus) resourceHelper.gs(R.string.mealbolus) else resourceHelper.gs(R.string.correctionbous)
holder.binding.pump.visibility = if (t.source == Source.PUMP) View.VISIBLE else View.GONE
holder.binding.ns.visibility = if (NSUpload.isIdValid(t._id)) View.VISIBLE else View.GONE
holder.binding.invalid.visibility = if (t.isValid) View.GONE else View.VISIBLE
if (iob.iobContrib != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.carbs.currentTextColor)
if (t.date > DateUtil.now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor)
holder.binding.remove.tag = t
holder.binding.calculation.tag = t
holder.binding.calculation.visibility = if (t.getBoluscalc() == null) View.INVISIBLE else View.VISIBLE
}
override fun getItemCount(): Int {
return treatments.size
}
inner class TreatmentsViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
val binding = TreatmentsBolusItemBinding.bind(view)
init {
binding.calculation.setOnClickListener {
val treatment = it.tag as Treatment
if (treatment.getBoluscalc() != null) {
val wizardDialog = WizardInfoDialog()
wizardDialog.setData(treatment.getBoluscalc()!!)
wizardDialog.show(childFragmentManager, "WizardInfoDialog")
}
}
binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.remove.setOnClickListener {
val treatment = it.tag as Treatment? ?: return@setOnClickListener
activity?.let { activity ->
val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " +
resourceHelper.gs(R.string.formatinsulinunits, treatment.insulin) + "\n" +
resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, treatment.carbs.toInt()) + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(treatment.date)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log(Action.TREATMENT_REMOVED, ValueWithUnit(treatment.date, Units.Timestamp), ValueWithUnit(treatment.insulin, Units.U, treatment.insulin != 0.0), ValueWithUnit(treatment.carbs.toInt(), Units.G, treatment.carbs != 0.0))
if (treatment.source == Source.PUMP) {
treatment.isValid = false
treatmentsPlugin.service.update(treatment)
} else {
if (NSUpload.isIdValid(treatment._id))
nsUpload.removeCareportalEntryFromNS(treatment._id)
else
uploadQueue.removeByMongoId("dbAdd", treatment._id)
treatmentsPlugin.service.delete(treatment)
}
updateGui()
})
}
}
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
private fun updateGui() {
if (_binding == null) return
binding.recyclerview.swapAdapter(RecyclerViewAdapter(treatmentsPlugin.treatmentsFromHistory), false)
if (treatmentsPlugin.lastCalculationTreatments != null) {
binding.iobTotal.text = resourceHelper.gs(R.string.formatinsulinunits, treatmentsPlugin.lastCalculationTreatments.iob)
binding.iobActivityTotal.text = resourceHelper.gs(R.string.formatinsulinunits, treatmentsPlugin.lastCalculationTreatments.activity)
}
if (treatmentsPlugin.service.getTreatmentDataFromTime(DateUtil.now() + 1000, true).isNotEmpty())
binding.deleteFutureTreatments.visibility = View.VISIBLE
else
binding.deleteFutureTreatments.visibility = View.GONE
}
}

View file

@ -120,28 +120,28 @@ class TreatmentsCareportalFragment : DaggerFragment() {
fun swapAdapter() { fun swapAdapter() {
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked) disposable +=
repository if (binding.showInvalidated.isChecked)
.getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false) repository
.observeOn(aapsSchedulers.main) .getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } .observeOn(aapsSchedulers.main)
else .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
repository else
.getTherapyEventDataFromTime(now - millsToThePast, false) repository
.observeOn(aapsSchedulers.main) .getTherapyEventDataFromTime(now - millsToThePast, false)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } .observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
} }
@Synchronized @Synchronized
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
swapAdapter() swapAdapter()
disposable.add(rxBus disposable += rxBus
.toObservable(EventTherapyEventChange::class.java) .toObservable(EventTherapyEventChange::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.debounce(1L, TimeUnit.SECONDS) .debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException) .subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
disposable += rxBus disposable += rxBus
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above .toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
@ -193,10 +193,11 @@ class TreatmentsCareportalFragment : DaggerFragment() {
val therapyEvent = v.tag as TherapyEvent val therapyEvent = v.tag as TherapyEvent
activity?.let { activity -> activity?.let { activity ->
val text = resourceHelper.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type.text) + "\n" + val text = resourceHelper.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type.text) + "\n" +
resourceHelper.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\n" + resourceHelper.gs(R.string.notes_label) + ": " + (therapyEvent.note
?: "") + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp) resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log(Action.CAREPORTAL_REMOVED, therapyEvent.note , ValueWithUnit(therapyEvent.timestamp, Units.Timestamp), ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent)) uel.log(Action.CAREPORTAL_REMOVED, therapyEvent.note, ValueWithUnit(therapyEvent.timestamp, Units.Timestamp), ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent))
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id)) disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
.subscribe({ .subscribe({
val id = therapyEvent.interfaceIDs.nightscoutId val id = therapyEvent.interfaceIDs.nightscoutId

View file

@ -0,0 +1,321 @@
package info.nightscout.androidaps.plugins.treatments.fragments
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.MealLinkLoaded
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InvalidateBolusTransaction
import info.nightscout.androidaps.database.transactions.InvalidateCarbsTransaction
import info.nightscout.androidaps.database.transactions.InvalidateMealLinkTransaction
import info.nightscout.androidaps.databinding.TreatmentsMealLinkFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsMealLinkItemBinding
import info.nightscout.androidaps.dialogs.WizardInfoDialog
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventTreatmentChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.iobCalc
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class TreatmentsMealLinkFragment : DaggerFragment() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var activePlugin: ActivePluginProvider
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
private var _binding: TreatmentsMealLinkFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
TreatmentsMealLinkFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") {
uel.log(Action.TREATMENTS_NS_REFRESH)
disposable +=
Completable.fromAction {
repository.deleteAllMealLinks()
repository.deleteAllBoluses()
repository.deleteAllCarbs()
}
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = { rxBus.send(EventTreatmentChange(null)) }
)
rxBus.send(EventNSClientRestart())
}
}
}
binding.deleteFutureTreatments.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.deletefuturetreatments) + "?", Runnable {
uel.log(Action.DELETE_FUTURE_TREATMENTS)
repository
.getMealLinkLoadedDataFromTime(dateUtil._now(), false)
.observeOn(aapsSchedulers.main)
.subscribe { list ->
list.forEach { mealLinkLoaded ->
disposable += repository.runTransactionForResult(InvalidateMealLinkTransaction(mealLinkLoaded.mealLink.id))
.subscribe({
if (mealLinkLoaded.bolus != null) {
val id = mealLinkLoaded.bolus!!.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.bolus!!.timestamp.toString())
}
if (mealLinkLoaded.carbs != null) {
val id = mealLinkLoaded.carbs!!.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.carbs!!.timestamp.toString())
}
}, {
aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating MealLink", it)
})
}
binding.deleteFutureTreatments.visibility = View.GONE
}
})
}
}
val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
rxBus.send(EventTreatmentUpdateGui())
}
}
fun swapAdapter() {
val now = System.currentTimeMillis()
disposable +=
if (binding.showInvalidated.isChecked)
repository
.getMealLinkLoadedDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
else
repository
.getMealLinkLoadedDataFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
disposable += repository
.getMealLinkLoadedDataFromTime(now, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() }
}
@Synchronized
override fun onResume() {
super.onResume()
swapAdapter()
disposable += rxBus
.toObservable(EventTreatmentChange::class.java)
.observeOn(aapsSchedulers.main)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
.observeOn(aapsSchedulers.io)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(aapsSchedulers.main)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLinkLoaded>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_meal_link_item, viewGroup, false)
return MealLinkLoadedViewHolder(v)
}
override fun onBindViewHolder(holder: MealLinkLoadedViewHolder, position: Int) {
val profile = profileFunction.getProfile() ?: return
val ml = mealLinks[position]
// MealLink
holder.binding.date.text = dateUtil.dateAndTimeString(ml.mealLink.timestamp)
val iob = ml.bolus?.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia)
?: Iob()
holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib)
if (iob.iobContrib != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.carbs.currentTextColor)
if (ml.mealLink.timestamp > dateUtil._now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor)
holder.binding.mealOrCorrection.text =
when (ml.bolus?.type) {
Bolus.Type.SMB -> "SMB"
Bolus.Type.NORMAL -> resourceHelper.gs(R.string.mealbolus)
else -> ""
}
holder.binding.calculation.visibility = (ml.bolusCalculatorResult != null).toVisibility()
// Bolus
holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus?.isValid == true || binding.showInvalidated.isChecked)).toVisibility()
holder.binding.bolusDate.text = dateUtil.timeString(ml.bolus?.timestamp ?: 0L)
holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, ml.bolus?.amount ?: 0.0)
holder.binding.bolusNs.visibility = (NSUpload.isIdValid(ml.bolus?.interfaceIDs?.nightscoutId)).toVisibility()
holder.binding.bolusPump.visibility = (ml.bolus?.interfaceIDs?.pumpId != null).toVisibility()
holder.binding.bolusInvalid.visibility = (ml.bolus?.isValid == true).not().toVisibility()
// Carbs
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs?.isValid == true || binding.showInvalidated.isChecked)).toVisibility()
holder.binding.carbsDate.text = dateUtil.timeString(ml.carbs?.timestamp ?: 0L)
holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, ml.carbs?.amount?.toInt() ?: 0)
holder.binding.carbsNs.visibility = (NSUpload.isIdValid(ml.carbs?.interfaceIDs?.nightscoutId)).toVisibility()
holder.binding.carbsPump.visibility = (ml.carbs?.interfaceIDs?.pumpId != null).toVisibility()
holder.binding.carbsInvalid.visibility = (ml.carbs?.isValid == true).not().toVisibility()
holder.binding.bolusRemove.visibility = (ml.bolus?.isValid == true).toVisibility()
holder.binding.carbsRemove.visibility = (ml.carbs?.isValid == true).toVisibility()
holder.binding.bolusRemove.tag = ml
holder.binding.carbsRemove.tag = ml
holder.binding.calculation.tag = ml
}
override fun getItemCount(): Int {
return mealLinks.size
}
inner class MealLinkLoadedViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
val binding = TreatmentsMealLinkItemBinding.bind(view)
init {
binding.calculation.setOnClickListener {
val mealLinkLoaded = it.tag as MealLinkLoaded
mealLinkLoaded.bolusCalculatorResult?.let { bolusCalculatorResult ->
WizardInfoDialog().also { wizardDialog ->
wizardDialog.setData(bolusCalculatorResult, mealLinkLoaded.therapyEvent?.note ?: "")
wizardDialog.show(childFragmentManager, "WizardInfoDialog")
}
}
}
binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.bolusRemove.setOnClickListener {
val mealLinkLoaded = it.tag as MealLinkLoaded? ?: return@setOnClickListener
activity?.let { activity ->
val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " +
resourceHelper.gs(R.string.formatinsulinunits, mealLinkLoaded.bolus!!.amount) + "\n" +
// resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, mealLinkLoaded.carbs.toInt()) + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(mealLinkLoaded.bolus!!.timestamp)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log(
Action.TREATMENT_REMOVED,
ValueWithUnit(mealLinkLoaded.bolus!!.timestamp, Units.Timestamp),
ValueWithUnit(mealLinkLoaded.bolus!!.amount, Units.U)
// ValueWithUnit(mealLinkLoaded.carbs.toInt(), Units.G)
)
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(mealLinkLoaded.bolus!!.id))
.subscribe({
val id = mealLinkLoaded.bolus!!.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.bolus!!.timestamp.toString())
}, {
aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating bolus", it)
})
})
}
}
binding.bolusRemove.paintFlags = binding.bolusRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.carbsRemove.setOnClickListener {
val mealLinkLoaded = it.tag as MealLinkLoaded? ?: return@setOnClickListener
activity?.let { activity ->
val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " +
resourceHelper.gs(R.string.formatinsulinunits, mealLinkLoaded.bolus!!.amount) + "\n" +
// resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, mealLinkLoaded.carbs.toInt()) + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(mealLinkLoaded.bolus!!.timestamp)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log(
Action.TREATMENT_REMOVED,
ValueWithUnit(mealLinkLoaded.bolus!!.timestamp, Units.Timestamp),
ValueWithUnit(mealLinkLoaded.bolus!!.amount, Units.U)
// ValueWithUnit(mealLinkLoaded.carbs.toInt(), Units.G)
)
disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(mealLinkLoaded.carbs!!.id))
.subscribe({
val id = mealLinkLoaded.carbs!!.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.carbs!!.timestamp.toString())
}, {
aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating carbs", it)
})
})
}
}
binding.carbsRemove.paintFlags = binding.carbsRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
}

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.dialogs.BolusProgressDialog import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventBolusRequested import info.nightscout.androidaps.events.EventBolusRequested
import info.nightscout.androidaps.events.EventNewBasalProfile import info.nightscout.androidaps.events.EventNewBasalProfile
@ -230,7 +229,7 @@ open class CommandQueue @Inject constructor(
// returns true if command is queued // returns true if command is queued
@Synchronized @Synchronized
override fun bolus(detailedBolusInfo: DetailedBolusInfo, callback: Callback?): Boolean { override fun bolus(detailedBolusInfo: DetailedBolusInfo, callback: Callback?): Boolean {
var type = if (detailedBolusInfo.bolusType == Bolus.Type.SMB) CommandType.SMB_BOLUS else CommandType.BOLUS var type = if (detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) CommandType.SMB_BOLUS else CommandType.BOLUS
if (type == CommandType.SMB_BOLUS) { if (type == CommandType.SMB_BOLUS) {
if (isRunning(CommandType.BOLUS) || isRunning(CommandType.SMB_BOLUS) || bolusInQueue()) { if (isRunning(CommandType.BOLUS) || isRunning(CommandType.SMB_BOLUS) || bolusInQueue()) {
aapsLogger.debug(LTag.PUMPQUEUE, "Rejecting SMB since a bolus is queue/running") aapsLogger.debug(LTag.PUMPQUEUE, "Rejecting SMB since a bolus is queue/running")
@ -257,7 +256,7 @@ open class CommandQueue @Inject constructor(
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(Constraint(detailedBolusInfo.insulin)).value() detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(Constraint(detailedBolusInfo.insulin)).value()
detailedBolusInfo.carbs = constraintChecker.applyCarbsConstraints(Constraint(detailedBolusInfo.carbs.toInt())).value().toDouble() detailedBolusInfo.carbs = constraintChecker.applyCarbsConstraints(Constraint(detailedBolusInfo.carbs.toInt())).value().toDouble()
// add new command to queue // add new command to queue
if (detailedBolusInfo.bolusType == Bolus.Type.SMB) { if (detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) {
add(CommandSMBBolus(injector, detailedBolusInfo, callback)) add(CommandSMBBolus(injector, detailedBolusInfo, callback))
} else { } else {
add(CommandBolus(injector, detailedBolusInfo, callback, type)) add(CommandBolus(injector, detailedBolusInfo, callback, type))

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.BolusCalculatorResult import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
@ -22,6 +23,7 @@ import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
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.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
@ -35,6 +37,8 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
@ -58,6 +62,10 @@ class BolusWizard @Inject constructor(
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer @Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider @Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
@Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
private val disposable = CompositeDisposable()
init { init {
injector.androidInjector().inject(this) injector.androidInjector().inject(this)
@ -112,7 +120,7 @@ class BolusWizard @Inject constructor(
var cob: Double = 0.0 var cob: Double = 0.0
var bg: Double = 0.0 var bg: Double = 0.0
private var correction: Double = 0.0 private var correction: Double = 0.0
private var percentageCorrection: Double = 0.0 private var percentageCorrection: Int = 0
private var useBg: Boolean = false private var useBg: Boolean = false
private var useCob: Boolean = false private var useCob: Boolean = false
private var includeBolusIOB: Boolean = false private var includeBolusIOB: Boolean = false
@ -132,7 +140,7 @@ class BolusWizard @Inject constructor(
cob: Double, cob: Double,
bg: Double, bg: Double,
correction: Double, correction: Double,
percentageCorrection: Double = 100.0, percentageCorrection: Int = 100,
useBg: Boolean, useBg: Boolean,
useCob: Boolean, useCob: Boolean,
includeBolusIOB: Boolean, includeBolusIOB: Boolean,
@ -276,7 +284,7 @@ class BolusWizard @Inject constructor(
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
val pct = if (percentageCorrection != 100.0) " (" + percentageCorrection.toInt() + "%)" else "" val pct = if (percentageCorrection != 100) " ($percentageCorrection%)" else ""
actions.add(resourceHelper.gs(R.string.bolus) + ": " + resourceHelper.gs(R.string.formatinsulinunits, insulinAfterConstraints).formatColor(resourceHelper, R.color.bolus) + pct) actions.add(resourceHelper.gs(R.string.bolus) + ": " + resourceHelper.gs(R.string.formatinsulinunits, insulinAfterConstraints).formatColor(resourceHelper, R.color.bolus) + pct)
} }
if (carbs > 0 && !advisor) { if (carbs > 0 && !advisor) {
@ -328,16 +336,16 @@ class BolusWizard @Inject constructor(
val confirmMessage = confirmMessageAfterConstraints(advisor = true) val confirmMessage = confirmMessageAfterConstraints(advisor = true)
OKDialog.showConfirmation(ctx, resourceHelper.gs(R.string.boluswizard), confirmMessage, { OKDialog.showConfirmation(ctx, resourceHelper.gs(R.string.boluswizard), confirmMessage, {
DetailedBolusInfo().apply { DetailedBolusInfo().apply {
eventType = TherapyEvent.Type.CORRECTION_BOLUS eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
insulin = insulinAfterConstraints insulin = insulinAfterConstraints
carbs = 0.0 carbs = 0.0
context = ctx context = ctx
mgdlGlucose = Profile.toMgdl(bg, profile.units) mgdlGlucose = Profile.toMgdl(bg, profile.units)
glucoseType = TherapyEvent.MeterType.MANUAL glucoseType = DetailedBolusInfo.MeterType.MANUAL
carbTime = 0 carbTime = 0
bolusCalculatorResult = createBolusCalculatorResult() bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes notes = this@BolusWizard.notes
uel.log(Action.BOLUS_ADVISOR, notes, ValueWithUnit(eventType, Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U)) uel.log(Action.BOLUS_ADVISOR, notes, ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U))
if (insulin > 0) { if (insulin > 0) {
commandQueue.bolus(this, object : Callback() { commandQueue.bolus(this, object : Callback() {
override fun run() { override fun run() {
@ -391,26 +399,44 @@ class BolusWizard @Inject constructor(
} }
} }
DetailedBolusInfo().apply { DetailedBolusInfo().apply {
eventType = TherapyEvent.Type.BOLUS_WIZARD eventType = DetailedBolusInfo.EventType.BOLUS_WIZARD
insulin = insulinAfterConstraints insulin = insulinAfterConstraints
carbs = this@BolusWizard.carbs.toDouble() carbs = this@BolusWizard.carbs.toDouble()
context = ctx context = ctx
mgdlGlucose = Profile.toMgdl(bg, profile.units) mgdlGlucose = Profile.toMgdl(bg, profile.units)
glucoseType = TherapyEvent.MeterType.MANUAL glucoseType = DetailedBolusInfo.MeterType.MANUAL
carbTime = this@BolusWizard.carbTime carbTime = this@BolusWizard.carbTime
bolusCalculatorResult = createBolusCalculatorResult() bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes notes = this@BolusWizard.notes
uel.log(Action.BOLUS, notes, ValueWithUnit(eventType, Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0), ValueWithUnit(carbTime, Units.M, carbTime != 0))
if (insulin > 0 || pump.pumpDescription.storesCarbInfo) { if (insulin > 0 || pump.pumpDescription.storesCarbInfo) {
commandQueue.bolus(this, object : Callback() { commandQueue.bolus(this, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror) ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror)
} } else
uel.log(Action.BOLUS, notes,
ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent),
ValueWithUnit(insulinAfterConstraints, Units.U),
ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0),
ValueWithUnit(carbTime, Units.M, carbTime != 0)
)
} }
}) })
} else { } else {
activePlugin.activeTreatments.addToHistoryTreatment(this, false) disposable += repository.runTransactionForResult(insertMealLinkTransaction())
.subscribe({ result ->
result.inserted.forEach { inserted ->
uel.log(Action.BOLUS, notes,
ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent),
ValueWithUnit(insulinAfterConstraints, Units.U),
ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0),
ValueWithUnit(carbTime, Units.M, carbTime != 0)
)
nsUpload.uploadMealLinkRecord(inserted)
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it)
})
} }
} }
if (useAlarm && carbs > 0 && carbTime > 0) { if (useAlarm && carbs > 0 && carbTime > 0) {

View file

@ -125,7 +125,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) { } else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
trend = true trend = true
} }
val percentage = sp.getDouble(R.string.key_boluswizard_percentage, 100.0) val percentage = sp.getInt(R.string.key_boluswizard_percentage, 100)
return BolusWizard(injector).doCalc(profile, profileName, tempTarget, carbs(), cob, bg, 0.0, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, false, "QuickWizard") return BolusWizard(injector).doCalc(profile, profileName, tempTarget, carbs(), cob, bg, 0.0, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, false, "QuickWizard")
} }

View file

@ -44,7 +44,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:contentDescription="@string/show_calculation" android:contentDescription="@string/show_removed"
app:srcCompat="@drawable/ic_visibility" /> app:srcCompat="@drawable/ic_visibility" />
</LinearLayout> </LinearLayout>

View file

@ -1,53 +1,11 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:context=".plugins.treatments.fragments.TreatmentsBolusFragment"> tools:context=".plugins.treatments.fragments.TreatmentsBolusFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="@string/treatments_iobtotal_label_string"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/iob_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"
tools:ignore="RtlSymmetry" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="@string/treatments_iobactivitytotal_label_string"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/iob_activity_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"
tools:ignore="RtlSymmetry" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -57,7 +15,7 @@
android:id="@+id/refresh_from_nightscout" android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"
android:layout_width="0px" android:layout_width="0px"
android:layout_height="fill_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_weight="1" android:layout_weight="1"
android:drawableStart="@drawable/ic_refresh" android:drawableStart="@drawable/ic_refresh"
@ -67,12 +25,28 @@
android:id="@+id/delete_future_treatments" android:id="@+id/delete_future_treatments"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"
android:layout_width="0px" android:layout_width="0px"
android:layout_height="fill_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_weight="1" android:layout_weight="1"
android:drawableStart="@drawable/ic_remove" android:drawableStart="@drawable/ic_remove"
android:text="@string/deletefuturetreatments" /> android:text="@string/deletefuturetreatments" />
<CheckBox
android:id="@+id/show_invalidated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:paddingEnd="5dp"
tools:ignore="RtlSymmetry" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="@string/show_removed"
app:srcCompat="@drawable/ic_visibility" />
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView

View file

@ -22,8 +22,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="5dp"
android:gravity="center" android:gravity="center"
android:paddingStart="10dp"
android:text="{fa-clock-o}" android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
@ -31,15 +31,48 @@
android:id="@+id/date" android:id="@+id/date"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="5dp" android:layout_marginStart="5dp"
tools:ignore="RtlSymmetry" /> android:text="1.1.2000"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/treatments_iob_label_string" />
<TextView
android:id="@+id/iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/meal_or_correction"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_weight="1" android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/calculation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/calculation_short"
android:textAlignment="viewEnd"
android:textColor="@color/colorCalculatorButton"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/meal_or_correction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Meal" android:text="Meal"
android:textAlignment="textEnd" android:textAlignment="textEnd"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -48,16 +81,34 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/bolus_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:gravity="center"
android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/bolus_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="1.1.2000"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"
android:paddingLeft="10dp" android:layout_marginStart="10dp"
android:paddingRight="10dp" android:layout_marginEnd="10dp"
android:text="@string/treatments_insulin_label_string" /> android:text="@string/treatments_insulin_label_string" />
<TextView <TextView
@ -68,12 +119,79 @@
android:layout_marginEnd="30dp" android:layout_marginEnd="30dp"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/bolus_ns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="NS"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/bolus_pump"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="PH"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/bolus_invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/bolus_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
</LinearLayout>
<LinearLayout
android:id="@+id/carbs_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:gravity="center"
android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/carbs_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="1.1.2000"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"
android:paddingLeft="10dp" android:layout_marginStart="10dp"
android:paddingRight="10dp" android:layout_marginEnd="10dp"
android:text="@string/treatments_carbs_label_string" /> android:text="@string/treatments_carbs_label_string" />
<TextView <TextView
@ -91,16 +209,7 @@
android:text="" /> android:text="" />
<TextView <TextView
android:id="@+id/pump" android:id="@+id/carbs_ns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="PH"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/ns"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
@ -109,57 +218,24 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/invalid" android:id="@+id/carbs_pump"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="PH"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/carbs_invalid"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:text="@string/invalid" android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" /> android:textColor="@android:color/holo_red_light" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/carbs_remove"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/treatments_iob_label_string" />
<TextView
android:id="@+id/iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="30dp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="30dp"
android:textStyle="bold" />
<TextView
android:id="@+id/calculation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="1"
android:paddingEnd="10dp"
android:text="@string/calculation_short"
android:textAlignment="viewEnd"
android:textColor="@color/colorCalculatorButton"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/remove"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"

View file

@ -35,7 +35,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:contentDescription="@string/show_calculation" android:contentDescription="@string/show_removed"
app:srcCompat="@drawable/ic_visibility" /> app:srcCompat="@drawable/ic_visibility" />

View file

@ -978,6 +978,7 @@
<string name="randombg_short">BG</string> <string name="randombg_short">BG</string>
<string name="tools">Tools</string> <string name="tools">Tools</string>
<string name="show_calculation">Show calcuation</string> <string name="show_calculation">Show calcuation</string>
<string name="show_removed">Show removed</string>
<string name="clearqueueconfirm">Clear queue? All data in queue will be lost!</string> <string name="clearqueueconfirm">Clear queue? All data in queue will be lost!</string>
<string name="key_xdripstatus_detailediob" translatable="false">xdripstatus_detailediob</string> <string name="key_xdripstatus_detailediob" translatable="false">xdripstatus_detailediob</string>
<string name="key_xdripstatus_showbgi" translatable="false">xdripstatus_showbgi</string> <string name="key_xdripstatus_showbgi" translatable="false">xdripstatus_showbgi</string>

View file

@ -57,7 +57,7 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface {
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject() override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
override fun model(): PumpType = PumpType.GenericAAPS override fun model(): PumpType = PumpType.GENERIC_AAPS
override fun serialNumber(): String = "1" override fun serialNumber(): String = "1"
override fun shortStatus(veryShort: Boolean): String = "" override fun shortStatus(veryShort: Boolean): String = ""
override val isFakingTempsByExtendedBoluses: Boolean = false override val isFakingTempsByExtendedBoluses: Boolean = false

View file

@ -51,7 +51,7 @@ import java.util.*
*/ */
@RunWith(PowerMockRunner::class) @RunWith(PowerMockRunner::class)
@PrepareForTest( @PrepareForTest(
MainApp::class, ConfigBuilderPlugin::class, ConstraintChecker::class, SP::class, Context::class, ConfigBuilderPlugin::class, ConstraintChecker::class, SP::class, Context::class,
OpenAPSAMAPlugin::class, OpenAPSSMBPlugin::class, TreatmentsPlugin::class, TreatmentService::class, OpenAPSAMAPlugin::class, OpenAPSSMBPlugin::class, TreatmentsPlugin::class, TreatmentService::class,
VirtualPumpPlugin::class, DetailedBolusInfoStorage::class, GlimpPlugin::class, Profiler::class, VirtualPumpPlugin::class, DetailedBolusInfoStorage::class, GlimpPlugin::class, Profiler::class,
UserEntryLogger::class, IobCobCalculatorPlugin::class, LoggerUtils::class, AppRepository::class) UserEntryLogger::class, IobCobCalculatorPlugin::class, LoggerUtils::class, AppRepository::class)

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.nsclient package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context import android.content.Context
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.events.EventChargingState import info.nightscout.androidaps.events.EventChargingState
@ -25,7 +24,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class) @RunWith(PowerMockRunner::class)
@PrepareForTest(MainApp::class, SP::class, Context::class) @PrepareForTest(SP::class, Context::class)
class NsClientReceiverDelegateTest : TestBase() { class NsClientReceiverDelegateTest : TestBase() {
@Mock lateinit var context: Context @Mock lateinit var context: Context

View file

@ -170,7 +170,7 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
`when`(virtualPumpPlugin.shortStatus(ArgumentMatchers.anyBoolean())).thenReturn("Virtual Pump") `when`(virtualPumpPlugin.shortStatus(ArgumentMatchers.anyBoolean())).thenReturn("Virtual Pump")
`when`(virtualPumpPlugin.isSuspended()).thenReturn(false) `when`(virtualPumpPlugin.isSuspended()).thenReturn(false)
`when`(virtualPumpPlugin.pumpDescription).thenReturn(PumpDescription()) `when`(virtualPumpPlugin.pumpDescription).thenReturn(PumpDescription())
`when`(virtualPumpPlugin.model()).thenReturn(PumpType.GenericAAPS) `when`(virtualPumpPlugin.model()).thenReturn(PumpType.GENERIC_AAPS)
`when`(treatmentsInterface.lastCalculationTreatments).thenReturn(IobTotal(0)) `when`(treatmentsInterface.lastCalculationTreatments).thenReturn(IobTotal(0))
`when`(treatmentsInterface.lastCalculationTempBasals).thenReturn(IobTotal(0)) `when`(treatmentsInterface.lastCalculationTempBasals).thenReturn(IobTotal(0))

View file

@ -46,7 +46,7 @@ class VirtualPumpPluginUTest : TestBase() {
fun refreshConfiguration() { fun refreshConfiguration() {
PowerMockito.`when`(sp.getString(R.string.key_virtualpump_type, "Generic AAPS")).thenReturn("Accu-Chek Combo") PowerMockito.`when`(sp.getString(R.string.key_virtualpump_type, "Generic AAPS")).thenReturn("Accu-Chek Combo")
virtualPumpPlugin.refreshConfiguration() virtualPumpPlugin.refreshConfiguration()
Assert.assertEquals(PumpType.AccuChekCombo, virtualPumpPlugin.pumpType) Assert.assertEquals(PumpType.ACCU_CHEK_COMBO, virtualPumpPlugin.pumpType)
} }
@Test @Test
@ -55,6 +55,6 @@ class VirtualPumpPluginUTest : TestBase() {
virtualPumpPlugin.refreshConfiguration() virtualPumpPlugin.refreshConfiguration()
PowerMockito.`when`(sp.getString(R.string.key_virtualpump_type, "Generic AAPS")).thenReturn("Accu-Chek Combo") PowerMockito.`when`(sp.getString(R.string.key_virtualpump_type, "Generic AAPS")).thenReturn("Accu-Chek Combo")
virtualPumpPlugin.refreshConfiguration() virtualPumpPlugin.refreshConfiguration()
Assert.assertEquals(PumpType.AccuChekCombo, virtualPumpPlugin.pumpType) Assert.assertEquals(PumpType.ACCU_CHEK_COMBO, virtualPumpPlugin.pumpType)
} }
} }

View file

@ -68,7 +68,7 @@ class TestPumpPlugin(pluginDescription: PluginDescription,
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject() override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
override fun model(): PumpType = PumpType.GenericAAPS override fun model(): PumpType = PumpType.GENERIC_AAPS
override fun serialNumber(): String = "1" override fun serialNumber(): String = "1"
override fun shortStatus(veryShort: Boolean): String = "" override fun shortStatus(veryShort: Boolean): String = ""
override val isFakingTempsByExtendedBoluses: Boolean = false override val isFakingTempsByExtendedBoluses: Boolean = false

View file

@ -25,8 +25,6 @@ import info.nightscout.androidaps.combo.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.embedments.InterfaceIDs;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD; import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
@ -160,7 +158,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
this.context = context; this.context = context;
this.databaseHelper = databaseHelper; this.databaseHelper = databaseHelper;
pumpDescription.setPumpDescription(PumpType.AccuChekCombo); pumpDescription.setPumpDescription(PumpType.ACCU_CHEK_COMBO);
} }
@Override protected void onStart() { @Override protected void onStart() {
@ -491,7 +489,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(new Treatment()); bolusingEvent.setT(new Treatment());
bolusingEvent.getT().isSMB = detailedBolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB; bolusingEvent.getT().isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
bolusingEvent.setPercent(100); bolusingEvent.setPercent(100);
rxBus.send(bolusingEvent); rxBus.send(bolusingEvent);
@ -569,7 +567,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
} }
Treatment treatment = new Treatment(); Treatment treatment = new Treatment();
treatment.isSMB = detailedBolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB; treatment.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
EventOverviewBolusProgress.INSTANCE.setT(treatment); EventOverviewBolusProgress.INSTANCE.setT(treatment);
// start bolus delivery // start bolus delivery
@ -667,8 +665,8 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
*/ */
private boolean addBolusToTreatments(DetailedBolusInfo detailedBolusInfo, Bolus lastPumpBolus) { private boolean addBolusToTreatments(DetailedBolusInfo detailedBolusInfo, Bolus lastPumpBolus) {
DetailedBolusInfo bolusInfo = detailedBolusInfo.copy(); DetailedBolusInfo bolusInfo = detailedBolusInfo.copy();
bolusInfo.timestamp = calculateFakeBolusDate(lastPumpBolus); bolusInfo.setBolusTimestamp(calculateFakeBolusDate(lastPumpBolus));
bolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_COMBO); bolusInfo.setPumpType(PumpType.ACCU_CHEK_COMBO);
bolusInfo.setPumpSerial(serialNumber()); bolusInfo.setPumpSerial(serialNumber());
bolusInfo.setBolusPumpId(bolusInfo.timestamp); bolusInfo.setBolusPumpId(bolusInfo.timestamp);
bolusInfo.insulin = lastPumpBolus.amount; bolusInfo.insulin = lastPumpBolus.amount;
@ -678,7 +676,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
DetailedBolusInfo carbInfo = new DetailedBolusInfo(); DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.timestamp = bolusInfo.timestamp + bolusInfo.carbTime * 60L * 1000L; carbInfo.timestamp = bolusInfo.timestamp + bolusInfo.carbTime * 60L * 1000L;
carbInfo.carbs = bolusInfo.carbs; carbInfo.carbs = bolusInfo.carbs;
carbInfo.setPumpType(InterfaceIDs.PumpType.USER); carbInfo.setPumpType(PumpType.USER);
treatmentsPlugin.addToHistoryTreatment(carbInfo, true); treatmentsPlugin.addToHistoryTreatment(carbInfo, true);
// remove carbs from bolusInfo to not trigger any unwanted code paths in // remove carbs from bolusInfo to not trigger any unwanted code paths in
@ -689,7 +687,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
treatmentsPlugin.addToHistoryTreatment(bolusInfo, true); treatmentsPlugin.addToHistoryTreatment(bolusInfo, true);
} catch (Exception e) { } catch (Exception e) {
getAapsLogger().error("Adding treatment record failed", e); getAapsLogger().error("Adding treatment record failed", e);
if (bolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB) { if (bolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB) {
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, getResourceHelper().gs(R.string.combo_error_updating_treatment_record), Notification.URGENT); Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, getResourceHelper().gs(R.string.combo_error_updating_treatment_record), Notification.URGENT);
rxBus.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
} }
@ -1156,12 +1154,12 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
boolean updated = false; boolean updated = false;
for (Bolus pumpBolus : history.bolusHistory) { for (Bolus pumpBolus : history.bolusHistory) {
DetailedBolusInfo dbi = new DetailedBolusInfo(); DetailedBolusInfo dbi = new DetailedBolusInfo();
dbi.timestamp = calculateFakeBolusDate(pumpBolus); dbi.setBolusTimestamp(calculateFakeBolusDate(pumpBolus));
dbi.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_COMBO); dbi.setPumpType(PumpType.ACCU_CHEK_COMBO);
dbi.setPumpSerial(serialNumber()); dbi.setPumpSerial(serialNumber());
dbi.setBolusPumpId(dbi.timestamp); dbi.setBolusPumpId(dbi.timestamp);
dbi.insulin = pumpBolus.amount; dbi.insulin = pumpBolus.amount;
dbi.setEventType(TherapyEvent.Type.CORRECTION_BOLUS); dbi.setEventType(DetailedBolusInfo.EventType.CORRECTION_BOLUS);
if (treatmentsPlugin.addToHistoryTreatment(dbi, true)) { if (treatmentsPlugin.addToHistoryTreatment(dbi, true)) {
updated = true; updated = true;
} }
@ -1311,7 +1309,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
@NonNull @Override @NonNull @Override
public PumpType model() { public PumpType model() {
return PumpType.AccuChekCombo; return PumpType.ACCU_CHEK_COMBO;
} }
@NonNull @Override @NonNull @Override

View file

@ -422,7 +422,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() {
private fun isOldData(historyList: List<TDD>): Boolean { private fun isOldData(historyList: List<TDD>): Boolean {
val type = activePlugin.activePump.pumpDescription.pumpType val type = activePlugin.activePump.pumpDescription.pumpType
val startsYesterday = type == PumpType.DanaR || type == PumpType.DanaRS || type == PumpType.DanaRv2 || type == PumpType.DanaRKorean || type == PumpType.AccuChekInsight val startsYesterday = type == PumpType.DANA_R || type == PumpType.DANA_RS || type == PumpType.DANA_RV2 || type == PumpType.DANA_R_KOREAN || type == PumpType.ACCU_CHEK_INSIGHT
val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault()) val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault())
return historyList.size < 3 || df.format(Date(historyList[0].date)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0)) return historyList.size < 3 || df.format(Date(historyList[0].date)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0))
} }

View file

@ -2,11 +2,14 @@ package info.nightscout.androidaps.data
import android.content.Context import android.content.Context
import com.google.gson.Gson import com.google.gson.Gson
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.BolusCalculatorResult import info.nightscout.androidaps.database.entities.BolusCalculatorResult
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.InsertMealLinkTransaction
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.T
class DetailedBolusInfo { class DetailedBolusInfo {
@ -23,36 +26,79 @@ class DetailedBolusInfo {
// Prefilled info for storing to db // Prefilled info for storing to db
var bolusCalculatorResult: BolusCalculatorResult? = null var bolusCalculatorResult: BolusCalculatorResult? = null
var eventType = TherapyEvent.Type.MEAL_BOLUS var eventType = EventType.MEAL_BOLUS
var notes: String? = null var notes: String? = null
var mgdlGlucose: Double? = null // Bg value in mgdl var mgdlGlucose: Double? = null // Bg value in mgdl
var glucoseType: TherapyEvent.MeterType? = null // NS values: Manual, Finger, Sensor var glucoseType: MeterType? = null // NS values: Manual, Finger, Sensor
var bolusType = Bolus.Type.NORMAL var bolusType = BolusType.NORMAL
var carbsDuration = 0L // in milliseconds
// Collected info from driver // Collected info from driver
var pumpType: InterfaceIDs.PumpType? = null // if == USER var pumpType: PumpType? = null // if == USER
var pumpSerial: String? = null var pumpSerial: String? = null
var bolusPumpId: Long? = null var bolusPumpId: Long? = null
var bolusTimestamp: Long? = null
var carbsPumpId: Long? = null var carbsPumpId: Long? = null
var carbsTimestamp: Long? = null
var superBolusTemporaryBasal: TemporaryBasal? = null
fun createTherapyEvent(): TherapyEvent? = enum class MeterType(val text: String) {
if (mgdlGlucose != null || notes != null) FINGER("Finger"),
TherapyEvent( SENSOR("Sensor"),
timestamp = timestamp, MANUAL("Manual");
type = TherapyEvent.Type.NOTE,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL, fun toDbMeterType(): TherapyEvent.MeterType =
note = notes, when (this) {
glucose = mgdlGlucose, FINGER -> TherapyEvent.MeterType.FINGER
glucoseType = glucoseType SENSOR -> TherapyEvent.MeterType.SENSOR
) MANUAL -> TherapyEvent.MeterType.MANUAL
else null }
}
enum class BolusType {
NORMAL,
SMB,
PRIMING;
fun toDBbBolusType(): Bolus.Type =
when (this) {
NORMAL -> Bolus.Type.NORMAL
SMB -> Bolus.Type.SMB
PRIMING -> Bolus.Type.PRIMING
}
}
enum class EventType {
MEAL_BOLUS,
BOLUS_WIZARD,
CORRECTION_BOLUS,
CARBS_CORRECTION;
fun toDBbEventType(): TherapyEvent.Type =
when (this) {
MEAL_BOLUS -> TherapyEvent.Type.MEAL_BOLUS
BOLUS_WIZARD -> TherapyEvent.Type.BOLUS_WIZARD
CORRECTION_BOLUS -> TherapyEvent.Type.CORRECTION_BOLUS
CARBS_CORRECTION -> TherapyEvent.Type.CARBS_CORRECTION
}
}
fun createTherapyEvent(): TherapyEvent =
TherapyEvent(
timestamp = timestamp,
type = eventType.toDBbEventType(),
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL,
note = notes,
glucose = mgdlGlucose,
glucoseType = glucoseType?.toDbMeterType()
)
fun createBolus(): Bolus? = fun createBolus(): Bolus? =
if (insulin != 0.0) if (insulin != 0.0)
Bolus( Bolus(
timestamp = timestamp, timestamp = bolusTimestamp ?: timestamp,
amount = insulin, amount = insulin,
type = bolusType, type = bolusType.toDBbBolusType(),
isBasalInsulin = false isBasalInsulin = false
) )
else null else null
@ -60,12 +106,26 @@ class DetailedBolusInfo {
fun createCarbs(): Carbs? = fun createCarbs(): Carbs? =
if (carbs != 0.0) if (carbs != 0.0)
Carbs( Carbs(
timestamp = timestamp, timestamp = carbsTimestamp ?: T.mins(timestamp).msecs(),
amount = carbs, amount = carbs,
duration = 0 duration = carbsDuration
) )
else null else null
fun insertMealLinkTransaction(): InsertMealLinkTransaction {
// For NS make sure timestamps of bolus and carbs are different to avoid unwanted deduplication
bolusTimestamp = bolusTimestamp ?: timestamp
carbsTimestamp = carbsTimestamp ?: timestamp
if (bolusTimestamp == carbsTimestamp) carbsTimestamp = carbsTimestamp!! + 1000
return InsertMealLinkTransaction(
bolus = createBolus(),
carbs = createCarbs(),
bolusCalculatorResult = bolusCalculatorResult,
therapyEvent = createTherapyEvent(),
superBolusTemporaryBasal = superBolusTemporaryBasal
)
}
fun toJsonString(): String = fun toJsonString(): String =
Gson().toJson(this) Gson().toJson(this)

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.interfaces package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.Iob import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.db.Treatment import info.nightscout.androidaps.db.Treatment
import org.json.JSONObject import org.json.JSONObject
@ -27,4 +28,5 @@ interface InsulinInterface : ConfigExportImportInterface{
val dia: Double val dia: Double
fun iobCalcForTreatment(treatment: Treatment, time: Long, dia: Double): Iob fun iobCalcForTreatment(treatment: Treatment, time: Long, dia: Double): Iob
fun iobCalcForTreatment(bolus: Bolus, time: Long, dia: Double): Iob
} }

View file

@ -10,7 +10,7 @@ class PumpDescription() {
setPumpDescription(pumpType) setPumpDescription(pumpType)
} }
var pumpType = PumpType.GenericAAPS var pumpType = PumpType.GENERIC_AAPS
var isBolusCapable = false var isBolusCapable = false
var bolusStep = 0.0 var bolusStep = 0.0
var isExtendedBolusCapable = false var isExtendedBolusCapable = false
@ -72,29 +72,27 @@ class PumpDescription() {
fun setPumpDescription(pumpType: PumpType) { fun setPumpDescription(pumpType: PumpType) {
resetSettings() resetSettings()
this.pumpType = pumpType this.pumpType = pumpType
val pumpCapability = pumpType.pumpCapability val pumpCapability = pumpType.pumpCapability ?: return
isBolusCapable = pumpCapability.hasCapability(PumpCapability.Bolus) isBolusCapable = pumpCapability.hasCapability(PumpCapability.Bolus)
bolusStep = pumpType.bolusSize bolusStep = pumpType.bolusSize
isExtendedBolusCapable = pumpCapability.hasCapability(PumpCapability.ExtendedBolus) isExtendedBolusCapable = pumpCapability.hasCapability(PumpCapability.ExtendedBolus)
extendedBolusStep = pumpType.extendedBolusSettings.step pumpType.extendedBolusSettings?.step?.let { extendedBolusStep = it }
extendedBolusDurationStep = pumpType.extendedBolusSettings.durationStep.toDouble() pumpType.extendedBolusSettings?.durationStep?.let { extendedBolusDurationStep = it.toDouble() }
extendedBolusMaxDuration = pumpType.extendedBolusSettings.maxDuration.toDouble() pumpType.extendedBolusSettings?.maxDuration?.let { extendedBolusMaxDuration = it.toDouble() }
isTempBasalCapable = pumpCapability.hasCapability(PumpCapability.TempBasal) isTempBasalCapable = pumpCapability.hasCapability(PumpCapability.TempBasal)
if (pumpType.pumpTempBasalType == PumpTempBasalType.Percent) { if (pumpType.pumpTempBasalType == PumpTempBasalType.Percent) {
tempBasalStyle = PERCENT tempBasalStyle = PERCENT
maxTempPercent = pumpType.tbrSettings.maxDose.toInt() pumpType.tbrSettings?.maxDose?.let { maxTempPercent = it.toInt() }
tempPercentStep = pumpType.tbrSettings.step.toInt() pumpType.tbrSettings?.step?.let { tempPercentStep = it.toInt() }
} else { } else {
tempBasalStyle = ABSOLUTE tempBasalStyle = ABSOLUTE
maxTempAbsolute = pumpType.tbrSettings.maxDose pumpType.tbrSettings?.maxDose?.let { maxTempAbsolute = it }
tempAbsoluteStep = pumpType.tbrSettings.step pumpType.tbrSettings?.step?.let { tempAbsoluteStep = it }
} }
tempDurationStep = pumpType.tbrSettings.durationStep pumpType.tbrSettings?.durationStep?.let { tempDurationStep = it }
tempMaxDuration = pumpType.tbrSettings.maxDuration pumpType.tbrSettings?.maxDuration?.let { tempMaxDuration = it }
tempDurationStep15mAllowed = pumpType.specialBasalDurations pumpType.specialBasalDurations?.hasCapability(PumpCapability.BasalRate_Duration15minAllowed)?.let { tempDurationStep15mAllowed = it }
.hasCapability(PumpCapability.BasalRate_Duration15minAllowed) pumpType.specialBasalDurations?.hasCapability(PumpCapability.BasalRate_Duration30minAllowed)?.let { tempDurationStep30mAllowed = it }
tempDurationStep30mAllowed = pumpType.specialBasalDurations
.hasCapability(PumpCapability.BasalRate_Duration30minAllowed)
isSetBasalProfileCapable = pumpCapability.hasCapability(PumpCapability.BasalProfileSet) isSetBasalProfileCapable = pumpCapability.hasCapability(PumpCapability.BasalProfileSet)
basalStep = pumpType.baseBasalStep basalStep = pumpType.baseBasalStep
basalMinimumRate = pumpType.baseBasalMinValue basalMinimumRate = pumpType.baseBasalMinValue

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.logging package info.nightscout.androidaps.logging
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
import info.nightscout.androidaps.database.transactions.UserEntryTransaction import info.nightscout.androidaps.database.transactions.UserEntryTransaction
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -38,9 +38,9 @@ class UserEntryLogger @Inject constructor(
) )
} }
fun log(action: Action, vararg listvalues: ValueWithUnit) { fun log(action: Action, vararg listValues: ValueWithUnit) {
val values = mutableListOf<ValueWithUnit>() val values = mutableListOf<ValueWithUnit>()
for (v in listvalues){ for (v in listValues){
if (v.condition) values.add(v) if (v.condition) values.add(v)
} }
compositeDisposable += repository.runTransaction(UserEntryTransaction( compositeDisposable += repository.runTransaction(UserEntryTransaction(

View file

@ -338,7 +338,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
} }
// always report hightemp // always report hightemp
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
if (percent.toDouble() == pumpLimit) { if (percent.toDouble() == pumpLimit) {
aapsLogger.debug(LTag.APS, "TRUE: Pump limit") aapsLogger.debug(LTag.APS, "TRUE: Pump limit")
return true return true
@ -374,7 +374,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
} }
// always report hightemp // always report hightemp
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
if (rate == pumpLimit) { if (rate == pumpLimit) {
aapsLogger.debug(LTag.APS, "TRUE: Pump limit") aapsLogger.debug(LTag.APS, "TRUE: Pump limit")
return true return true

View file

@ -80,7 +80,7 @@ class RunningConfiguration @Inject constructor(
} }
if (configuration.has("pump")) { if (configuration.has("pump")) {
val pumpType = JsonHelper.safeGetString(configuration, "pump", PumpType.GenericAAPS.description) val pumpType = JsonHelper.safeGetString(configuration, "pump", PumpType.GENERIC_AAPS.description)
sp.putString(R.string.key_virtualpump_type, pumpType) sp.putString(R.string.key_virtualpump_type, pumpType)
activePlugin.activePump.pumpDescription.setPumpDescription(PumpType.getByDescription(pumpType)) activePlugin.activePump.pumpDescription.setPumpDescription(PumpType.getByDescription(pumpType))
aapsLogger.debug(LTag.CORE, "Changing pump type to $pumpType") aapsLogger.debug(LTag.CORE, "Changing pump type to $pumpType")

View file

@ -4,6 +4,8 @@ import android.os.Build;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.gson.Gson;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -17,7 +19,10 @@ import info.nightscout.androidaps.core.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.entities.Carbs;
import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.database.entities.GlucoseValue;
import info.nightscout.androidaps.database.entities.MealLinkLoaded;
import info.nightscout.androidaps.database.entities.TemporaryTarget; import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.entities.TherapyEvent; import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.db.DbRequest;
@ -245,6 +250,7 @@ public class NSUpload {
} }
public void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) { public void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) {
throw new IllegalStateException("DO NOT USE");
/* /*
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
try { try {
@ -271,10 +277,60 @@ public class NSUpload {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp); uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp);
*/ */
} }
public void uploadMealLinkRecord(MealLinkLoaded mealLinkLoaded) {
Bolus bolus = mealLinkLoaded.getBolus();
Carbs carbs = mealLinkLoaded.getCarbs();
TherapyEvent therapyEvent = mealLinkLoaded.getTherapyEvent();
if (bolus != null && therapyEvent != null && bolus.getAmount() > 0) {
try {
JSONObject data = new JSONObject();
data.put("eventType", therapyEvent.getType().getText());
data.put("insulin", bolus.getAmount());
data.put("created_at", DateUtil.toISOString(bolus.getTimestamp()));
data.put("date", bolus.getTimestamp());
data.put("isSMB", bolus.getType() == Bolus.Type.SMB);
if (bolus.getInterfaceIDs().getPumpId() != null)
data.put("pumpId", bolus.getInterfaceIDs().getPumpId());
if (therapyEvent.getGlucose() != null)
data.put("glucose", therapyEvent.getGlucose());
if (therapyEvent.getGlucoseType() != null)
data.put("glucoseType", therapyEvent.getGlucoseType().getText());
if (mealLinkLoaded.getBolusCalculatorResult() != null)
data.put("bolusCalc", new Gson().toJson(mealLinkLoaded.getBolusCalculatorResult()));
if (therapyEvent.getNote() != null)
data.put("notes", therapyEvent.getNote());
uploadCareportalEntryToNS(data, bolus.getTimestamp());
} catch (JSONException e) {
e.printStackTrace();
}
}
if (carbs != null && therapyEvent != null && carbs.getAmount() > 0) {
try {
JSONObject data = new JSONObject();
data.put("eventType", therapyEvent.getType().getText());
data.put("carbs", carbs.getAmount());
data.put("created_at", DateUtil.toISOString(carbs.getTimestamp()));
data.put("date", carbs.getTimestamp());
if (carbs.getDuration() != 0)
data.put("duration", carbs.getDuration());
if (carbs.getInterfaceIDs().getPumpId() != null)
data.put("pumpId", carbs.getInterfaceIDs().getPumpId());
if (therapyEvent.getGlucose() != null)
data.put("glucose", therapyEvent.getGlucose());
if (therapyEvent.getGlucoseType() != null)
data.put("glucoseType", therapyEvent.getGlucoseType().getText());
if (therapyEvent.getNote() != null)
data.put("notes", therapyEvent.getNote());
uploadCareportalEntryToNS(data, carbs.getTimestamp());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) { public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) {
try { try {
JSONObject data = getJson(profileSwitch); JSONObject data = getJson(profileSwitch);

View file

@ -16,7 +16,6 @@ import info.nightscout.androidaps.core.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
@ -420,7 +419,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(new Treatment()); bolusingEvent.setT(new Treatment());
bolusingEvent.getT().isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; bolusingEvent.getT().isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
bolusingEvent.setPercent(100); bolusingEvent.setPercent(100);
rxBus.send(bolusingEvent); rxBus.send(bolusingEvent);

View file

@ -1,49 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common.data;
/**
* Created by andy on 02/05/2018.
*/
public class DoseSettings {
private final double step;
private final int durationStep;
private final int maxDuration;
private final double minDose;
private final Double maxDose;
public DoseSettings(double step, int durationStep, int maxDuration, double minDose, Double maxDose)
{
this.step = step;
this.durationStep = durationStep;
this.maxDuration = maxDuration;
this.minDose = minDose;
this.maxDose = maxDose;
}
public DoseSettings(double step, int durationStep, int maxDuration, double minDose)
{
this(step, durationStep, maxDuration, minDose, Double.MAX_VALUE);
}
public double getStep() {
return step;
}
public int getDurationStep() {
return durationStep;
}
public int getMaxDuration() {
return maxDuration;
}
public double getMinDose() {
return minDose;
}
public Double getMaxDose() {
return maxDose;
}
}

View file

@ -0,0 +1,3 @@
package info.nightscout.androidaps.plugins.pump.common.data
class DoseSettings constructor(val step: Double, val durationStep: Int, val maxDuration: Int, val minDose: Double, val maxDose: Double = Double.MAX_VALUE)

View file

@ -1,69 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common.defs;
/**
* Created by andy on 03/05/2018.
*/
public enum PumpCapability {
Bolus, // isBolusCapable
ExtendedBolus, // isExtendedBolusCapable
TempBasal, // isTempBasalCapable
BasalProfileSet, // isSetBasalProfileCapable
Refill, // isRefillingCapable
ReplaceBattery, // isBatteryReplaceable
StoreCarbInfo, // storesCarbInfo
TDD, // supportsTDDs
ManualTDDLoad, // needsManualTDDLoad
BasalRate30min, // is30minBasalRatesCapable
// grouped by pump
VirtualPumpCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery), //
ComboCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad), //
DanaCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad), //
DanaWithHistoryCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, StoreCarbInfo, TDD, ManualTDDLoad), //
InsightCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, BasalRate30min), //
MedtronicCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD), //
OmnipodCapabilities(Bolus, TempBasal, BasalProfileSet, BasalRate30min), //
YpsomedCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad),
// BasalRates (separately grouped)
BasalRate_Duration15minAllowed, //
BasalRate_Duration30minAllowed, //
BasalRate_Duration15and30minAllowed(BasalRate_Duration15minAllowed, BasalRate_Duration30minAllowed), //
BasalRate_Duration15and30minNotAllowed, //
;
PumpCapability[] children;
PumpCapability() {
}
PumpCapability(PumpCapability... children) {
this.children = children;
}
public boolean hasCapability(PumpCapability capability) {
// we can only check presense of simple capabilities
if (capability.children != null)
return false;
if (this == capability)
return true;
if (this.children != null) {
for (PumpCapability child : children) {
if (child == capability)
return true;
}
return false;
} else
return false;
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.pump.common.defs
import info.nightscout.androidaps.plugins.pump.common.defs.PumpCapability
/**
* Created by andy on 03/05/2018.
*/
enum class PumpCapability {
Bolus, // isBolusCapable
ExtendedBolus, // isExtendedBolusCapable
TempBasal, // isTempBasalCapable
BasalProfileSet, // isSetBasalProfileCapable
Refill, // isRefillingCapable
ReplaceBattery, // isBatteryReplaceable
StoreCarbInfo, // storesCarbInfo
TDD, // supportsTDDs
ManualTDDLoad, // needsManualTDDLoad
BasalRate30min, // is30minBasalRatesCapable
// grouped by pump
MDI(arrayOf(Bolus)),
VirtualPumpCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery)),
ComboCapabilities(arrayOf(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad)),
DanaCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad)),
DanaWithHistoryCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, StoreCarbInfo, TDD, ManualTDDLoad)),
InsightCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, BasalRate30min)),
MedtronicCapabilities(arrayOf(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD)),
OmnipodCapabilities(arrayOf(Bolus, TempBasal, BasalProfileSet, BasalRate30min)),
YpsomedCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad)), // BasalRates (separately grouped)
BasalRate_Duration15minAllowed,
BasalRate_Duration30minAllowed,
BasalRate_Duration15and30minAllowed(arrayOf(BasalRate_Duration15minAllowed, BasalRate_Duration30minAllowed)),
BasalRate_Duration15and30minNotAllowed;
var children: ArrayList<PumpCapability> = ArrayList()
constructor() { children.add(this)}
constructor(list: Array<PumpCapability>) {
children.addAll(list)
}
fun hasCapability(capability: PumpCapability): Boolean = children.contains(capability)
}

View file

@ -1,481 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common.defs;
import java.util.HashMap;
import java.util.Map;
import info.nightscout.androidaps.core.R;
import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.pump.common.data.DoseSettings;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
/**
* Created by andy on 02/05/2018.
* <p>
* Most of this defintions is intended for VirtualPump only, but they can be used by other plugins.
*/
public enum PumpType {
GenericAAPS("Generic AAPS", ManufacturerType.AndroidAPS, "VirutalPump", 0.1d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, //
new DoseSettings(10, 30, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), //
// Cellnovo
Cellnovo1("Cellnovo", ManufacturerType.Cellnovo, "Cellnovo", 0.05d, null, //
new DoseSettings(0.05d, 30, 24 * 60, 1d, null),
PumpTempBasalType.Percent,
new DoseSettings(5, 30, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), //
// Accu-Chek
AccuChekCombo("Accu-Chek Combo", ManufacturerType.Roche, "Combo", 0.1d, null, //
new DoseSettings(0.1d, 15, 12 * 60, 0.1d), //
PumpTempBasalType.Percent,
new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), //
AccuChekSpirit("Accu-Chek Spirit", ManufacturerType.Roche, "Spirit", 0.1d, null, //
new DoseSettings(0.1d, 15, 12 * 60, 0.1d), //
PumpTempBasalType.Percent,
new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), //
AccuChekInsight("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.05d, DoseStepSize.InsightBolus, //
new DoseSettings(0.05d, 15, 24 * 60, 0.05d), //
PumpTempBasalType.Percent,
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.02d, 0.01d, null, PumpCapability.InsightCapabilities), //
AccuChekInsightBluetooth("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.01d, null, //
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
PumpTempBasalType.Percent,
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), //
AccuChekSolo("Accu-Chek Solo", ManufacturerType.Roche, "Solo", 0.01d, null, //
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
PumpTempBasalType.Percent,
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), //
// Animas
AnimasVibe("Animas Vibe", ManufacturerType.Animas, "Vibe", 0.05d, null, // AnimasBolus?
new DoseSettings(0.05d, 30, 12 * 60, 0.05d), //
PumpTempBasalType.Percent, //
new DoseSettings(10, 30, 24 * 60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), //
AnimasPing("Animas Ping", "Ping", AnimasVibe),
// Dana
DanaR("DanaR", ManufacturerType.Sooil, "DanaR", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, //
0.04d, 0.01d, null, PumpCapability.DanaCapabilities),
DanaRKorean("DanaR Korean", ManufacturerType.Sooil, "DanaRKorean", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, //
0.1d, 0.01d, null, PumpCapability.DanaCapabilities),
DanaRS("DanaRS", ManufacturerType.Sooil, "DanaRS", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities),
DanaRv2("DanaRv2", "DanaRv2", DanaRS),
// Insulet
Omnipod_Eros("Omnipod", ManufacturerType.Insulet, "Eros", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, null, 0.05d, null, PumpCapability.OmnipodCapabilities, true),
Omnipod_Dash("Omnipod", ManufacturerType.Insulet, "Dash", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, null, 0.05d, null, PumpCapability.OmnipodCapabilities, false),
// Medtronic
Medtronic_512_712("Medtronic 512/712", ManufacturerType.Medtronic, "512/712", 0.1d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, 0.05d, null, PumpCapability.MedtronicCapabilities), //
Medtronic_515_715("Medtronic 515/715", "515/715", Medtronic_512_712),
Medtronic_522_722("Medtronic 522/722", "522/722", Medtronic_512_712),
Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", ManufacturerType.Medtronic, "523/723 (Revel)", 0.05d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.MedtronicCapabilities), //
Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", "554/754 (Veo)", Medtronic_523_723_Revel), // TODO
Medtronic_640G("Medtronic 640G", ManufacturerType.Medtronic, "640G", 0.025d, null, //
new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), //
// Tandem
TandemTSlim("Tandem t:slim", ManufacturerType.Tandem, "t:slim", 0.01d, null, //
new DoseSettings(0.01d, 15, 8 * 60, 0.4d),
PumpTempBasalType.Percent,
new DoseSettings(1, 15, 8 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities),
TandemTFlex("Tandem t:flex", "t:flex", TandemTSlim), //
TandemTSlimG4("Tandem t:slim G4", "t:slim G4", TandemTSlim), //
TandemTSlimX2("Tandem t:slim X2", "t:slim X2", TandemTSlim), //
// Ypsomed/myLife
YpsoPump("YpsoPump", ManufacturerType.Ypsomed, "Ypsopump", 0.1d, null, //
new DoseSettings(0.1d, 15, 12 * 60, 0.1d), //
PumpTempBasalType.Percent,
new DoseSettings(1, 15, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.02d, 40.0d, 0.01d, DoseStepSize.YpsopumpBasal, PumpCapability.YpsomedCapabilities),
// MDI
MDI("MDI", ManufacturerType.AndroidAPS, "MDI");
private final String description;
private ManufacturerType manufacturer;
private String model;
private double bolusSize;
private DoseStepSize specialBolusSize;
private DoseSettings extendedBolusSettings;
private PumpTempBasalType pumpTempBasalType;
private DoseSettings tbrSettings;
private PumpCapability specialBasalDurations;
private double baseBasalMinValue; //
private Double baseBasalMaxValue;
private double baseBasalStep; //
private DoseStepSize baseBasalSpecialSteps; //
private PumpCapability pumpCapability;
private boolean hasCustomUnreachableAlertCheck;
private PumpType parent;
private static final Map<String, PumpType> mapByDescription;
static {
mapByDescription = new HashMap<>();
for (PumpType pumpType : values()) {
mapByDescription.put(pumpType.getDescription(), pumpType);
}
}
PumpType(String description, String model, PumpType parent) {
this.description = description;
this.parent = parent;
this.model = model;
}
PumpType(String description, ManufacturerType manufacturer, String model) {
this.description = description;
this.manufacturer = manufacturer;
this.model = model;
}
PumpType(String description, String model, PumpType parent, PumpCapability pumpCapability) {
this.description = description;
this.parent = parent;
this.pumpCapability = pumpCapability;
parent.model = model;
}
PumpType(String description,
ManufacturerType manufacturer,
String model,
double bolusSize,
DoseStepSize specialBolusSize, //
DoseSettings extendedBolusSettings, //
PumpTempBasalType pumpTempBasalType,
DoseSettings tbrSettings,
PumpCapability specialBasalDurations, //
double baseBasalMinValue,
double baseBasalStep,
DoseStepSize baseBasalSpecialSteps,
PumpCapability pumpCapability) {
this(description, manufacturer, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability);
}
PumpType(String description,
ManufacturerType manufacturer,
String model,
double bolusSize,
DoseStepSize specialBolusSize, //
DoseSettings extendedBolusSettings, //
PumpTempBasalType pumpTempBasalType,
DoseSettings tbrSettings,
PumpCapability specialBasalDurations, //
double baseBasalMinValue,
Double baseBasalMaxValue,
double baseBasalStep,
DoseStepSize baseBasalSpecialSteps,
PumpCapability pumpCapability) {
this(description, manufacturer, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType,
tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep,
baseBasalSpecialSteps, pumpCapability, false);
}
PumpType(String description,
ManufacturerType manufacturer,
String model,
double bolusSize,
DoseStepSize specialBolusSize, //
DoseSettings extendedBolusSettings, //
PumpTempBasalType pumpTempBasalType,
DoseSettings tbrSettings,
PumpCapability specialBasalDurations, //
double baseBasalMinValue,
Double baseBasalMaxValue,
double baseBasalStep,
DoseStepSize baseBasalSpecialSteps, //
PumpCapability pumpCapability,
boolean hasCustomUnreachableAlertCheck) {
this.description = description;
this.manufacturer = manufacturer;
this.model = model;
this.bolusSize = bolusSize;
this.specialBolusSize = specialBolusSize;
this.extendedBolusSettings = extendedBolusSettings;
this.pumpTempBasalType = pumpTempBasalType;
this.tbrSettings = tbrSettings;
this.specialBasalDurations = specialBasalDurations;
this.baseBasalMinValue = baseBasalMinValue;
this.baseBasalMaxValue = baseBasalMaxValue;
this.baseBasalStep = baseBasalStep;
this.baseBasalSpecialSteps = baseBasalSpecialSteps;
this.pumpCapability = pumpCapability;
this.hasCustomUnreachableAlertCheck = hasCustomUnreachableAlertCheck;
}
public boolean getHasCustomUnreachableAlertCheck() {
return hasCustomUnreachableAlertCheck;
}
public String getDescription() {
return description;
}
public ManufacturerType getManufacturer() {
return isParentSet() ? parent.manufacturer : manufacturer;
}
public String getModel() {
return isParentSet() ? parent.model : model;
}
public PumpCapability getPumpCapability() {
if (isParentSet())
return this.pumpCapability == null ? parent.pumpCapability : pumpCapability;
else
return this.pumpCapability;
}
public double getBolusSize() {
return isParentSet() ? parent.bolusSize : bolusSize;
}
public DoseStepSize getSpecialBolusSize() {
return isParentSet() ? parent.specialBolusSize : specialBolusSize;
}
public DoseSettings getExtendedBolusSettings() {
return isParentSet() ? parent.extendedBolusSettings : extendedBolusSettings;
}
public PumpTempBasalType getPumpTempBasalType() {
return isParentSet() ? parent.pumpTempBasalType : pumpTempBasalType;
}
public DoseSettings getTbrSettings() {
return isParentSet() ? parent.tbrSettings : tbrSettings;
}
public double getBaseBasalMinValue() {
return isParentSet() ? parent.baseBasalMinValue : baseBasalMinValue;
}
public Double getBaseBasalMaxValue() {
return isParentSet() ? parent.baseBasalMaxValue : baseBasalMaxValue;
}
public double getBaseBasalStep() {
return isParentSet() ? parent.baseBasalStep : baseBasalStep;
}
public DoseStepSize getBaseBasalSpecialSteps() {
return isParentSet() ? parent.baseBasalSpecialSteps : baseBasalSpecialSteps;
}
public PumpType getParent() {
return parent;
}
private boolean isParentSet() {
return this.parent != null;
}
public static PumpType getByDescription(String desc) {
if (mapByDescription.containsKey(desc)) {
return mapByDescription.get(desc);
} else {
return PumpType.GenericAAPS;
}
}
public String getFullDescription(String i18nTemplate, boolean hasExtendedBasals, ResourceHelper resourceHelper) {
String unit = getPumpTempBasalType() == PumpTempBasalType.Percent ? "%" : "";
DoseSettings eb = getExtendedBolusSettings();
DoseSettings tbr = getTbrSettings();
String extendedNote = hasExtendedBasals ? resourceHelper.gs(R.string.def_extended_note) : "";
return String.format(i18nTemplate, //
getStep("" + getBolusSize(), getSpecialBolusSize()), //
eb.getStep(), eb.getDurationStep(), eb.getMaxDuration() / 60, //
getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), //
tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit,
tbr.getDurationStep(), tbr.getMaxDuration() / 60, extendedNote);
}
private String getBaseBasalRange() {
Double maxValue = getBaseBasalMaxValue();
return maxValue == null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue;
}
private String getStep(String step, DoseStepSize stepSize) {
if (stepSize != null)
return step + " [" + stepSize.getDescription() + "] *";
else
return "" + step;
}
public boolean hasExtendedBasals() {
return ((getBaseBasalSpecialSteps() != null) || (getSpecialBolusSize() != null));
}
public PumpCapability getSpecialBasalDurations() {
if (isParentSet()) {
return parent.getSpecialBasalDurations();
} else {
return specialBasalDurations == null ? //
PumpCapability.BasalRate_Duration15and30minNotAllowed : specialBasalDurations;
}
}
public double determineCorrectBolusSize(double bolusAmount) {
if (bolusAmount == 0.0d) {
return bolusAmount;
}
double bolusStepSize = getBolusSize();
if (getSpecialBolusSize() != null) {
DoseStepSize specialBolusSize = getSpecialBolusSize();
bolusStepSize = specialBolusSize.getStepSizeForAmount(bolusAmount);
}
return Round.roundTo(bolusAmount, bolusStepSize);
}
public double determineCorrectBolusStepSize(double bolusAmount) {
DoseStepSize specialBolusSize = getSpecialBolusSize();
if (specialBolusSize != null)
return specialBolusSize.getStepSizeForAmount(bolusAmount);
return getBolusSize();
}
public double determineCorrectExtendedBolusSize(double bolusAmount) {
if (bolusAmount == 0.0d) {
return bolusAmount;
}
double bolusStepSize;
if (getExtendedBolusSettings() == null) { // this should be never null
return 0.0d;
}
DoseSettings extendedBolusSettings = getExtendedBolusSettings();
bolusStepSize = extendedBolusSettings.getStep();
if (bolusAmount > extendedBolusSettings.getMaxDose()) {
bolusAmount = extendedBolusSettings.getMaxDose();
}
return Round.roundTo(bolusAmount, bolusStepSize);
}
public double determineCorrectBasalSize(double basalAmount) {
if (basalAmount == 0.0d) {
return basalAmount;
}
double basalStepSize;
if (getBaseBasalSpecialSteps() == null) {
basalStepSize = getBaseBasalStep();
} else {
DoseStepSize specialBolusSize = getBaseBasalSpecialSteps();
basalStepSize = specialBolusSize.getStepSizeForAmount(basalAmount);
}
if (basalAmount > getTbrSettings().getMaxDose())
basalAmount = getTbrSettings().getMaxDose().doubleValue();
return Round.roundTo(basalAmount, basalStepSize);
}
}

View file

@ -0,0 +1,411 @@
package info.nightscout.androidaps.plugins.pump.common.defs
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.pump.common.data.DoseSettings
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.min
@Suppress("unused")
enum class PumpType {
GENERIC_AAPS(description = "Generic AAPS",
manufacturer = ManufacturerType.AndroidAPS,
model = "VirtualPump",
bolusSize = 0.1,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 30, 24 * 60, 0.0, 500.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.01,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
CELLNOVO(description = "Cellnovo",
manufacturer = ManufacturerType.Cellnovo,
model = "Cellnovo",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 24 * 60, 1.0),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(5.0, 30, 24 * 60, 0.0, 200.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.05,
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
ACCU_CHEK_COMBO(description = "Accu-Chek Combo",
manufacturer = ManufacturerType.Roche,
model = "Combo",
bolusSize = 0.1,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 15, 12 * 60, 0.0, 500.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.01,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.ComboBasal,
pumpCapability = PumpCapability.ComboCapabilities),
ACCU_CHEK_SPIRIT(description = "Accu-Chek Spirit",
manufacturer = ManufacturerType.Roche,
model = "Spirit",
bolusSize = 0.1,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 15, 12 * 60, 0.0, 500.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.01,
baseBasalStep = 0.1,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
ACCU_CHEK_INSIGHT(description = "Accu-Chek Insight",
manufacturer = ManufacturerType.Roche,
model = "Insight",
bolusSize = 0.05,
specialBolusSize = DoseStepSize.InsightBolus,
extendedBolusSettings = DoseSettings(0.05, 15, 24 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 15, 24 * 60, 0.0, 250.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.02,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.InsightCapabilities),
ACCU_CHEK_INSIGHT_BLUETOOTH(description = "Accu-Chek Insight",
manufacturer = ManufacturerType.Roche,
model = "Insight",
bolusSize = 0.01,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.01, 15, 24 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 15, 24 * 60, 0.0, 250.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.02,
baseBasalMaxValue = null,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.InsightBolus,
pumpCapability = PumpCapability.InsightCapabilities),
ACCU_CHEK_SOLO(description = "Accu-Chek Solo",
manufacturer = ManufacturerType.Roche,
model = "Solo",
bolusSize = 0.01,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.01, 15, 24 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 15, 24 * 60, 0.0, 250.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.02,
baseBasalMaxValue = null,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.InsightBolus,
pumpCapability = PumpCapability.InsightCapabilities),
ANIMAS_VIBE(description = "Animas Vibe",
manufacturer = ManufacturerType.Animas,
model = "Vibe",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 12 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 30, 24 * 60, 0.0, 300.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.025,
baseBasalMaxValue = 5.0,
baseBasalStep = 0.0,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
ANIMAS_PING(description = "Animas Ping", model = "Ping", parent = ANIMAS_VIBE),
DANA_R(description = "DanaR",
manufacturer = ManufacturerType.Sooil,
model = "DanaR",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 60, 24 * 60, 0.0, 200.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minNotAllowed,
baseBasalMinValue = 0.04,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaCapabilities),
DANA_R_KOREAN(description = "DanaR Korean",
manufacturer = ManufacturerType.Sooil,
model = "DanaRKorean",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 60, 24 * 60, 0.0, 200.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minNotAllowed,
baseBasalMinValue = 0.1,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaCapabilities),
DANA_RS(description = "DanaRS",
manufacturer = ManufacturerType.Sooil,
model = "DanaRS",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(10.0, 60, 24 * 60, 0.0, 200.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.04,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaWithHistoryCapabilities),
DANA_RV2(description = "DanaRv2", model = "DanaRv2", parent = DANA_RS),
OMNIPOD_EROS(description = "Omnipod Eros",
manufacturer = ManufacturerType.Insulet,
model = "Eros",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Absolute,
tbrSettings = DoseSettings(0.05, 30, 12 * 60, 0.0, 30.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.05,
baseBasalMaxValue = null,
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.OmnipodCapabilities,
hasCustomUnreachableAlertCheck = true),
OMNIPOD_DASH(description = "Omnipod Dash",
manufacturer = ManufacturerType.Insulet,
model = "Dash",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Absolute,
tbrSettings = DoseSettings(0.05, 30, 12 * 60, 0.0, 30.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.05,
baseBasalMaxValue = null,
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.OmnipodCapabilities,
hasCustomUnreachableAlertCheck = false),
MEDTRONIC_512_712(description = "Medtronic 512/712",
manufacturer = ManufacturerType.Medtronic,
model = "512/712",
bolusSize = 0.1,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Absolute,
tbrSettings = DoseSettings(0.05, 30, 24 * 60, 0.0, 35.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.05,
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.MedtronicCapabilities),
MEDTRONIC_515_715(description = "Medtronic 515/715",
model = "515/715",
parent = MEDTRONIC_512_712),
MEDTRONIC_522_722(description = "Medtronic 522/722",
model = "522/722",
parent = MEDTRONIC_512_712),
MEDTRONIC_523_723_REVEL(description = "Medtronic 523/723 (Revel)",
manufacturer = ManufacturerType.Medtronic,
model = "523/723 (Revel)",
bolusSize = 0.05,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Absolute,
tbrSettings = DoseSettings(0.05, 30, 24 * 60, 0.0, 35.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.025,
baseBasalStep = 0.025,
baseBasalSpecialSteps = DoseStepSize.MedtronicVeoBasal,
pumpCapability = PumpCapability.MedtronicCapabilities),
MEDTRONIC_554_754_VEO(description = "Medtronic 554/754 (Veo)", model = "554/754 (Veo)", parent = MEDTRONIC_523_723_REVEL),
MEDTRONIC_640G(description = "Medtronic 640G",
manufacturer = ManufacturerType.Medtronic,
model = "640G",
bolusSize = 0.025,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.05, 30, 8 * 60, 0.05),
pumpTempBasalType = PumpTempBasalType.Absolute,
tbrSettings = DoseSettings(0.05, 30, 24 * 60, 0.0, 35.0),
specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed,
baseBasalMinValue = 0.025,
baseBasalStep = 0.025,
baseBasalSpecialSteps = DoseStepSize.MedtronicVeoBasal,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
TANDEM_T_SLIM(description = "Tandem t:slim",
manufacturer = ManufacturerType.Tandem,
model = "t:slim",
bolusSize = 0.01,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.01, 15, 8 * 60, 0.4),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(1.0, 15, 8 * 60, 0.0, 250.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.1,
baseBasalStep = 0.001,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
TANDEM_T_FLEX(description = "Tandem t:flex", model = "t:flex", parent = TANDEM_T_SLIM),
TANDEM_T_SLIM_G4(description = "Tandem t:slim G4", model = "t:slim G4", parent = TANDEM_T_SLIM),
TANDEM_T_SLIM_X2(description = "Tandem t:slim X2", model = "t:slim X2", parent = TANDEM_T_SLIM),
YPSOPUMP(description = "YpsoPump",
manufacturer = ManufacturerType.Ypsomed,
model = "Ypsopump",
bolusSize = 0.1,
specialBolusSize = null,
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpTempBasalType = PumpTempBasalType.Percent,
tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0),
specialBasalDurations = PumpCapability.BasalRate_Duration15and30minAllowed,
baseBasalMinValue = 0.02,
baseBasalMaxValue = 40.0,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.YpsopumpBasal,
pumpCapability = PumpCapability.YpsomedCapabilities),
MDI(description = "MDI",
manufacturer = ManufacturerType.AndroidAPS,
model = "MDI",
tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0),
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpCapability = PumpCapability.MDI),
// Not real pump. Used for User as a source
USER(description = "USER",
manufacturer = ManufacturerType.AndroidAPS,
model = "USER",
tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0),
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpCapability = PumpCapability.MDI);
val description: String
var manufacturer: ManufacturerType? = null
get() = parent?.manufacturer ?: field
private set
var model: String = "NONE"
get() = parent?.model ?: field
private set
var bolusSize = 0.0
get() = parent?.bolusSize ?: field
private var specialBolusSize: DoseStepSize? = null
get() = parent?.specialBolusSize ?: field
var extendedBolusSettings: DoseSettings? = null
get() = parent?.extendedBolusSettings ?: field
private set
var pumpTempBasalType: PumpTempBasalType? = null
get() = parent?.pumpTempBasalType ?: field
private set
var tbrSettings: DoseSettings? = null
get() = parent?.tbrSettings ?: field
private set
var specialBasalDurations: PumpCapability? = null
get() = parent?.specialBasalDurations ?: field
?: PumpCapability.BasalRate_Duration15and30minNotAllowed
private set
var baseBasalMinValue = 0.01
get() = parent?.baseBasalMinValue ?: field
private set
private var baseBasalMaxValue: Double? = null
get() = parent?.baseBasalMaxValue ?: field
var baseBasalStep = 1.0
get() = parent?.baseBasalStep ?: field
private set
private var baseBasalSpecialSteps: DoseStepSize? = null
get() = parent?.baseBasalSpecialSteps ?: field
var pumpCapability: PumpCapability? = null
get() = parent?.pumpCapability ?: field
private set
var hasCustomUnreachableAlertCheck = false
private set
private var parent: PumpType? = null
companion object {
fun getByDescription(desc: String): PumpType =
values().firstOrNull { it.description == desc } ?: GENERIC_AAPS
}
constructor(description: String, model: String, parent: PumpType, pumpCapability: PumpCapability? = null) {
this.description = description
this.parent = parent
this.pumpCapability = pumpCapability
parent.model = model
}
constructor(description: String,
manufacturer: ManufacturerType,
model: String,
bolusSize: Double = 0.0,
specialBolusSize: DoseStepSize? = null,
extendedBolusSettings: DoseSettings,
pumpTempBasalType: PumpTempBasalType? = null,
tbrSettings: DoseSettings,
specialBasalDurations: PumpCapability? = null,
baseBasalMinValue: Double = 0.01,
baseBasalMaxValue: Double? = null,
baseBasalStep: Double = 1.0,
baseBasalSpecialSteps: DoseStepSize? = null,
pumpCapability: PumpCapability,
hasCustomUnreachableAlertCheck: Boolean = false) {
this.description = description
this.manufacturer = manufacturer
this.model = model
this.bolusSize = bolusSize
this.specialBolusSize = specialBolusSize
this.extendedBolusSettings = extendedBolusSettings
this.pumpTempBasalType = pumpTempBasalType
this.tbrSettings = tbrSettings
this.specialBasalDurations = specialBasalDurations
this.baseBasalMinValue = baseBasalMinValue
this.baseBasalMaxValue = baseBasalMaxValue
this.baseBasalStep = baseBasalStep
this.baseBasalSpecialSteps = baseBasalSpecialSteps
this.pumpCapability = pumpCapability
this.hasCustomUnreachableAlertCheck = hasCustomUnreachableAlertCheck
}
fun getFullDescription(i18nTemplate: String, hasExtendedBasals: Boolean, resourceHelper: ResourceHelper): String {
val unit = if (pumpTempBasalType == PumpTempBasalType.Percent) "%" else ""
val eb = extendedBolusSettings ?: return "INVALID"
val tbr = tbrSettings ?: return "INVALID"
val extendedNote = if (hasExtendedBasals) resourceHelper.gs(R.string.def_extended_note) else ""
return String.format(i18nTemplate,
getStep("" + bolusSize, specialBolusSize),
eb.step, eb.durationStep, eb.maxDuration / 60,
getStep(baseBasalRange(), baseBasalSpecialSteps),
tbr.minDose.toString() + unit + "-" + tbr.maxDose + unit, tbr.step.toString() + unit,
tbr.durationStep, tbr.maxDuration / 60, extendedNote)
}
private fun baseBasalRange(): String =
if (baseBasalMaxValue == null) baseBasalMinValue.toString()
else baseBasalMinValue.toString() + "-" + baseBasalMaxValue.toString()
private fun getStep(step: String, stepSize: DoseStepSize?): String =
if (stepSize != null) step + " [" + stepSize.description + "] *"
else step
fun hasExtendedBasals(): Boolean = baseBasalSpecialSteps != null || specialBolusSize != null
fun determineCorrectBolusSize(bolusAmount: Double): Double =
Round.roundTo(bolusAmount, specialBolusSize?.getStepSizeForAmount(bolusAmount) ?: bolusSize)
fun determineCorrectBolusStepSize(bolusAmount: Double): Double =
specialBolusSize?.getStepSizeForAmount(bolusAmount) ?: bolusSize
fun determineCorrectExtendedBolusSize(bolusAmount: Double): Double {
val ebSettings = extendedBolusSettings ?: throw IllegalStateException()
return Round.roundTo(min(bolusAmount, ebSettings.maxDose), ebSettings.step)
}
fun determineCorrectBasalSize(basalAmount: Double): Double {
val tSettings = tbrSettings ?: throw IllegalStateException()
return Round.roundTo(min(basalAmount, tSettings.maxDose), baseBasalSpecialSteps?.getStepSizeForAmount(basalAmount)
?: baseBasalStep)
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.InsulinInterface
fun Bolus.iobCalc(activePlugin: ActivePluginProvider, time: Long, dia: Double): Iob {
if (!isValid) return Iob()
val insulinInterface: InsulinInterface = activePlugin.activeInsulin
return insulinInterface.iobCalcForTreatment(this, time, dia)
}

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.utils.T
import kotlin.math.roundToInt
fun Carbs.expandCarbs(): List<Carbs> =
mutableListOf<Carbs>().also { carbs ->
if (this.duration == 0L) {
carbs.add(this)
} else {
var remainingCarbs = this.amount
val ticks = T.msecs(this.duration).mins() * 4 //duration guaranteed to be integer greater zero
for (i in 0 until ticks) {
val carbTime = this.timestamp + i * 15 * 60 * 1000
val smallCarbAmount = (1.0 * remainingCarbs / (ticks - i)).roundToInt() //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs
remainingCarbs -= smallCarbAmount.toLong()
if (smallCarbAmount > 0)
carbs.add(Carbs(
timestamp = carbTime,
amount = smallCarbAmount.toDouble(),
duration = 0
))
}
}
}

View file

@ -57,7 +57,7 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface {
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject() override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
override fun model(): PumpType = PumpType.GenericAAPS override fun model(): PumpType = PumpType.GENERIC_AAPS
override fun serialNumber(): String = "1" override fun serialNumber(): String = "1"
override fun shortStatus(veryShort: Boolean): String = "" override fun shortStatus(veryShort: Boolean): String = ""
override val isFakingTempsByExtendedBoluses: Boolean = false override val isFakingTempsByExtendedBoluses: Boolean = false

View file

@ -49,12 +49,12 @@ class DetailedBolusInfoTest : TestBase() {
detailedBolusInfo.glucoseType = TherapyEvent.MeterType.FINGER detailedBolusInfo.glucoseType = TherapyEvent.MeterType.FINGER
val therapyEvent = detailedBolusInfo.createTherapyEvent() val therapyEvent = detailedBolusInfo.createTherapyEvent()
Assert.assertEquals(1000L, therapyEvent?.timestamp) Assert.assertEquals(1000L, therapyEvent.timestamp)
Assert.assertEquals(TherapyEvent.Type.NOTE, therapyEvent?.type) Assert.assertEquals(TherapyEvent.Type.NOTE, therapyEvent.type)
Assert.assertEquals(TherapyEvent.GlucoseUnit.MGDL, therapyEvent?.glucoseUnit) Assert.assertEquals(TherapyEvent.GlucoseUnit.MGDL, therapyEvent.glucoseUnit)
Assert.assertEquals("note", therapyEvent?.note) Assert.assertEquals("note", therapyEvent.note)
Assert.assertEquals(180.0, therapyEvent?.glucose) Assert.assertEquals(180.0, therapyEvent.glucose)
Assert.assertEquals(TherapyEvent.MeterType.FINGER, therapyEvent?.glucoseType) Assert.assertEquals(TherapyEvent.MeterType.FINGER, therapyEvent.glucoseType)
} }
@Test @Test
@ -110,7 +110,7 @@ class DetailedBolusInfoTest : TestBase() {
superbolusInsulin = 1.0, superbolusInsulin = 1.0,
wasTempTargetUsed = true, wasTempTargetUsed = true,
totalInsulin = 15.0, totalInsulin = 15.0,
percentageCorrection = 50.0, percentageCorrection = 50,
profileName = "profile" profileName = "profile"
) )
} }

View file

@ -6,30 +6,27 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
/**
* Created by andy on 5/13/18.
*/
class PumpDescriptionTest { class PumpDescriptionTest {
@Test fun setPumpDescription() { @Test fun setPumpDescription() {
val pumpDescription = PumpDescription() val pumpDescription = PumpDescription()
pumpDescription.setPumpDescription(PumpType.AccuChekCombo) pumpDescription.setPumpDescription(PumpType.ACCU_CHEK_COMBO)
Assert.assertEquals(pumpDescription.bolusStep, PumpType.AccuChekCombo.bolusSize, 0.1) Assert.assertEquals(pumpDescription.bolusStep, PumpType.ACCU_CHEK_COMBO.bolusSize, 0.1)
Assert.assertEquals(pumpDescription.basalMinimumRate, PumpType.AccuChekCombo.baseBasalStep, 0.1) Assert.assertEquals(pumpDescription.basalMinimumRate, PumpType.ACCU_CHEK_COMBO.baseBasalStep, 0.1)
Assert.assertEquals(pumpDescription.basalStep, PumpType.AccuChekCombo.baseBasalStep, 0.1) Assert.assertEquals(pumpDescription.basalStep, PumpType.ACCU_CHEK_COMBO.baseBasalStep, 0.1)
Assert.assertEquals(pumpDescription.extendedBolusDurationStep, PumpType.AccuChekCombo.extendedBolusSettings.durationStep.toDouble(), 0.1) Assert.assertEquals(pumpDescription.extendedBolusDurationStep, PumpType.ACCU_CHEK_COMBO.extendedBolusSettings?.durationStep?.toDouble())
Assert.assertEquals(pumpDescription.extendedBolusMaxDuration, PumpType.AccuChekCombo.extendedBolusSettings.maxDuration.toDouble(), 0.1) Assert.assertEquals(pumpDescription.extendedBolusMaxDuration, PumpType.ACCU_CHEK_COMBO.extendedBolusSettings?.maxDuration?.toDouble())
Assert.assertEquals(pumpDescription.extendedBolusStep, PumpType.AccuChekCombo.extendedBolusSettings.step, 0.1) Assert.assertEquals(pumpDescription.extendedBolusStep, PumpType.ACCU_CHEK_COMBO.extendedBolusSettings?.step)
Assert.assertEquals(pumpDescription.isExtendedBolusCapable, PumpType.AccuChekCombo.pumpCapability.hasCapability(PumpCapability.ExtendedBolus)) Assert.assertEquals(pumpDescription.isExtendedBolusCapable, PumpType.ACCU_CHEK_COMBO.pumpCapability?.hasCapability(PumpCapability.ExtendedBolus))
Assert.assertEquals(pumpDescription.isBolusCapable, PumpType.AccuChekCombo.pumpCapability.hasCapability(PumpCapability.Bolus)) Assert.assertEquals(pumpDescription.isBolusCapable, PumpType.ACCU_CHEK_COMBO.pumpCapability?.hasCapability(PumpCapability.Bolus))
Assert.assertEquals(pumpDescription.isRefillingCapable, PumpType.AccuChekCombo.pumpCapability.hasCapability(PumpCapability.Refill)) Assert.assertEquals(pumpDescription.isRefillingCapable, PumpType.ACCU_CHEK_COMBO.pumpCapability?.hasCapability(PumpCapability.Refill))
Assert.assertEquals(pumpDescription.isSetBasalProfileCapable, PumpType.AccuChekCombo.pumpCapability.hasCapability(PumpCapability.BasalProfileSet)) Assert.assertEquals(pumpDescription.isSetBasalProfileCapable, PumpType.ACCU_CHEK_COMBO.pumpCapability?.hasCapability(PumpCapability.BasalProfileSet))
Assert.assertEquals(pumpDescription.isTempBasalCapable, PumpType.AccuChekCombo.pumpCapability.hasCapability(PumpCapability.TempBasal)) Assert.assertEquals(pumpDescription.isTempBasalCapable, PumpType.ACCU_CHEK_COMBO.pumpCapability?.hasCapability(PumpCapability.TempBasal))
Assert.assertEquals(pumpDescription.maxTempPercent.toDouble(), PumpType.AccuChekCombo.tbrSettings.maxDose, 0.1) Assert.assertEquals(pumpDescription.maxTempPercent.toDouble(), PumpType.ACCU_CHEK_COMBO.tbrSettings?.maxDose)
Assert.assertEquals(pumpDescription.tempPercentStep.toDouble(), PumpType.AccuChekCombo.tbrSettings.step, 0.1) Assert.assertEquals(pumpDescription.tempPercentStep.toDouble(), PumpType.ACCU_CHEK_COMBO.tbrSettings?.step)
Assert.assertEquals(pumpDescription.tempBasalStyle, if (PumpType.AccuChekCombo.pumpTempBasalType == PumpTempBasalType.Percent) PumpDescription.PERCENT else PumpDescription.ABSOLUTE) Assert.assertEquals(pumpDescription.tempBasalStyle, if (PumpType.ACCU_CHEK_COMBO.pumpTempBasalType == PumpTempBasalType.Percent) PumpDescription.PERCENT else PumpDescription.ABSOLUTE)
Assert.assertEquals(pumpDescription.tempDurationStep.toLong(), PumpType.AccuChekCombo.tbrSettings.durationStep.toLong()) Assert.assertEquals(pumpDescription.tempDurationStep.toLong(), PumpType.ACCU_CHEK_COMBO.tbrSettings?.durationStep?.toLong())
Assert.assertEquals(pumpDescription.tempDurationStep15mAllowed, PumpType.AccuChekCombo.specialBasalDurations.hasCapability(PumpCapability.BasalRate_Duration15minAllowed)) Assert.assertEquals(pumpDescription.tempDurationStep15mAllowed, PumpType.ACCU_CHEK_COMBO.specialBasalDurations?.hasCapability(PumpCapability.BasalRate_Duration15minAllowed))
Assert.assertEquals(pumpDescription.tempDurationStep30mAllowed, PumpType.AccuChekCombo.specialBasalDurations.hasCapability(PumpCapability.BasalRate_Duration30minAllowed)) Assert.assertEquals(pumpDescription.tempDurationStep30mAllowed, PumpType.ACCU_CHEK_COMBO.specialBasalDurations?.hasCapability(PumpCapability.BasalRate_Duration30minAllowed))
} }
} }

View file

@ -49,7 +49,7 @@ class APSResultTest : TestBaseWithProfile() {
// BASAL RATE IN TEST PROFILE IS 1U/h // BASAL RATE IN TEST PROFILE IS 1U/h
// **** PERCENT pump **** // **** PERCENT pump ****
testPumpPlugin.pumpDescription.setPumpDescription(PumpType.Cellnovo1) // % based testPumpPlugin.pumpDescription.setPumpDescription(PumpType.CELLNOVO) // % based
apsResult.usePercent(true) apsResult.usePercent(true)
// closed loop mode return original request // closed loop mode return original request
@ -107,7 +107,7 @@ class APSResultTest : TestBaseWithProfile() {
Assert.assertEquals(true, apsResult.isChangeRequested) Assert.assertEquals(true, apsResult.isChangeRequested)
// **** ABSOLUTE pump **** // **** ABSOLUTE pump ****
testPumpPlugin.pumpDescription.setPumpDescription(PumpType.Medtronic_515_715) // U/h based testPumpPlugin.pumpDescription.setPumpDescription(PumpType.MEDTRONIC_515_715) // U/h based
apsResult.usePercent(false) apsResult.usePercent(false)
// open loop // open loop

View file

@ -10,7 +10,7 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.activities.TDDStatsActivity import info.nightscout.androidaps.activities.TDDStatsActivity
import info.nightscout.androidaps.dana.databinding.DanarFragmentBinding import info.nightscout.androidaps.dana.databinding.DanarFragmentBinding
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventExtendedBolusChange
import info.nightscout.androidaps.events.EventInitializationChanged import info.nightscout.androidaps.events.EventInitializationChanged
@ -105,11 +105,11 @@ class DanaFragment : DaggerFragment() {
danaPump.lastConnection = 0 danaPump.lastConnection = 0
commandQueue.readStatus("Clicked connect to pump", null) commandQueue.readStatus("Clicked connect to pump", null)
} }
if (activePlugin.activePump.pumpDescription.pumpType == PumpType.DanaRS) if (activePlugin.activePump.pumpDescription.pumpType == PumpType.DANA_RS)
binding.btconnection.setOnLongClickListener { binding.btconnection.setOnLongClickListener {
activity?.let { activity?.let {
OKDialog.showConfirmation(it, resourceHelper.gs(R.string.resetpairing)) { OKDialog.showConfirmation(it, resourceHelper.gs(R.string.resetpairing)) {
uel.log(Action.CLEAR_PAIRING_KEYS) uel.log(UserEntry.Action.CLEAR_PAIRING_KEYS)
(activePlugin.activePump as DanaPumpInterface).clearPairing() (activePlugin.activePump as DanaPumpInterface).clearPairing()
} }
} }

View file

@ -91,8 +91,8 @@ class DanaHistoryActivity : NoSplashAppCompatActivity() {
binding.status.visibility = View.GONE binding.status.visibility = View.GONE
val pump = activePlugin.activePump val pump = activePlugin.activePump
val isKorean = pump.pumpDescription.pumpType == PumpType.DanaRKorean val isKorean = pump.pumpDescription.pumpType == PumpType.DANA_R_KOREAN
val isRS = pump.pumpDescription.pumpType == PumpType.DanaRS val isRS = pump.pumpDescription.pumpType == PumpType.DANA_RS
// Types // Types
val typeList = ArrayList<TypeList>() val typeList = ArrayList<TypeList>()

View file

@ -39,9 +39,9 @@ class DanaUserOptionsActivity : NoSplashAppCompatActivity() {
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
// This is for Dana pumps only // This is for Dana pumps only
private fun isRS() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DanaRS private fun isRS() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DANA_RS
private fun isDanaR() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DanaR private fun isDanaR() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DANA_R
private fun isDanaRv2() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DanaRv2 private fun isDanaRv2() = activePlugin.activePump.pumpDescription.pumpType == PumpType.DANA_RV2
var minBacklight = 1 var minBacklight = 1

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.danar.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
@ -77,7 +76,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
getPluginDescription().description(R.string.description_pump_dana_r_korean); getPluginDescription().description(R.string.description_pump_dana_r_korean);
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
pumpDescription.setPumpDescription(PumpType.DanaRKorean); pumpDescription.setPumpDescription(PumpType.DANA_R_KOREAN);
} }
@Override @Override
@ -165,7 +164,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment(); Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; t.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t); connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
@ -326,7 +325,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
@NonNull @Override @NonNull @Override
public PumpType model() { public PumpType model() {
return PumpType.DanaRKorean; return PumpType.DANA_R_KOREAN;
} }
private PumpEnactResult cancelRealTempBasal() { private PumpEnactResult cancelRealTempBasal() {

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.danar.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
@ -82,7 +81,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
getPluginDescription().description(R.string.description_pump_dana_r_v2); getPluginDescription().description(R.string.description_pump_dana_r_v2);
useExtendedBoluses = false; useExtendedBoluses = false;
pumpDescription.setPumpDescription(PumpType.DanaRv2); pumpDescription.setPumpDescription(PumpType.DANA_RV2);
} }
@Override @Override
@ -184,7 +183,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
detailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history detailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
Treatment t = new Treatment(); Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; t.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0) if (detailedBolusInfo.insulin > 0 || carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t); connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);
@ -350,7 +349,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
@NonNull @Override @NonNull @Override
public PumpType model() { public PumpType model() {
return PumpType.DanaRv2; return PumpType.DANA_RV2;
} }
@NonNull @Override @NonNull @Override

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.db.TemporaryBasal
import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import java.util.* import java.util.*
@ -92,8 +93,8 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.BOLUS -> { info.nightscout.androidaps.dana.DanaPump.BOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.timestamp = datetime detailedBolusInfo.bolusTimestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2 detailedBolusInfo.pumpType = PumpType.DANA_RV2
detailedBolusInfo.pumpSerial = danaPump.serialNumber detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = datetime detailedBolusInfo.bolusPumpId = datetime
detailedBolusInfo.insulin = param1 / 100.0 detailedBolusInfo.insulin = param1 / 100.0
@ -105,8 +106,8 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.DUALBOLUS -> { info.nightscout.androidaps.dana.DanaPump.DUALBOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.timestamp = datetime detailedBolusInfo.bolusTimestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2 detailedBolusInfo.pumpType = PumpType.DANA_RV2
detailedBolusInfo.pumpSerial = danaPump.serialNumber detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = datetime detailedBolusInfo.bolusPumpId = datetime
detailedBolusInfo.insulin = param1 / 100.0 detailedBolusInfo.insulin = param1 / 100.0
@ -157,8 +158,8 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.CARBS -> { info.nightscout.androidaps.dana.DanaPump.CARBS -> {
val emptyCarbsInfo = DetailedBolusInfo() val emptyCarbsInfo = DetailedBolusInfo()
emptyCarbsInfo.carbs = param1.toDouble() emptyCarbsInfo.carbs = param1.toDouble()
emptyCarbsInfo.timestamp = datetime emptyCarbsInfo.carbsTimestamp = datetime
emptyCarbsInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2 emptyCarbsInfo.pumpType = PumpType.DANA_RV2
emptyCarbsInfo.pumpSerial = danaPump.serialNumber emptyCarbsInfo.pumpSerial = danaPump.serialNumber
emptyCarbsInfo.carbsPumpId = datetime emptyCarbsInfo.carbsPumpId = datetime
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false) val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false)

View file

@ -17,7 +17,6 @@ import info.nightscout.androidaps.danar.services.DanaRExecutionService;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
@ -74,7 +73,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
this.fabricPrivacy = fabricPrivacy; this.fabricPrivacy = fabricPrivacy;
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false); useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
pumpDescription.setPumpDescription(PumpType.DanaR); pumpDescription.setPumpDescription(PumpType.DANA_R);
} }
@Override @Override
@ -163,7 +162,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment(); Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; t.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t); connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
@ -324,7 +323,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
@NonNull @Override @NonNull @Override
public PumpType model() { public PumpType model() {
return PumpType.DanaR; return PumpType.DANA_R;
} }
private PumpEnactResult cancelRealTempBasal() { private PumpEnactResult cancelRealTempBasal() {

View file

@ -57,7 +57,7 @@ class TestPumpPlugin(val injector: HasAndroidInjector) : PumpInterface {
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject() override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS override fun manufacturer(): ManufacturerType = ManufacturerType.AndroidAPS
override fun model(): PumpType = PumpType.GenericAAPS override fun model(): PumpType = PumpType.GENERIC_AAPS
override fun serialNumber(): String = "1" override fun serialNumber(): String = "1"
override fun shortStatus(veryShort: Boolean): String = "" override fun shortStatus(veryShort: Boolean): String = ""
override val isFakingTempsByExtendedBoluses: Boolean = false override val isFakingTempsByExtendedBoluses: Boolean = false

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.danars.services.DanaRSService
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.db.Treatment import info.nightscout.androidaps.db.Treatment
import info.nightscout.androidaps.events.EventAppExit import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.events.EventConfigBuilderChange import info.nightscout.androidaps.events.EventConfigBuilderChange
@ -74,7 +73,7 @@ class DanaRSPlugin @Inject constructor(
private var danaRSService: DanaRSService? = null private var danaRSService: DanaRSService? = null
private var mDeviceAddress = "" private var mDeviceAddress = ""
var mDeviceName = "" var mDeviceName = ""
override val pumpDescription = PumpDescription(PumpType.DanaRS) override val pumpDescription = PumpDescription(PumpType.DANA_RS)
override fun updatePreferenceSummary(pref: Preference) { override fun updatePreferenceSummary(pref: Preference) {
super.updatePreferenceSummary(pref) super.updatePreferenceSummary(pref)
@ -280,7 +279,7 @@ class DanaRSPlugin @Inject constructor(
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 = Treatment() val t = Treatment()
t.isSMB = detailedBolusInfo.bolusType == Bolus.Type.SMB t.isSMB = 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
@ -597,7 +596,7 @@ class DanaRSPlugin @Inject constructor(
} }
override fun model(): PumpType { override fun model(): PumpType {
return PumpType.DanaRS return PumpType.DANA_RS
} }
override fun serialNumber(): String { override fun serialNumber(): String {

View file

@ -6,7 +6,6 @@ import info.nightscout.androidaps.danars.R
import info.nightscout.androidaps.danars.encryption.BleEncryption import info.nightscout.androidaps.danars.encryption.BleEncryption
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.db.ExtendedBolus import info.nightscout.androidaps.db.ExtendedBolus
@ -18,6 +17,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -133,8 +133,8 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.BOLUS -> { DanaPump.BOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.timestamp = datetime detailedBolusInfo.bolusTimestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RS detailedBolusInfo.pumpType = PumpType.DANA_RS
detailedBolusInfo.pumpSerial = danaPump.serialNumber detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = pumpId detailedBolusInfo.bolusPumpId = pumpId
detailedBolusInfo.insulin = param1 / 100.0 detailedBolusInfo.insulin = param1 / 100.0
@ -146,8 +146,8 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.DUALBOLUS -> { DanaPump.DUALBOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.timestamp = datetime detailedBolusInfo.bolusTimestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RS detailedBolusInfo.pumpType = PumpType.DANA_RS
detailedBolusInfo.pumpSerial = danaPump.serialNumber detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = pumpId detailedBolusInfo.bolusPumpId = pumpId
detailedBolusInfo.insulin = param1 / 100.0 detailedBolusInfo.insulin = param1 / 100.0
@ -209,8 +209,8 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.CARBS -> { DanaPump.CARBS -> {
val emptyCarbsInfo = DetailedBolusInfo() val emptyCarbsInfo = DetailedBolusInfo()
emptyCarbsInfo.carbs = param1.toDouble() emptyCarbsInfo.carbs = param1.toDouble()
emptyCarbsInfo.timestamp = datetime emptyCarbsInfo.carbsTimestamp = datetime
emptyCarbsInfo.pumpType = InterfaceIDs.PumpType.DANA_RS emptyCarbsInfo.pumpType = PumpType.DANA_RS
emptyCarbsInfo.pumpSerial = danaPump.serialNumber emptyCarbsInfo.pumpSerial = danaPump.serialNumber
emptyCarbsInfo.carbsPumpId = pumpId emptyCarbsInfo.carbsPumpId = pumpId
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false) val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false)

View file

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 8, "version": 8,
"identityHash": "b45eaf7386412002a6289168c3dfa06e", "identityHash": "c38f6acf42463481d39fe05be1fd3b55",
"entities": [ "entities": [
{ {
"tableName": "apsResults", "tableName": "apsResults",
@ -350,7 +350,7 @@
}, },
{ {
"tableName": "bolusCalculatorResults", "tableName": "bolusCalculatorResults",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` REAL NOT NULL, `profileName` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -553,7 +553,7 @@
{ {
"fieldPath": "percentageCorrection", "fieldPath": "percentageCorrection",
"columnName": "percentageCorrection", "columnName": "percentageCorrection",
"affinity": "REAL", "affinity": "INTEGER",
"notNull": true "notNull": true
}, },
{ {
@ -2222,7 +2222,7 @@
}, },
{ {
"tableName": "mealLinks", "tableName": "mealLinks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `bolusId` INTEGER, `carbsId` INTEGER, `bolusCalcResultId` INTEGER, `superbolusTempBasalId` INTEGER, `noteId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`carbsId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`bolusCalcResultId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`superbolusTempBasalId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`noteId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `mealLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `bolusId` INTEGER, `carbsId` INTEGER, `bolusCalcResultId` INTEGER, `superbolusTempBasalId` INTEGER, `noteId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`carbsId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`bolusCalcResultId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`superbolusTempBasalId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`noteId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `mealLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -2254,6 +2254,18 @@
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": false "notNull": false
}, },
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "utcOffset",
"columnName": "utcOffset",
"affinity": "INTEGER",
"notNull": true
},
{ {
"fieldPath": "bolusId", "fieldPath": "bolusId",
"columnName": "bolusId", "columnName": "bolusId",
@ -2930,7 +2942,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b45eaf7386412002a6289168c3dfa06e')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c38f6acf42463481d39fe05be1fd3b55')"
] ]
} }
} }

View file

@ -1,10 +1,6 @@
package info.nightscout.androidaps.database package info.nightscout.androidaps.database
import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.interfaces.DBEntry import info.nightscout.androidaps.database.interfaces.DBEntry
import info.nightscout.androidaps.database.transactions.Transaction import info.nightscout.androidaps.database.transactions.Transaction
import io.reactivex.Completable import io.reactivex.Completable
@ -179,6 +175,28 @@ open class AppRepository @Inject internal constructor(
fun deleteAllFoods() = fun deleteAllFoods() =
database.foodDao.deleteAllEntries() database.foodDao.deleteAllEntries()
// MEAL LINK
fun getMealLinkLoadedDataFromTime(timestamp: Long, ascending: Boolean): Single<List<MealLinkLoaded>> =
database.mealLinkDao.getMealLinkLoadedFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getMealLinkLoadedDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<MealLinkLoaded>> =
database.mealLinkDao.getMealLinkLoadedIncludingInvalidFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun deleteAllBoluses() =
database.bolusDao.deleteAllEntries()
fun deleteAllCarbs() =
database.carbsDao.deleteAllEntries()
fun deleteAllBolusCalculatorResults() =
database.bolusCalculatorResultDao.deleteAllEntries()
fun deleteAllMealLinks() =
database.mealLinkDao.deleteAllEntries()
} }
@Suppress("USELESS_CAST") @Suppress("USELESS_CAST")

View file

@ -48,9 +48,18 @@ open class DatabaseModule {
private val migration7to8 = object : Migration(7, 8) { private val migration7to8 = object : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) { override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS bolusCalculatorResults") database.execSQL("DROP TABLE IF EXISTS bolusCalculatorResults")
database.execSQL("CREATE TABLE IF NOT EXISTS bolusCalculatorResults (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` REAL NOT NULL, `profileName` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )") database.execSQL("CREATE TABLE IF NOT EXISTS bolusCalculatorResults (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_referenceId` ON bolusCalculatorResults (`referenceId`)") database.execSQL("CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_referenceId` ON bolusCalculatorResults (`referenceId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_timestamp` ON bolusCalculatorResults (`timestamp`)") database.execSQL("CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_timestamp` ON bolusCalculatorResults (`timestamp`)")
database.execSQL("DROP TABLE IF EXISTS mealLinks")
database.execSQL("CREATE TABLE IF NOT EXISTS mealLinks (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `bolusId` INTEGER, `carbsId` INTEGER, `bolusCalcResultId` INTEGER, `superbolusTempBasalId` INTEGER, `noteId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`carbsId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`bolusCalcResultId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`superbolusTempBasalId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`noteId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `mealLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_referenceId` ON mealLinks (`referenceId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_bolusId` ON `mealLinks (`bolusId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_carbsId` ON mealLinks (`carbsId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_bolusCalcResultId` ON mealLinks (`bolusCalcResultId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_superbolusTempBasalId` ON mealLinks (`superbolusTempBasalId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_mealLinks_noteId` ON mealLinks (`noteId`)")
} }
} }
} }

View file

@ -2,8 +2,10 @@ package info.nightscout.androidaps.database.daos
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction
import info.nightscout.androidaps.database.TABLE_MEAL_LINKS import info.nightscout.androidaps.database.TABLE_MEAL_LINKS
import info.nightscout.androidaps.database.entities.MealLink import info.nightscout.androidaps.database.entities.MealLink
import info.nightscout.androidaps.database.entities.MealLinkLoaded
import io.reactivex.Single import io.reactivex.Single
@Suppress("FunctionName") @Suppress("FunctionName")
@ -15,4 +17,12 @@ internal interface MealLinkDao : TraceableDao<MealLink> {
@Query("DELETE FROM $TABLE_MEAL_LINKS") @Query("DELETE FROM $TABLE_MEAL_LINKS")
override fun deleteAllEntries() override fun deleteAllEntries()
@Transaction
@Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE isValid = 1 AND timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getMealLinkLoadedFromTime(timestamp: Long): Single<List<MealLinkLoaded>>
@Transaction
@Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getMealLinkLoadedIncludingInvalidFromTime(timestamp: Long): Single<List<MealLinkLoaded>>
} }

View file

@ -11,15 +11,33 @@ data class InterfaceIDs(
) { ) {
enum class PumpType { enum class PumpType {
USER, GENERIC_AAPS,
VIRTUAL_PUMP, CELLNOVO,
ACCU_CHEK_INSIGHT,
ACCU_CHEK_COMBO, ACCU_CHEK_COMBO,
ACCU_CHEK_SPIRIT,
ACCU_CHEK_INSIGHT,
ACCU_CHEK_INSIGHT_BLUETOOTH,
ACCU_CHEK_SOLO,
ANIMAS_VIBE,
ANIMAS_PING,
DANA_R, DANA_R,
DANA_R_KOREAN,
DANA_RV2, DANA_RV2,
DANA_RS, DANA_RS,
MEDTRONIC,
OMNIPOD_EROS, OMNIPOD_EROS,
OMNIPOD_DASH OMNIPOD_DASH,
MEDTRONIC_512_517,
MEDTRONIC_515_715,
MEDTRONIC_522_722,
MEDTRONIC_523_723_REVEL,
MEDTRONIC_554_754_VEO,
MEDTRONIC_640G,
TANDEM_T_SLIM,
TANDEM_T_FLEX,
TANDEM_T_SLIM_G4,
TANDEM_T_SLIM_X2,
YPSOPUMP,
MDI,
USER
} }
} }

View file

@ -50,6 +50,6 @@ data class BolusCalculatorResult(
var superbolusInsulin: Double, var superbolusInsulin: Double,
var wasTempTargetUsed: Boolean, var wasTempTargetUsed: Boolean,
var totalInsulin: Double, var totalInsulin: Double,
var percentageCorrection: Double, var percentageCorrection: Int,
var profileName: String var profileName: String
) : TraceableDBEntry, DBEntryWithTime ) : TraceableDBEntry, DBEntryWithTime

View file

@ -28,6 +28,6 @@ data class Carbs(
override var interfaceIDs_backing: InterfaceIDs? = null, override var interfaceIDs_backing: InterfaceIDs? = null,
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(),
override var duration: Long, override var duration: Long, // in milliseconds
var amount: Double var amount: Double
) : TraceableDBEntry, DBEntryWithTimeAndDuration ) : TraceableDBEntry, DBEntryWithTimeAndDuration

View file

@ -3,7 +3,9 @@ package info.nightscout.androidaps.database.entities
import androidx.room.* import androidx.room.*
import info.nightscout.androidaps.database.TABLE_MEAL_LINKS import info.nightscout.androidaps.database.TABLE_MEAL_LINKS
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.*
@Entity(tableName = TABLE_MEAL_LINKS, @Entity(tableName = TABLE_MEAL_LINKS,
foreignKeys = [ foreignKeys = [
@ -41,6 +43,8 @@ data class MealLink(
override var dateCreated: Long = -1, override var dateCreated: Long = -1,
override var isValid: Boolean = true, override var isValid: Boolean = true,
override var referenceId: Long? = null, override var referenceId: Long? = null,
override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
@Embedded @Embedded
override var interfaceIDs_backing: InterfaceIDs? = null, override var interfaceIDs_backing: InterfaceIDs? = null,
var bolusId: Long? = null, var bolusId: Long? = null,
@ -48,7 +52,8 @@ data class MealLink(
var bolusCalcResultId: Long? = null, var bolusCalcResultId: Long? = null,
var superbolusTempBasalId: Long? = null, var superbolusTempBasalId: Long? = null,
var noteId: Long? = null var noteId: Long? = null
) : TraceableDBEntry {
) : TraceableDBEntry, DBEntryWithTime {
override val foreignKeysValid: Boolean override val foreignKeysValid: Boolean
get() = super.foreignKeysValid && bolusId != 0L && carbsId != 0L && get() = super.foreignKeysValid && bolusId != 0L && carbsId != 0L &&

View file

@ -0,0 +1,33 @@
package info.nightscout.androidaps.database.entities
import androidx.room.Embedded
import androidx.room.Relation
data class MealLinkLoaded constructor(
@Embedded val mealLink: MealLink,
@Relation(
entity = Bolus::class,
parentColumn = "bolusId",
entityColumn = "id")
val bolus: Bolus?,
@Relation(
entity = Carbs::class,
parentColumn = "carbsId",
entityColumn = "id")
val carbs: Carbs?,
@Relation(
entity = BolusCalculatorResult::class,
parentColumn = "bolusCalcResultId",
entityColumn = "id")
val bolusCalculatorResult: BolusCalculatorResult?,
@Relation(
entity = TemporaryBasal::class,
parentColumn = "superbolusTempBasalId",
entityColumn = "id")
val superBolusTemporaryBasal: TemporaryBasal?,
@Relation(
entity = TherapyEvent::class,
parentColumn = "noteId",
entityColumn = "id")
val therapyEvent: TherapyEvent?
)

View file

@ -23,6 +23,7 @@ class InsertMealLinkTransaction(
val therapyEventId = if (therapyEvent != null) database.therapyEventDao.insert(therapyEvent) else null val therapyEventId = if (therapyEvent != null) database.therapyEventDao.insert(therapyEvent) else null
val mealLink = MealLink( val mealLink = MealLink(
timestamp = System.currentTimeMillis(),
bolusId = bolusId, bolusId = bolusId,
carbsId = carbsId, carbsId = carbsId,
bolusCalcResultId = bolusCalculatorResultId, bolusCalcResultId = bolusCalculatorResultId,
@ -31,13 +32,14 @@ class InsertMealLinkTransaction(
) )
database.mealLinkDao.insert(mealLink) database.mealLinkDao.insert(mealLink)
result.inserted.add(mealLink) val full = MealLinkLoaded(mealLink, bolus, carbs, bolusCalculatorResult, superBolusTemporaryBasal, therapyEvent)
result.inserted.add(full)
return result return result
} }
class TransactionResult { class TransactionResult {
val inserted = mutableListOf<MealLink>() val inserted = mutableListOf<MealLinkLoaded>()
} }
} }

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.database.transactions
class InvalidateBolusTransaction(val id: Long) : Transaction<Unit>() {
override fun run() {
val bolus = database.bolusDao.findById(id)
?: throw IllegalArgumentException("There is no such Bolus with the specified ID.")
bolus.isValid = false
database.bolusDao.updateExistingEntry(bolus)
}
}

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.database.transactions
class InvalidateCarbsTransaction(val id: Long) : Transaction<Unit>() {
override fun run() {
val carbs = database.carbsDao.findById(id)
?: throw IllegalArgumentException("There is no such Carbs with the specified ID.")
carbs.isValid = false
database.carbsDao.updateExistingEntry(carbs)
}
}

View file

@ -0,0 +1,42 @@
package info.nightscout.androidaps.database.transactions
class InvalidateMealLinkTransaction(val id: Long) : Transaction<Unit>() {
override fun run() {
val mealLink = database.mealLinkDao.findById(id)
?: throw IllegalArgumentException("There is no such MealLink with the specified ID.")
if (mealLink.bolusId != null) {
val bolus = database.bolusDao.findById(id)
?: throw IllegalArgumentException("There is no such Bolus with the specified ID.")
bolus.isValid = false
database.bolusDao.updateExistingEntry(bolus)
}
if (mealLink.carbsId != null) {
val carbs = database.carbsDao.findById(id)
?: throw IllegalArgumentException("There is no such Carbs with the specified ID.")
carbs.isValid = false
database.carbsDao.updateExistingEntry(carbs)
}
if (mealLink.bolusCalcResultId != null) {
val bolusCalculatorResult = database.bolusCalculatorResultDao.findById(id)
?: throw IllegalArgumentException("There is no such BolusCalculatorResult with the specified ID.")
bolusCalculatorResult.isValid = false
database.bolusCalculatorResultDao.updateExistingEntry(bolusCalculatorResult)
}
// TemporaryBasal is not invalidated for safety reason
if (mealLink.noteId != null) {
val therapyEvent = database.therapyEventDao.findById(id)
?: throw IllegalArgumentException("There is no such TherapyEvent with the specified ID.")
therapyEvent.isValid = false
database.therapyEventDao.updateExistingEntry(therapyEvent)
}
mealLink.isValid = false
database.mealLinkDao.updateExistingEntry(mealLink)
}
}

View file

@ -31,8 +31,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; 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.embedments.InterfaceIDs;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.entities.TherapyEvent; import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction; import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
@ -247,7 +245,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
this.repository = repository; this.repository = repository;
pumpDescription = new PumpDescription(); pumpDescription = new PumpDescription();
pumpDescription.setPumpDescription(PumpType.AccuChekInsightBluetooth); pumpDescription.setPumpDescription(PumpType.ACCU_CHEK_INSIGHT_BLUETOOTH);
} }
public TBROverNotificationBlock getTBROverNotificationBlock() { public TBROverNotificationBlock getTBROverNotificationBlock() {
@ -593,13 +591,13 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
bolusMessage.setDuration(0); bolusMessage.setDuration(0);
bolusMessage.setExtendedAmount(0); bolusMessage.setExtendedAmount(0);
bolusMessage.setImmediateAmount(insulin); bolusMessage.setImmediateAmount(insulin);
bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration, false)); bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration, false));
bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId(); bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId();
bolusCancelled = false; bolusCancelled = false;
} }
result.success(true).enacted(true); result.success(true).enacted(true);
Treatment t = new Treatment(); Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB; t.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(t); bolusingEvent.setT(t);
bolusingEvent.setStatus(resourceHelper.gs(R.string.insight_delivered, 0d, insulin)); bolusingEvent.setStatus(resourceHelper.gs(R.string.insight_delivered, 0d, insulin));
@ -611,15 +609,15 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
insightBolusID.timestamp = System.currentTimeMillis(); insightBolusID.timestamp = System.currentTimeMillis();
insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber(); insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber();
databaseHelper.createOrUpdate(insightBolusID); databaseHelper.createOrUpdate(insightBolusID);
detailedBolusInfo.timestamp = insightBolusID.timestamp; detailedBolusInfo.setBolusTimestamp(insightBolusID.timestamp);
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT); detailedBolusInfo.setPumpType(PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber()); detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(insightBolusID.id); detailedBolusInfo.setBolusPumpId(insightBolusID.id);
if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime != 0) { if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime != 0) {
DetailedBolusInfo carbInfo = new DetailedBolusInfo(); DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.carbs = detailedBolusInfo.carbs; carbInfo.carbs = detailedBolusInfo.carbs;
carbInfo.timestamp = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L; carbInfo.setCarbsTimestamp(detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L);
carbInfo.setPumpType(InterfaceIDs.PumpType.USER); carbInfo.setPumpType(PumpType.USER);
treatmentsPlugin.addToHistoryTreatment(carbInfo, false); treatmentsPlugin.addToHistoryTreatment(carbInfo, false);
detailedBolusInfo.carbTime = 0; detailedBolusInfo.carbTime = 0;
detailedBolusInfo.carbs = 0; detailedBolusInfo.carbs = 0;
@ -1033,7 +1031,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
@NonNull @Override @NonNull @Override
public PumpType model() { public PumpType model() {
return PumpType.AccuChekInsightBluetooth; return PumpType.ACCU_CHEK_INSIGHT_BLUETOOTH;
} }
@NonNull @Override @NonNull @Override
@ -1394,7 +1392,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) { if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.timestamp = bolusID.timestamp; detailedBolusInfo.timestamp = bolusID.timestamp;
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT); detailedBolusInfo.setPumpType(PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber()); detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(bolusID.id); detailedBolusInfo.setBolusPumpId(bolusID.id);
detailedBolusInfo.insulin = event.getImmediateAmount(); detailedBolusInfo.insulin = event.getImmediateAmount();
@ -1428,8 +1426,8 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
databaseHelper.createOrUpdate(bolusID); databaseHelper.createOrUpdate(bolusID);
if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) { if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.timestamp = bolusID.timestamp; detailedBolusInfo.setBolusTimestamp(bolusID.timestamp);
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT); detailedBolusInfo.setPumpType(PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber()); detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(bolusID.id); detailedBolusInfo.setBolusPumpId(bolusID.id);
detailedBolusInfo.insulin = event.getImmediateAmount(); detailedBolusInfo.insulin = event.getImmediateAmount();

View file

@ -151,7 +151,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
.shortName(R.string.medtronic_name_short) // .shortName(R.string.medtronic_name_short) //
.preferencesId(R.xml.pref_medtronic) .preferencesId(R.xml.pref_medtronic)
.description(R.string.description_pump_medtronic), // .description(R.string.description_pump_medtronic), //
PumpType.Medtronic_522_722, // we default to most basic model, correct model from config is loaded later PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later
injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers
); );
@ -888,7 +888,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// we subtract insulin, exact amount will be visible with next remainingInsulin update. // we subtract insulin, exact amount will be visible with next remainingInsulin update.
medtronicPumpStatus.reservoirRemainingUnits -= detailedBolusInfo.insulin; medtronicPumpStatus.reservoirRemainingUnits -= detailedBolusInfo.insulin;
incrementStatistics(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? MedtronicConst.Statistics.SMBBoluses incrementStatistics(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? MedtronicConst.Statistics.SMBBoluses
: MedtronicConst.Statistics.StandardBoluses); : MedtronicConst.Statistics.StandardBoluses);

View file

@ -22,7 +22,6 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.embedments.InterfaceIDs;
import info.nightscout.androidaps.database.entities.TherapyEvent; import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction; import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.DbObjectBase; import info.nightscout.androidaps.db.DbObjectBase;
@ -986,8 +985,8 @@ public class MedtronicHistoryData {
case Normal: { case Normal: {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.timestamp = tryToGetByLocalTime(bolus.atechDateTime); detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.atechDateTime));
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.MEDTRONIC); detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model
detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber); detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber);
detailedBolusInfo.setBolusPumpId(bolus.getPumpId()); detailedBolusInfo.setBolusPumpId(bolus.getPumpId());
detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount();

View file

@ -65,7 +65,7 @@ public class MedtronicPumpStatus extends info.nightscout.androidaps.plugins.pump
RxBusWrapper rxBus, RxBusWrapper rxBus,
RileyLinkUtil rileyLinkUtil RileyLinkUtil rileyLinkUtil
) { ) {
super(PumpType.Medtronic_522_722); super(PumpType.MEDTRONIC_522_722);
this.resourceHelper = resourceHelper; this.resourceHelper = resourceHelper;
this.sp = sp; this.sp = sp;
this.rxBus = rxBus; this.rxBus = rxBus;
@ -110,17 +110,17 @@ public class MedtronicPumpStatus extends info.nightscout.androidaps.plugins.pump
private void createMedtronicPumpMap() { private void createMedtronicPumpMap() {
medtronicPumpMap = new HashMap<>(); medtronicPumpMap = new HashMap<>();
medtronicPumpMap.put("512", PumpType.Medtronic_512_712); medtronicPumpMap.put("512", PumpType.MEDTRONIC_512_712);
medtronicPumpMap.put("712", PumpType.Medtronic_512_712); medtronicPumpMap.put("712", PumpType.MEDTRONIC_512_712);
medtronicPumpMap.put("515", PumpType.Medtronic_515_715); medtronicPumpMap.put("515", PumpType.MEDTRONIC_515_715);
medtronicPumpMap.put("715", PumpType.Medtronic_515_715); medtronicPumpMap.put("715", PumpType.MEDTRONIC_515_715);
medtronicPumpMap.put("522", PumpType.Medtronic_522_722); medtronicPumpMap.put("522", PumpType.MEDTRONIC_522_722);
medtronicPumpMap.put("722", PumpType.Medtronic_522_722); medtronicPumpMap.put("722", PumpType.MEDTRONIC_522_722);
medtronicPumpMap.put("523", PumpType.Medtronic_523_723_Revel); medtronicPumpMap.put("523", PumpType.MEDTRONIC_523_723_REVEL);
medtronicPumpMap.put("723", PumpType.Medtronic_523_723_Revel); medtronicPumpMap.put("723", PumpType.MEDTRONIC_523_723_REVEL);
medtronicPumpMap.put("554", PumpType.Medtronic_554_754_Veo); medtronicPumpMap.put("554", PumpType.MEDTRONIC_554_754_VEO);
medtronicPumpMap.put("754", PumpType.Medtronic_554_754_Veo); medtronicPumpMap.put("754", PumpType.MEDTRONIC_554_754_VEO);
} }

View file

@ -34,7 +34,7 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper;
@Singleton @Singleton
public class OmnipodDashPumpPlugin extends PumpPluginBase implements PumpInterface { public class OmnipodDashPumpPlugin extends PumpPluginBase implements PumpInterface {
private static final PumpDescription PUMP_DESCRIPTION = new PumpDescription(PumpType.Omnipod_Dash); private static final PumpDescription PUMP_DESCRIPTION = new PumpDescription(PumpType.OMNIPOD_DASH);
private final AAPSLogger aapsLogger; private final AAPSLogger aapsLogger;
private final ResourceHelper resourceHelper; private final ResourceHelper resourceHelper;

View file

@ -140,7 +140,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
private final DateUtil dateUtil; private final DateUtil dateUtil;
private final PumpDescription pumpDescription; private final PumpDescription pumpDescription;
private final ServiceConnection serviceConnection; private final ServiceConnection serviceConnection;
private final PumpType pumpType = PumpType.Omnipod_Eros; private final PumpType pumpType = PumpType.OMNIPOD_EROS;
private final CompositeDisposable disposables = new CompositeDisposable(); private final CompositeDisposable disposables = new CompositeDisposable();
private final NSUpload nsUpload; private final NSUpload nsUpload;
@ -1086,7 +1086,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
PumpEnactResult result = executeCommand(OmnipodCommandType.SET_BOLUS, () -> aapsOmnipodErosManager.bolus(detailedBolusInfo)); PumpEnactResult result = executeCommand(OmnipodCommandType.SET_BOLUS, () -> aapsOmnipodErosManager.bolus(detailedBolusInfo));
if (result.getSuccess()) { if (result.getSuccess()) {
incrementStatistics(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? OmnipodErosStorageKeys.Statistics.SMB_BOLUSES_DELIVERED incrementStatistics(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? OmnipodErosStorageKeys.Statistics.SMB_BOLUSES_DELIVERED
: OmnipodErosStorageKeys.Statistics.STANDARD_BOLUSES_DELIVERED); : OmnipodErosStorageKeys.Statistics.STANDARD_BOLUSES_DELIVERED);
result.carbsDelivered(detailedBolusInfo.carbs); result.carbsDelivered(detailedBolusInfo.carbs);

View file

@ -19,8 +19,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; 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.embedments.InterfaceIDs;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.entities.TherapyEvent; import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction; import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.OmnipodHistoryRecord; import info.nightscout.androidaps.db.OmnipodHistoryRecord;
@ -374,11 +372,11 @@ public class AapsOmnipodErosManager {
public PumpEnactResult bolus(DetailedBolusInfo detailedBolusInfo) { public PumpEnactResult bolus(DetailedBolusInfo detailedBolusInfo) {
OmnipodManager.BolusCommandResult bolusCommandResult; OmnipodManager.BolusCommandResult bolusCommandResult;
boolean beepsEnabled = detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? isSmbBeepsEnabled() : isBolusBeepsEnabled(); boolean beepsEnabled = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? isSmbBeepsEnabled() : isBolusBeepsEnabled();
Date bolusStarted; Date bolusStarted;
try { try {
bolusCommandResult = executeCommand(() -> delegate.bolus(PumpType.Omnipod_Eros.determineCorrectBolusSize(detailedBolusInfo.insulin), beepsEnabled, beepsEnabled, detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? null : bolusCommandResult = executeCommand(() -> delegate.bolus(PumpType.OMNIPOD_EROS.determineCorrectBolusSize(detailedBolusInfo.insulin), beepsEnabled, beepsEnabled, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? null :
(estimatedUnitsDelivered, percentage) -> { (estimatedUnitsDelivered, percentage) -> {
EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE; EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE;
progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, detailedBolusInfo.insulin)); progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, detailedBolusInfo.insulin));
@ -395,7 +393,7 @@ public class AapsOmnipodErosManager {
if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus())) { if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus())) {
// For safety reasons, we treat this as a bolus that has successfully been delivered, in order to prevent insulin overdose // For safety reasons, we treat this as a bolus that has successfully been delivered, in order to prevent insulin overdose
if (detailedBolusInfo.getBolusType() == Bolus.Type.SMB) { if (detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB) {
showNotification(Notification.OMNIPOD_UNCERTAIN_SMB, getStringResource(R.string.omnipod_eros_error_bolus_failed_uncertain_smb, detailedBolusInfo.insulin), Notification.URGENT, isNotificationUncertainSmbSoundEnabled() ? R.raw.boluserror : null); showNotification(Notification.OMNIPOD_UNCERTAIN_SMB, getStringResource(R.string.omnipod_eros_error_bolus_failed_uncertain_smb, detailedBolusInfo.insulin), Notification.URGENT, isNotificationUncertainSmbSoundEnabled() ? R.raw.boluserror : null);
} else { } else {
showErrorDialog(getStringResource(R.string.omnipod_eros_error_bolus_failed_uncertain), isNotificationUncertainBolusSoundEnabled() ? R.raw.boluserror : null); showErrorDialog(getStringResource(R.string.omnipod_eros_error_bolus_failed_uncertain), isNotificationUncertainBolusSoundEnabled() ? R.raw.boluserror : null);
@ -403,7 +401,7 @@ public class AapsOmnipodErosManager {
} }
detailedBolusInfo.timestamp = bolusStarted.getTime(); detailedBolusInfo.timestamp = bolusStarted.getTime();
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.OMNIPOD_EROS); detailedBolusInfo.setPumpType(PumpType.OMNIPOD_EROS);
detailedBolusInfo.setPumpSerial(serialNumber()); detailedBolusInfo.setPumpSerial(serialNumber());
// Store the current bolus for in case the app crashes, gets killed, the phone dies or whatever before the bolus finishes // Store the current bolus for in case the app crashes, gets killed, the phone dies or whatever before the bolus finishes
@ -490,7 +488,7 @@ public class AapsOmnipodErosManager {
public PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair) { public PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair) {
boolean beepsEnabled = isTbrBeepsEnabled(); boolean beepsEnabled = isTbrBeepsEnabled();
try { try {
executeCommand(() -> delegate.setTemporaryBasal(PumpType.Omnipod_Eros.determineCorrectBasalSize(tempBasalPair.getInsulinRate()), Duration.standardMinutes(tempBasalPair.getDurationMinutes()), beepsEnabled, beepsEnabled)); executeCommand(() -> delegate.setTemporaryBasal(PumpType.OMNIPOD_EROS.determineCorrectBasalSize(tempBasalPair.getInsulinRate()), Duration.standardMinutes(tempBasalPair.getDurationMinutes()), beepsEnabled, beepsEnabled));
} catch (CommandFailedAfterChangingDeliveryStatusException ex) { } catch (CommandFailedAfterChangingDeliveryStatusException ex) {
String errorMessage = translateException(ex.getCause()); String errorMessage = translateException(ex.getCause());
addFailureToHistory(PodHistoryEntryType.SET_TEMPORARY_BASAL, errorMessage); addFailureToHistory(PodHistoryEntryType.SET_TEMPORARY_BASAL, errorMessage);
@ -532,7 +530,7 @@ public class AapsOmnipodErosManager {
return new PumpEnactResult(injector) return new PumpEnactResult(injector)
.duration(tempBasalPair.getDurationMinutes()) .duration(tempBasalPair.getDurationMinutes())
.absolute(PumpType.Omnipod_Eros.determineCorrectBasalSize(tempBasalPair.getInsulinRate())) .absolute(PumpType.OMNIPOD_EROS.determineCorrectBasalSize(tempBasalPair.getInsulinRate()))
.success(true).enacted(true); .success(true).enacted(true);
} }
@ -705,16 +703,17 @@ public class AapsOmnipodErosManager {
public void addBolusToHistory(DetailedBolusInfo originalDetailedBolusInfo) { public void addBolusToHistory(DetailedBolusInfo originalDetailedBolusInfo) {
DetailedBolusInfo detailedBolusInfo = originalDetailedBolusInfo.copy(); DetailedBolusInfo detailedBolusInfo = originalDetailedBolusInfo.copy();
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.OMNIPOD_EROS); detailedBolusInfo.setBolusTimestamp(detailedBolusInfo.timestamp);
detailedBolusInfo.setPumpType(PumpType.OMNIPOD_EROS);
detailedBolusInfo.setPumpSerial(serialNumber()); detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(addSuccessToHistory(detailedBolusInfo.timestamp, PodHistoryEntryType.SET_BOLUS, detailedBolusInfo.insulin + ";" + detailedBolusInfo.carbs)); detailedBolusInfo.setBolusPumpId(addSuccessToHistory(detailedBolusInfo.timestamp, PodHistoryEntryType.SET_BOLUS, detailedBolusInfo.insulin + ";" + detailedBolusInfo.carbs));
if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime > 0) { if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime > 0) {
// split out a separate carbs record without a pumpId // split out a separate carbs record without a pumpId
DetailedBolusInfo carbInfo = new DetailedBolusInfo(); DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.timestamp = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L; carbInfo.setCarbsTimestamp(detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L);
carbInfo.carbs = detailedBolusInfo.carbs; carbInfo.carbs = detailedBolusInfo.carbs;
carbInfo.setPumpType(InterfaceIDs.PumpType.USER); carbInfo.setPumpType(PumpType.USER);
activePlugin.getActiveTreatments().addToHistoryTreatment(carbInfo, false); activePlugin.getActiveTreatments().addToHistoryTreatment(carbInfo, false);
// remove carbs from bolusInfo to not trigger any unwanted code paths in // remove carbs from bolusInfo to not trigger any unwanted code paths in
@ -997,7 +996,7 @@ public class AapsOmnipodErosManager {
} }
List<BasalScheduleEntry> entries = new ArrayList<>(); List<BasalScheduleEntry> entries = new ArrayList<>();
for (Profile.ProfileValue basalValue : basalValues) { for (Profile.ProfileValue basalValue : basalValues) {
entries.add(new BasalScheduleEntry(PumpType.Omnipod_Eros.determineCorrectBasalSize(basalValue.value), entries.add(new BasalScheduleEntry(PumpType.OMNIPOD_EROS.determineCorrectBasalSize(basalValue.value),
Duration.standardSeconds(basalValue.timeAsSeconds))); Duration.standardSeconds(basalValue.timeAsSeconds)));
} }

View file

@ -309,7 +309,7 @@ public class ErosPodHistoryActivity extends NoSplashAppCompatActivity {
try { try {
Profile.ProfileValue[] profileValuesArray = aapsOmnipodUtil.getGsonInstance().fromJson(data, Profile.ProfileValue[].class); Profile.ProfileValue[] profileValuesArray = aapsOmnipodUtil.getGsonInstance().fromJson(data, Profile.ProfileValue[].class);
valueView.setText(ProfileUtil.getBasalProfilesDisplayable(profileValuesArray, PumpType.Omnipod_Eros)); valueView.setText(ProfileUtil.getBasalProfilesDisplayable(profileValuesArray, PumpType.OMNIPOD_EROS));
} catch (Exception e) { } catch (Exception e) {
aapsLogger.error(LTag.PUMP, "Problem parsing Profile json. Ex: {}, Data:\n{}", e.getMessage(), data); aapsLogger.error(LTag.PUMP, "Problem parsing Profile json. Ex: {}, Data:\n{}", e.getMessage(), data);
valueView.setText(""); valueView.setText("");

View file

@ -30,7 +30,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodE
import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.rx.TestAapsSchedulers; import info.nightscout.androidaps.utils.rx.TestAapsSchedulers;
import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
@ -124,7 +123,7 @@ public class OmnipodErosPumpPluginTest {
// When treatment // When treatment
result1 = plugin.setTempBasalPercent(80, 30, profile, false); result1 = plugin.setTempBasalPercent(80, 30, profile, false);
// Then return sane values // Then return sane values
assertEquals(result1.getAbsolute(), PumpType.Omnipod_Eros.determineCorrectBasalSize(500d * 0.8), 0.01d); assertEquals(result1.getAbsolute(), PumpType.OMNIPOD_EROS.determineCorrectBasalSize(500d * 0.8), 0.01d);
assertEquals(result1.getDuration(), 30); assertEquals(result1.getDuration(), 30);
// Given weird basal // Given weird basal