prepare DetailedBolusInfo

This commit is contained in:
Milos Kozak 2021-03-22 16:59:09 +01:00
parent 906fc35da5
commit 616871c95c
44 changed files with 3520 additions and 435 deletions

View file

@ -222,7 +222,7 @@ class CarbsDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
when {
activitySelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M))
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(activityTT, units), ValueWithUnit(activityTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()),
@ -238,7 +238,7 @@ class CarbsDialog : DialogFragmentWithDate() {
}
eatingSoonSelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M))
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
@ -254,7 +254,7 @@ class CarbsDialog : DialogFragmentWithDate() {
}
hypoSelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M))
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(hypoTT, units), ValueWithUnit(hypoTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()),
@ -271,7 +271,7 @@ class CarbsDialog : DialogFragmentWithDate() {
}
if (carbsAfterConstraints > 0) {
if (duration == 0) {
carbsGenerator.createCarb(carbsAfterConstraints, time, TherapyEvent.Type.CARBS_CORRECTION.text, notes)
carbsGenerator.createCarb(carbsAfterConstraints, time, TherapyEvent.Type.CARBS_CORRECTION, notes)
} else {
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
nsUpload.uploadEvent(TherapyEvent.Type.NOTE.text, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))

View file

@ -10,11 +10,13 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
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.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.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogFillBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
@ -181,8 +183,7 @@ class FillDialog : DialogFragmentWithDate() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = insulin
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
detailedBolusInfo.bolusType = Bolus.Type.PRIMING
detailedBolusInfo.notes = notes
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -17,10 +17,11 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
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.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.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
@ -205,18 +206,17 @@ class InsulinDialog : DialogFragmentWithDate() {
}
if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes
if (recordOnlyChecked) {
uel.log(Action.BOLUS_RECORD, notes, ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(timeOffset, Units.M, timeOffset!= 0))
detailedBolusInfo.date = time
uel.log(Action.BOLUS_RECORD, notes, ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(timeOffset, Units.M, timeOffset != 0))
detailedBolusInfo.timestamp = time
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
} else {
uel.log(Action.BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U))
detailedBolusInfo.date = DateUtil.now()
detailedBolusInfo.timestamp = DateUtil.now()
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {

View file

@ -13,9 +13,10 @@ 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.database.entities.UserEntry.*
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.databinding.DialogTreatmentBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
@ -132,12 +133,11 @@ class TreatmentDialog : DialogFragmentWithDate() {
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()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = TherapyEvent.Type.CARBS_CORRECTION.text
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = TherapyEvent.Type.CARBS_CORRECTION
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) {
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -16,9 +16,9 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
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.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventNewBG
@ -596,11 +596,10 @@ open class LoopPlugin @Inject constructor(
// deliver SMB
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.lastBolusTime
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS
detailedBolusInfo.insulin = request.smb
detailedBolusInfo.isSMB = true
detailedBolusInfo.source = Source.USER
detailedBolusInfo.deliverAt = request.deliverAt
detailedBolusInfo.bolusType = Bolus.Type.SMB
detailedBolusInfo.deliverAtTheLatest = request.deliverAt
aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()")
commandQueue.bolus(detailedBolusInfo, callback)
}

View file

@ -17,10 +17,11 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
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.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.*
@ -40,7 +41,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.extensions.valueToUnitsString
import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -793,7 +793,6 @@ class SmsCommunicatorPlugin @Inject constructor(
override fun run() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = aDouble()
detailedBolusInfo.source = Source.USER
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
val resultSuccess = result.success
@ -875,8 +874,7 @@ class SmsCommunicatorPlugin @Inject constructor(
override fun run() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.carbs = anInteger().toDouble()
detailedBolusInfo.source = Source.USER
detailedBolusInfo.date = secondLong()
detailedBolusInfo.timestamp = secondLong()
if (activePlugin.activePump.pumpDescription.storesCarbInfo) {
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -15,12 +15,12 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
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.TherapyEvent
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
@ -545,7 +545,7 @@ class ActionStringHandler @Inject constructor(
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
if (carbs > 0) {
if (duration == 0) {
carbsGenerator.createCarb(carbs, time, TherapyEvent.Type.CARBS_CORRECTION.text, "watch")
carbsGenerator.createCarb(carbs, time, TherapyEvent.Type.CARBS_CORRECTION, "watch")
} else {
carbsGenerator.generateCarbs(carbs, time, duration, "watch eCarbs")
}
@ -604,8 +604,7 @@ class ActionStringHandler @Inject constructor(
private fun doFillBolus(amount: Double) {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = amount
detailedBolusInfo.isValid = false
detailedBolusInfo.source = Source.USER
detailedBolusInfo.bolusType = Bolus.Type.PRIMING
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
@ -621,7 +620,7 @@ class ActionStringHandler @Inject constructor(
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = amount
detailedBolusInfo.carbs = carbs.toDouble()
detailedBolusInfo.source = Source.USER
detailedBolusInfo.bolusType = Bolus.Type.NORMAL
val storesCarbs = activePlugin.activePump.pumpDescription.storesCarbInfo
if (detailedBolusInfo.insulin > 0 || storesCarbs) {
commandQueue.bolus(detailedBolusInfo, object : Callback() {

View file

@ -5,7 +5,6 @@ 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.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.queue.Callback
@ -31,19 +30,18 @@ class CarbsGenerator @Inject constructor(
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.text, notes)
if (smallCarbAmount > 0) createCarb(smallCarbAmount, carbTime, TherapyEvent.Type.MEAL_BOLUS, notes)
}
}
fun createCarb(carbs: Int, time: Long, eventType: String, notes: String) {
fun createCarb(carbs: Int, time: Long, eventType: TherapyEvent.Type, notes: String) {
val carbInfo = DetailedBolusInfo()
carbInfo.date = time
carbInfo.timestamp = time
carbInfo.eventType = eventType
carbInfo.carbs = carbs.toDouble()
carbInfo.context = context
carbInfo.source = Source.USER
carbInfo.notes = notes
if (activePlugin.activePump.pumpDescription.storesCarbInfo && carbInfo.date <= DateUtil.now() && carbInfo.date > DateUtil.now() - T.mins(2).msecs()) {
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) {

View file

@ -26,6 +26,8 @@ import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals;
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.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
@ -623,16 +625,17 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump);
Treatment treatment = new Treatment();
treatment.date = detailedBolusInfo.date;
treatment.source = detailedBolusInfo.source;
treatment.pumpId = detailedBolusInfo.pumpId;
treatment.date = detailedBolusInfo.timestamp;
treatment.source = (detailedBolusInfo.getPumpType() == InterfaceIDs.PumpType.USER) ? Source.USER : Source.PUMP;
treatment.pumpId = detailedBolusInfo.getBolusPumpId();
treatment.insulin = detailedBolusInfo.insulin;
treatment.isValid = detailedBolusInfo.isValid;
treatment.isSMB = detailedBolusInfo.isSMB;
treatment.isValid = detailedBolusInfo.getBolusType() != Bolus.Type.PRIMING;
treatment.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB;
if (detailedBolusInfo.carbTime == 0)
treatment.carbs = detailedBolusInfo.carbs;
treatment.mealBolus = treatment.carbs > 0;
treatment.boluscalc = detailedBolusInfo.boluscalc != null ? detailedBolusInfo.boluscalc.toString() : null;
// treatment.boluscalc = detailedBolusInfo.boluscalc != null ? detailedBolusInfo.boluscalc.toString() : null;
treatment.boluscalc = null;
UpdateReturn creatOrUpdateResult;
getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::treatment={} " + treatment);
@ -647,9 +650,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
if (detailedBolusInfo.carbTime != 0) {
Treatment carbsTreatment = new Treatment();
carbsTreatment.source = detailedBolusInfo.source;
carbsTreatment.pumpId = detailedBolusInfo.pumpId; // but this should never happen
carbsTreatment.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records
carbsTreatment.source = (detailedBolusInfo.getPumpType() == InterfaceIDs.PumpType.USER) ? Source.USER : Source.PUMP;
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.carbs = detailedBolusInfo.carbs;
getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: carbTime!=0, creating second treatment. CarbsTreatment={}" + carbsTreatment);
@ -660,7 +663,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
getService().createOrUpdateMedtronic(carbsTreatment, false);
//log.debug("Adding new Treatment record" + carbsTreatment);
}
if (newRecordCreated && detailedBolusInfo.isValid)
if (newRecordCreated && detailedBolusInfo.getBolusType() != Bolus.Type.PRIMING)
nsUpload.uploadTreatmentRecord(detailedBolusInfo);
if (!allowUpdate && !creatOrUpdateResult.getSuccess()) {

View file

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

View file

@ -23,14 +23,14 @@ class CommandSMBBolus(
override fun execute() {
val r: PumpEnactResult
val lastBolusTime = activePlugin.activeTreatments.lastBolusTime
if (lastBolusTime != 0L && lastBolusTime + T.mins(3).msecs() > DateUtil.now()) {
if (lastBolusTime != 0L && lastBolusTime + T.mins(3).msecs() > dateUtil._now()) {
aapsLogger.debug(LTag.PUMPQUEUE, "SMB requested but still in 3 min interval")
r = PumpEnactResult(injector).enacted(false).success(false).comment("SMB requested but still in 3 min interval")
} else if (detailedBolusInfo.deliverAt != 0L && detailedBolusInfo.deliverAt + T.mins(1).msecs() > System.currentTimeMillis()) {
} else if (detailedBolusInfo.deliverAtTheLatest != 0L && detailedBolusInfo.deliverAtTheLatest + T.mins(1).msecs() > System.currentTimeMillis()) {
r = activePlugin.activePump.deliverTreatment(detailedBolusInfo)
} else {
r = PumpEnactResult(injector).enacted(false).success(false).comment("SMB request too old")
aapsLogger.debug(LTag.PUMPQUEUE, "SMB bolus canceled. deliverAt: " + dateUtil.dateAndTimeString(detailedBolusInfo.deliverAt))
aapsLogger.debug(LTag.PUMPQUEUE, "SMB bolus canceled. deliverAt: " + dateUtil.dateAndTimeString(detailedBolusInfo.deliverAtTheLatest))
}
aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}")
callback?.result(r)?.run()

View file

@ -10,10 +10,10 @@ 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.database.entities.BolusCalculatorResult
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.db.Source
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
@ -35,8 +35,6 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import kotlin.math.abs
@ -241,47 +239,38 @@ class BolusWizard @Inject constructor(
return this
}
@Suppress("SpellCheckingInspection")
private fun nsJSON(): JSONObject {
val bolusCalcJSON = JSONObject()
try {
bolusCalcJSON.put("profile", profileName)
bolusCalcJSON.put("notes", notes)
bolusCalcJSON.put("eventTime", DateUtil.toISOString(Date()))
bolusCalcJSON.put("targetBGLow", targetBGLow)
bolusCalcJSON.put("targetBGHigh", targetBGHigh)
bolusCalcJSON.put("isf", sens)
bolusCalcJSON.put("ic", ic)
bolusCalcJSON.put("iob", -(insulinFromBolusIOB + insulinFromBasalIOB))
bolusCalcJSON.put("bolusiob", insulinFromBolusIOB)
bolusCalcJSON.put("basaliob", insulinFromBasalIOB)
bolusCalcJSON.put("bolusiobused", includeBolusIOB)
bolusCalcJSON.put("basaliobused", includeBasalIOB)
bolusCalcJSON.put("bg", bg)
bolusCalcJSON.put("insulinbg", insulinFromBG)
bolusCalcJSON.put("insulinbgused", useBg)
bolusCalcJSON.put("bgdiff", bgDiff)
bolusCalcJSON.put("insulincarbs", insulinFromCarbs)
bolusCalcJSON.put("carbs", carbs)
bolusCalcJSON.put("cob", cob)
bolusCalcJSON.put("cobused", useCob)
bolusCalcJSON.put("insulincob", insulinFromCOB)
bolusCalcJSON.put("othercorrection", correction)
bolusCalcJSON.put("insulinsuperbolus", insulinFromSuperBolus)
bolusCalcJSON.put("insulintrend", insulinFromTrend)
bolusCalcJSON.put("insulin", calculatedTotalInsulin)
bolusCalcJSON.put("superbolusused", useSuperBolus)
bolusCalcJSON.put("insulinsuperbolus", insulinFromSuperBolus)
bolusCalcJSON.put("trendused", useTrend)
bolusCalcJSON.put("insulintrend", insulinFromTrend)
bolusCalcJSON.put("trend", trend)
bolusCalcJSON.put("ttused", useTT)
bolusCalcJSON.put("percentageCorrection", percentageCorrection)
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return bolusCalcJSON
}
private fun createBolusCalculatorResult(): BolusCalculatorResult =
BolusCalculatorResult(
timestamp = dateUtil._now(),
targetBGLow = targetBGLow,
targetBGHigh = targetBGHigh,
isf = sens,
ic = ic,
bolusIOB = insulinFromBolusIOB,
wasBolusIOBUsed = includeBolusIOB,
basalIOB = insulinFromBasalIOB,
wasBasalIOBUsed = includeBasalIOB,
glucoseValue = bg,
wasGlucoseUsed = useBg && bg > 0,
glucoseDifference = bgDiff,
glucoseInsulin = insulinFromBG,
glucoseTrend = trend,
wasTrendUsed = useTrend,
trendInsulin = insulinFromTrend,
cob = cob,
wasCOBUsed = useCob,
cobInsulin = insulinFromCOB,
carbs = carbs.toDouble(),
wereCarbsUsed = cob > 0,
carbsInsulin = insulinFromCarbs,
otherCorrection = correction,
wasSuperbolusUsed = useSuperBolus,
superbolusInsulin = insulinFromSuperBolus,
wasTempTargetUsed = useTT,
totalInsulin = calculatedTotalInsulin,
percentageCorrection = percentageCorrection,
profileName = profileName
)
private fun confirmMessageAfterConstraints(advisor: Boolean): Spanned {
@ -339,15 +328,14 @@ class BolusWizard @Inject constructor(
val confirmMessage = confirmMessageAfterConstraints(advisor = true)
OKDialog.showConfirmation(ctx, resourceHelper.gs(R.string.boluswizard), confirmMessage, {
DetailedBolusInfo().apply {
eventType = TherapyEvent.Type.CORRECTION_BOLUS.text
eventType = TherapyEvent.Type.CORRECTION_BOLUS
insulin = insulinAfterConstraints
carbs = 0.0
context = ctx
glucose = bg
glucoseType = "Manual"
mgdlGlucose = Profile.toMgdl(bg, profile.units)
glucoseType = TherapyEvent.MeterType.MANUAL
carbTime = 0
boluscalc = nsJSON()
source = Source.USER
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
uel.log(Action.BOLUS_ADVISOR, notes, ValueWithUnit(eventType, Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U))
if (insulin > 0) {
@ -403,17 +391,16 @@ class BolusWizard @Inject constructor(
}
}
DetailedBolusInfo().apply {
eventType = TherapyEvent.Type.BOLUS_WIZARD.text
eventType = TherapyEvent.Type.BOLUS_WIZARD
insulin = insulinAfterConstraints
carbs = this@BolusWizard.carbs.toDouble()
context = ctx
glucose = bg
glucoseType = "Manual"
mgdlGlucose = Profile.toMgdl(bg, profile.units)
glucoseType = TherapyEvent.MeterType.MANUAL
carbTime = this@BolusWizard.carbTime
boluscalc = nsJSON()
source = Source.USER
bolusCalculatorResult = createBolusCalculatorResult()
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))
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) {
commandQueue.bolus(this, object : Callback() {
override fun run() {

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
@ -95,8 +96,8 @@ class CommandQueueTest : TestBaseWithProfile() {
}
}
lateinit var commandQueue: CommandQueue
lateinit var testPumpPlugin: TestPumpPlugin
private lateinit var commandQueue: CommandQueue
private lateinit var testPumpPlugin: TestPumpPlugin
@Before
fun prepare() {
@ -214,7 +215,7 @@ class CommandQueueTest : TestBaseWithProfile() {
Assert.assertEquals(0, commandQueue.size())
val smb = DetailedBolusInfo()
smb.lastKnownBolusTime = DateUtil.now()
smb.isSMB = true
smb.bolusType = Bolus.Type.SMB
commandQueue.bolus(smb, null)
commandQueue.bolus(DetailedBolusInfo(), null)
Assert.assertEquals(2, commandQueue.size())
@ -234,7 +235,7 @@ class CommandQueueTest : TestBaseWithProfile() {
// when
commandQueue.bolus(DetailedBolusInfo(), null)
val smb = DetailedBolusInfo()
smb.isSMB = true
smb.bolusType = Bolus.Type.SMB
val queued: Boolean = commandQueue.bolus(smb, null)
// then
@ -249,7 +250,7 @@ class CommandQueueTest : TestBaseWithProfile() {
// when
val bolus = DetailedBolusInfo()
bolus.isSMB = true
bolus.bolusType = Bolus.Type.SMB
bolus.lastKnownBolusTime = 0
val queued: Boolean = commandQueue.bolus(bolus, null)

View file

@ -25,6 +25,7 @@ import info.nightscout.androidaps.combo.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
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.TDD;
@ -490,7 +491,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(new Treatment());
bolusingEvent.getT().isSMB = detailedBolusInfo.isSMB;
bolusingEvent.getT().isSMB = detailedBolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB;
bolusingEvent.setPercent(100);
rxBus.send(bolusingEvent);
@ -568,7 +569,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
}
Treatment treatment = new Treatment();
treatment.isSMB = detailedBolusInfo.isSMB;
treatment.isSMB = detailedBolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB;
EventOverviewBolusProgress.INSTANCE.setT(treatment);
// start bolus delivery
@ -666,17 +667,18 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
*/
private boolean addBolusToTreatments(DetailedBolusInfo detailedBolusInfo, Bolus lastPumpBolus) {
DetailedBolusInfo bolusInfo = detailedBolusInfo.copy();
bolusInfo.date = calculateFakeBolusDate(lastPumpBolus);
bolusInfo.pumpId = bolusInfo.date;
bolusInfo.source = Source.PUMP;
bolusInfo.timestamp = calculateFakeBolusDate(lastPumpBolus);
bolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_COMBO);
bolusInfo.setPumpSerial(serialNumber());
bolusInfo.setBolusPumpId(bolusInfo.timestamp);
bolusInfo.insulin = lastPumpBolus.amount;
try {
if (bolusInfo.carbs > 0 && bolusInfo.carbTime != 0) {
// split out a separate carbs record without a pumpId
DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.date = bolusInfo.date + bolusInfo.carbTime * 60L * 1000L;
carbInfo.timestamp = bolusInfo.timestamp + bolusInfo.carbTime * 60L * 1000L;
carbInfo.carbs = bolusInfo.carbs;
carbInfo.source = Source.USER;
carbInfo.setPumpType(InterfaceIDs.PumpType.USER);
treatmentsPlugin.addToHistoryTreatment(carbInfo, true);
// remove carbs from bolusInfo to not trigger any unwanted code paths in
@ -687,7 +689,7 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
treatmentsPlugin.addToHistoryTreatment(bolusInfo, true);
} catch (Exception e) {
getAapsLogger().error("Adding treatment record failed", e);
if (bolusInfo.isSMB) {
if (bolusInfo.getBolusType() == info.nightscout.androidaps.database.entities.Bolus.Type.SMB) {
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, getResourceHelper().gs(R.string.combo_error_updating_treatment_record), Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
}
@ -1154,11 +1156,12 @@ public class ComboPlugin extends PumpPluginBase implements PumpInterface, Constr
boolean updated = false;
for (Bolus pumpBolus : history.bolusHistory) {
DetailedBolusInfo dbi = new DetailedBolusInfo();
dbi.date = calculateFakeBolusDate(pumpBolus);
dbi.pumpId = dbi.date;
dbi.source = Source.PUMP;
dbi.timestamp = calculateFakeBolusDate(pumpBolus);
dbi.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_COMBO);
dbi.setPumpSerial(serialNumber());
dbi.setBolusPumpId(dbi.timestamp);
dbi.insulin = pumpBolus.amount;
dbi.eventType = TherapyEvent.Type.CORRECTION_BOLUS.getText();
dbi.setEventType(TherapyEvent.Type.CORRECTION_BOLUS);
if (treatmentsPlugin.addToHistoryTreatment(dbi, true)) {
updated = true;
}

View file

@ -1,65 +0,0 @@
package info.nightscout.androidaps.data;
import android.content.Context;
import org.json.JSONObject;
import java.util.Date;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.db.Source;
/**
* Created by mike on 29.05.2017.
*/
public class DetailedBolusInfo {
public long date = System.currentTimeMillis();
public long lastKnownBolusTime;
public String eventType = TherapyEvent.Type.MEAL_BOLUS.getText();
public double insulin = 0;
public double carbs = 0;
public int source = Source.NONE;
public boolean isValid = true;
public double glucose = 0; // Bg value in current units
public String glucoseType = ""; // NS values: Manual, Finger, Sensor
public int carbTime = 0; // time shift of carbs in minutes
public JSONObject boluscalc = null; // additional bolus wizard info
public Context context = null; // context for progress dialog
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
public boolean isSMB = false; // is a Super-MicroBolus
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
public String notes = null;
public DetailedBolusInfo copy() {
DetailedBolusInfo n = new DetailedBolusInfo();
n.date = date;
n.eventType = eventType;
n.insulin = insulin;
n.carbs = carbs;
n.source = source;
n.isValid = isValid;
n.glucose = glucose;
n.glucoseType = glucoseType;
n.carbTime = carbTime;
n.boluscalc = boluscalc;
n.context = context;
n.pumpId = pumpId;
n.isSMB = isSMB;
n.deliverAt = deliverAt;
n.notes = notes;
return n;
}
@Override
public String toString() {
return new Date(date).toLocaleString() +
" date: " + date +
" insulin: " + insulin +
" carbs: " + carbs +
" isValid: " + isValid +
" carbTime: " + carbTime +
" isSMB: " + isSMB +
" deliverAt: " + new Date(deliverAt).toLocaleString();
}
}

View file

@ -0,0 +1,104 @@
package info.nightscout.androidaps.data
import android.content.Context
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.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.TherapyEvent
class DetailedBolusInfo {
// Requesting parameters for driver
@JvmField var insulin = 0.0
@JvmField var carbs = 0.0
// Additional requesting parameters
@JvmField var timestamp = System.currentTimeMillis()
@JvmField var carbTime = 0 // time shift of carbs in minutes
@JvmField var lastKnownBolusTime: Long = 0 // for SMB check
@JvmField var deliverAtTheLatest: Long = 0 // SMB should be delivered within 1 min from this time
@Transient var context: Context? = null // context for progress dialog
// Prefilled info for storing to db
var bolusCalculatorResult: BolusCalculatorResult? = null
var eventType = TherapyEvent.Type.MEAL_BOLUS
var notes: String? = null
var mgdlGlucose: Double? = null // Bg value in mgdl
var glucoseType: TherapyEvent.MeterType? = null // NS values: Manual, Finger, Sensor
var bolusType = Bolus.Type.NORMAL
// Collected info from driver
var pumpType: InterfaceIDs.PumpType? = null // if == USER
var pumpSerial: String? = null
var bolusPumpId: Long? = null
var carbsPumpId: Long? = null
fun createTherapyEvent(): TherapyEvent? =
if (mgdlGlucose != null || notes != null)
TherapyEvent(
timestamp = timestamp,
type = TherapyEvent.Type.NOTE,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL,
note = notes,
glucose = mgdlGlucose,
glucoseType = glucoseType
)
else null
fun createBolus(): Bolus? =
if (insulin != 0.0)
Bolus(
timestamp = timestamp,
amount = insulin,
type = bolusType,
isBasalInsulin = false
)
else null
fun createCarbs(): Carbs? =
if (carbs != 0.0)
Carbs(
timestamp = timestamp,
amount = carbs,
duration = 0
)
else null
fun toJsonString(): String =
Gson().toJson(this)
fun copy(): DetailedBolusInfo {
val n = DetailedBolusInfo()
n.insulin = insulin
n.carbs = carbs
n.timestamp = timestamp
n.carbTime = carbTime
n.lastKnownBolusTime = lastKnownBolusTime
n.deliverAtTheLatest = deliverAtTheLatest
n.context = context
n.bolusCalculatorResult = bolusCalculatorResult
n.eventType = eventType
n.notes = notes
n.mgdlGlucose = mgdlGlucose
n.glucoseType = glucoseType
n.bolusType = bolusType
n.pumpType = pumpType
n.pumpSerial = pumpSerial
n.bolusPumpId = bolusPumpId
n.carbsPumpId = carbsPumpId
return n
}
override fun toString(): String = toJsonString()
companion object {
fun fromJsonString(json: String): DetailedBolusInfo =
Gson().fromJson(json, DetailedBolusInfo::class.java)
}
}

View file

@ -4,7 +4,6 @@ import android.os.Build;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
@ -246,13 +245,14 @@ public class NSUpload {
}
public void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) {
/*
JSONObject data = new JSONObject();
try {
data.put("eventType", detailedBolusInfo.eventType);
if (detailedBolusInfo.insulin != 0d) data.put("insulin", detailedBolusInfo.insulin);
if (detailedBolusInfo.carbs != 0d) data.put("carbs", (int) detailedBolusInfo.carbs);
data.put("created_at", DateUtil.toISOString(detailedBolusInfo.date));
data.put("date", detailedBolusInfo.date);
data.put("created_at", DateUtil.toISOString(detailedBolusInfo.timestamp));
data.put("date", detailedBolusInfo.timestamp);
data.put("isSMB", detailedBolusInfo.isSMB);
if (detailedBolusInfo.pumpId != 0)
data.put("pumpId", detailedBolusInfo.pumpId);
@ -264,13 +264,15 @@ public class NSUpload {
data.put("boluscalc", detailedBolusInfo.boluscalc);
if (detailedBolusInfo.carbTime != 0)
data.put("preBolus", detailedBolusInfo.carbTime);
if (!StringUtils.isEmpty(detailedBolusInfo.notes)) {
data.put("notes", detailedBolusInfo.notes);
if (StringUtils.isNotEmpty(detailedBolusInfo.notes())) {
data.put("notes", detailedBolusInfo.notes());
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadCareportalEntryToNS(data, detailedBolusInfo.date);
uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp);
*/
}
public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) {

View file

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

View file

@ -12,7 +12,7 @@ import kotlin.math.abs
@Singleton
class DetailedBolusInfoStorage @Inject constructor(
val aapsLogger: AAPSLogger
){
) {
val store = ArrayList<DetailedBolusInfo>()
@ -27,8 +27,8 @@ class DetailedBolusInfoStorage @Inject constructor(
// Look for info with bolus
for (i in store.indices) {
val d = store[i]
aapsLogger.debug(LTag.PUMP, "Existing bolus info: " + store[i])
if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && abs(store[i].insulin - bolus) < 0.01) {
aapsLogger.debug(LTag.PUMP, "Existing bolus info: " + store[i])
if (bolusTime > d.timestamp - T.mins(1).msecs() && bolusTime < d.timestamp + T.mins(1).msecs() && abs(store[i].insulin - bolus) < 0.01) {
aapsLogger.debug(LTag.PUMP, "Using & removing bolus info: ${store[i]}")
store.removeAt(i)
return d
@ -37,7 +37,7 @@ class DetailedBolusInfoStorage @Inject constructor(
// If not found use time only
for (i in store.indices) {
val d = store[i]
if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && bolus <= store[i].insulin + 0.01) {
if (bolusTime > d.timestamp - T.mins(1).msecs() && bolusTime < d.timestamp + T.mins(1).msecs() && bolus <= store[i].insulin + 0.01) {
aapsLogger.debug(LTag.PUMP, "Using TIME-ONLY & removing bolus info: ${store[i]}")
store.removeAt(i)
return d

View file

@ -1,13 +1,18 @@
package info.nightscout.androidaps.data
import android.content.Context
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.TherapyEvent
import org.apache.commons.lang3.builder.EqualsBuilder
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.modules.junit4.PowerMockRunner
import org.mockito.Mock
@RunWith(PowerMockRunner::class)
class DetailedBolusInfoTest {
class DetailedBolusInfoTest : TestBase() {
@Mock lateinit var context: Context
@Test fun toStringShouldBeOverloaded() {
val detailedBolusInfo = DetailedBolusInfo()
@ -16,8 +21,96 @@ class DetailedBolusInfoTest {
@Test fun copyShouldCopyAllProperties() {
val d1 = DetailedBolusInfo()
d1.deliverAt = 123
d1.deliverAtTheLatest = 123
val d2 = d1.copy()
Assert.assertEquals(true, EqualsBuilder.reflectionEquals(d2, d1))
}
@Test
fun shouldAllowSerialization() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.bolusCalculatorResult = createBolusCalculatorResult()
detailedBolusInfo.context = context
detailedBolusInfo.eventType = TherapyEvent.Type.BOLUS_WIZARD
val serialized = detailedBolusInfo.toJsonString()
val deserialized = DetailedBolusInfo.fromJsonString(serialized)
Assert.assertEquals(1L, deserialized.bolusCalculatorResult?.timestamp)
Assert.assertEquals(TherapyEvent.Type.BOLUS_WIZARD, deserialized.eventType)
// Context should be excluded
Assert.assertNull(deserialized.context)
}
@Test
fun generateTherapyEventTest() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.timestamp = 1000
detailedBolusInfo.notes = "note"
detailedBolusInfo.mgdlGlucose = 180.0
detailedBolusInfo.glucoseType = TherapyEvent.MeterType.FINGER
val therapyEvent = detailedBolusInfo.createTherapyEvent()
Assert.assertEquals(1000L, therapyEvent?.timestamp)
Assert.assertEquals(TherapyEvent.Type.NOTE, therapyEvent?.type)
Assert.assertEquals(TherapyEvent.GlucoseUnit.MGDL, therapyEvent?.glucoseUnit)
Assert.assertEquals("note", therapyEvent?.note)
Assert.assertEquals(180.0, therapyEvent?.glucose)
Assert.assertEquals(TherapyEvent.MeterType.FINGER, therapyEvent?.glucoseType)
}
@Test
fun generateBolus() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.timestamp = 1000
detailedBolusInfo.bolusType = Bolus.Type.SMB
detailedBolusInfo.insulin = 7.0
val bolus = detailedBolusInfo.createBolus()
Assert.assertEquals(1000L, bolus?.timestamp)
Assert.assertEquals(Bolus.Type.SMB, bolus?.type)
Assert.assertEquals(7.0, bolus?.amount)
}
@Test
fun generateCarbs() {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.timestamp = 1000
detailedBolusInfo.carbs = 6.0
val carbs = detailedBolusInfo.createCarbs()
Assert.assertEquals(1000L, carbs?.timestamp)
Assert.assertEquals(6.0, carbs?.amount)
}
private fun createBolusCalculatorResult(): BolusCalculatorResult =
BolusCalculatorResult(
timestamp = 1,
targetBGLow = 5.0,
targetBGHigh = 5.0,
isf = 5.0,
ic = 5.0,
bolusIOB = 1.0,
wasBolusIOBUsed = true,
basalIOB = 1.0,
wasBasalIOBUsed = true,
glucoseValue = 10.0,
wasGlucoseUsed = true,
glucoseDifference = 1.0,
glucoseInsulin = 1.0,
glucoseTrend = 1.0,
wasTrendUsed = true,
trendInsulin = 1.0,
cob = 10.0,
wasCOBUsed = true,
cobInsulin = 1.0,
carbs = 5.0,
wereCarbsUsed = true,
carbsInsulin = 1.0,
otherCorrection = 1.0,
wasSuperbolusUsed = true,
superbolusInsulin = 1.0,
wasTempTargetUsed = true,
totalInsulin = 15.0,
percentageCorrection = 50.0,
profileName = "profile"
)
}

View file

@ -18,13 +18,13 @@ class DetailedBolusInfoStorageTest : TestBase() {
private val info3 = DetailedBolusInfo()
private lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
init {
info1.date = 1000000
info1.timestamp = 1000000
info1.insulin = 3.0
info2.date = 1000001
info2.timestamp = 1000001
info2.insulin = 4.0
info3.date = 2000000
info3.timestamp = 2000000
info3.insulin = 5.0
}

View file

@ -17,4 +17,5 @@ android {
dependencies {
implementation project(':core')
implementation project(':dana')
implementation project(':database')
}

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.danar.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
@ -164,7 +165,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
@ -178,7 +179,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
result.comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered());
detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.date = System.currentTimeMillis();
detailedBolusInfo.timestamp = System.currentTimeMillis();
activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, false);
return result;
} else {

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.danar.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
@ -171,7 +172,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
speed = 60;
break;
}
detailedBolusInfo.date = DateUtil.now() + (long) (speed * detailedBolusInfo.insulin * 1000);
detailedBolusInfo.timestamp = DateUtil.now() + (long) (speed * detailedBolusInfo.insulin * 1000);
// clean carbs to prevent counting them as twice because they will picked up as another record
// I don't think it's necessary to copy DetailedBolusInfo right now for carbs records
double carbs = detailedBolusInfo.carbs;
@ -183,7 +184,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
detailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);

View file

@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.danar.R
import info.nightscout.androidaps.danar.comm.MessageBase
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.db.ExtendedBolus
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TemporaryBasal
@ -91,9 +92,10 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.BOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo()
detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP
detailedBolusInfo.pumpId = datetime
detailedBolusInfo.timestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2
detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = datetime
detailedBolusInfo.insulin = param1 / 100.0
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U Duration: " + param2 + "min")
@ -103,9 +105,10 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.DUALBOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo()
detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP
detailedBolusInfo.pumpId = datetime
detailedBolusInfo.timestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2
detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = datetime
detailedBolusInfo.insulin = param1 / 100.0
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT DUALBOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U Duration: " + param2 + "min")
@ -154,9 +157,10 @@ class MsgHistoryEvents_v2 constructor(
info.nightscout.androidaps.dana.DanaPump.CARBS -> {
val emptyCarbsInfo = DetailedBolusInfo()
emptyCarbsInfo.carbs = param1.toDouble()
emptyCarbsInfo.date = datetime
emptyCarbsInfo.source = Source.PUMP
emptyCarbsInfo.pumpId = datetime
emptyCarbsInfo.timestamp = datetime
emptyCarbsInfo.pumpType = InterfaceIDs.PumpType.DANA_RV2
emptyCarbsInfo.pumpSerial = danaPump.serialNumber
emptyCarbsInfo.carbsPumpId = datetime
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false)
aapsLogger.debug(LTag.PUMPBTCOMM, (if (newRecord) "**NEW** " else "") + "EVENT CARBS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Carbs: " + param1 + "g")
status = "CARBS " + dateUtil.timeString(datetime)

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.danar.services.DanaRExecutionService;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
@ -162,7 +163,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
@ -176,7 +177,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
result.comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered());
detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.date = System.currentTimeMillis();
detailedBolusInfo.timestamp = System.currentTimeMillis();
activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, false);
return result;
} else {

View file

@ -15,6 +15,7 @@ import info.nightscout.androidaps.danars.services.DanaRSService
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.db.Treatment
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.events.EventConfigBuilderChange
@ -269,7 +270,7 @@ class DanaRSPlugin @Inject constructor(
}
// RS stores end time for bolus, we need to adjust time
// default delivery speed is 12 sec/U
detailedBolusInfo.date = DateUtil.now() + (speed * detailedBolusInfo.insulin * 1000).toLong()
detailedBolusInfo.timestamp = DateUtil.now() + (speed * detailedBolusInfo.insulin * 1000).toLong()
// clean carbs to prevent counting them as twice because they will picked up as another record
// I don't think it's necessary to copy DetailedBolusInfo right now for carbs records
val carbs = detailedBolusInfo.carbs
@ -279,7 +280,7 @@ class DanaRSPlugin @Inject constructor(
detailedBolusInfo.carbTime = 0
detailedBolusInfoStorage.add(detailedBolusInfo) // will be picked up on reading history
val t = Treatment()
t.isSMB = detailedBolusInfo.isSMB
t.isSMB = detailedBolusInfo.bolusType == Bolus.Type.SMB
var connectionOK = false
if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService?.bolus(detailedBolusInfo.insulin, carbs.toInt(), DateUtil.now() + T.mins(carbTime.toLong()).msecs(), t)
?: false

View file

@ -6,6 +6,7 @@ import info.nightscout.androidaps.danars.R
import info.nightscout.androidaps.danars.encryption.BleEncryption
import info.nightscout.androidaps.data.DetailedBolusInfo
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.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.db.ExtendedBolus
@ -132,9 +133,10 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.BOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo()
detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP
detailedBolusInfo.pumpId = datetime
detailedBolusInfo.timestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RS
detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = pumpId
detailedBolusInfo.insulin = param1 / 100.0
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U Duration: " + param2 + "min")
@ -144,9 +146,10 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.DUALBOLUS -> {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo()
detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP
detailedBolusInfo.pumpId = datetime
detailedBolusInfo.timestamp = datetime
detailedBolusInfo.pumpType = InterfaceIDs.PumpType.DANA_RS
detailedBolusInfo.pumpSerial = danaPump.serialNumber
detailedBolusInfo.bolusPumpId = pumpId
detailedBolusInfo.insulin = param1 / 100.0
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT DUALBOLUS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Bolus: " + param1 / 100.0 + "U Duration: " + param2 + "min")
@ -206,9 +209,10 @@ open class DanaRS_Packet_APS_History_Events(
DanaPump.CARBS -> {
val emptyCarbsInfo = DetailedBolusInfo()
emptyCarbsInfo.carbs = param1.toDouble()
emptyCarbsInfo.date = datetime
emptyCarbsInfo.source = Source.PUMP
emptyCarbsInfo.pumpId = datetime
emptyCarbsInfo.timestamp = datetime
emptyCarbsInfo.pumpType = InterfaceIDs.PumpType.DANA_RS
emptyCarbsInfo.pumpSerial = danaPump.serialNumber
emptyCarbsInfo.carbsPumpId = pumpId
val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(emptyCarbsInfo, false)
aapsLogger.debug(LTag.PUMPCOMM, "[" + id + "] " + (if (newRecord) "**NEW** " else "") + "EVENT CARBS (" + recordCode + ") " + dateUtil.dateAndTimeString(datetime) + " (" + datetime + ")" + " Carbs: " + param1 + "g")
status = "CARBS " + dateUtil.timeString(datetime)

File diff suppressed because it is too large Load diff

View file

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

View file

@ -23,6 +23,7 @@ open class DatabaseModule {
.databaseBuilder(context, AppDatabase::class.java, fileName)
.addMigrations(migration5to6)
.addMigrations(migration6to7)
.addMigrations(migration7to8)
.fallbackToDestructiveMigration()
.build()
@ -38,8 +39,18 @@ open class DatabaseModule {
private val migration6to7 = object : Migration(6, 7) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS foods")
database.execSQL("CREATE TABLE IF NOT EXISTS foods (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `name` TEXT NOT NULL, `category` TEXT, `subCategory` TEXT, `portion` REAL NOT NULL, `carbs` INTEGER NOT NULL, `fat` INTEGER, `protein` INTEGER, `energy` INTEGER, `unit` TEXT NOT NULL, `gi` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `foods`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_foods_referenceId` ON `foods` (`referenceId`)")
}
}
private val migration7to8 = object : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) {
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 INDEX IF NOT EXISTS `index_bolusCalculatorResults_referenceId` ON bolusCalculatorResults (`referenceId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_bolusCalculatorResults_timestamp` ON bolusCalculatorResults (`timestamp`)")
}
}
}

View file

@ -1,20 +1,25 @@
package info.nightscout.androidaps.database.embedments
data class InterfaceIDs(
var nightscoutSystemId: String? = null,
var nightscoutId: String? = null,
var pumpType: PumpType? = null,
var pumpSerial: String? = null,
var pumpId: Long? = null,
var startId: Long? = null,
var endId: Long? = null
var nightscoutSystemId: String? = null,
var nightscoutId: String? = null,
var pumpType: PumpType? = null, // if == USER pumpSerial & pumpId can be null
var pumpSerial: String? = null,
var pumpId: Long? = null,
var startId: Long? = null,
var endId: Long? = null
) {
enum class PumpType {
USER,
VIRTUAL_PUMP,
ACCU_CHEK_INSIGHT,
ACCU_CHEK_COMBO,
DANA_R,
DANA_RV2,
DANA_RS,
MEDTRONIC,
OMNIPOD
OMNIPOD_EROS,
OMNIPOD_DASH
}
}

View file

@ -1,36 +1,42 @@
package info.nightscout.androidaps.database.entities
import androidx.room.*
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import info.nightscout.androidaps.database.TABLE_BOLUSES
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.TimeZone
import java.util.*
@Entity(tableName = TABLE_BOLUSES,
foreignKeys = [ForeignKey(
entity = Bolus::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
foreignKeys = [
ForeignKey(
entity = Bolus::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
data class Bolus(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = null,
override var interfaceIDs_backing: InterfaceIDs? = null,
override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
var amount: Double,
var type: Type,
var isBasalInsulin: Boolean,
@Embedded
var insulinConfiguration: InsulinConfiguration? = null
var insulinConfiguration: InsulinConfiguration? = null
) : TraceableDBEntry, DBEntryWithTime {
enum class Type {
NORMAL,
SMB,

View file

@ -8,20 +8,20 @@ import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.TimeZone
@Entity(tableName = TABLE_BOLUS_CALCULATOR_RESULTS,
foreignKeys = [ForeignKey(
entity = BolusCalculatorResult::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
foreignKeys = [ForeignKey(
entity = BolusCalculatorResult::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
data class BolusCalculatorResult(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = null,
override var interfaceIDs_backing: InterfaceIDs? = null,
override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
var targetBGLow: Double,
@ -49,5 +49,7 @@ data class BolusCalculatorResult(
var wasSuperbolusUsed: Boolean,
var superbolusInsulin: Double,
var wasTempTargetUsed: Boolean,
var totalInsulin: Double
var totalInsulin: Double,
var percentageCorrection: Double,
var profileName: String
) : TraceableDBEntry, DBEntryWithTime

View file

@ -1,27 +1,31 @@
package info.nightscout.androidaps.database.entities
import androidx.room.*
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import info.nightscout.androidaps.database.TABLE_CARBS
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.DBEntryWithTimeAndDuration
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
import java.util.TimeZone
import java.util.*
@Entity(tableName = TABLE_CARBS,
foreignKeys = [ForeignKey(
entity = Carbs::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
foreignKeys = [ForeignKey(
entity = Carbs::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("timestamp")])
data class Carbs(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = null,
override var interfaceIDs_backing: InterfaceIDs? = null,
override var timestamp: Long,
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
override var duration: Long,

View file

@ -6,49 +6,51 @@ import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
@Entity(tableName = TABLE_MEAL_LINKS,
foreignKeys = [ForeignKey(
entity = Bolus::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("bolusId")), ForeignKey(
entity = Carbs::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("carbsId")), ForeignKey(
entity = BolusCalculatorResult::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("bolusCalcResultId")), ForeignKey(
entity = TemporaryBasal::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("superbolusTempBasalId")), ForeignKey(
entity = TherapyEvent::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("noteId")), ForeignKey(
entity = MealLink::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("bolusId"),
Index("carbsId"), Index("bolusCalcResultId"),
Index("superbolusTempBasalId"), Index("noteId")])
foreignKeys = [
ForeignKey(
entity = Bolus::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("bolusId")),
ForeignKey(
entity = Carbs::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("carbsId")),
ForeignKey(
entity = BolusCalculatorResult::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("bolusCalcResultId")),
ForeignKey(
entity = TemporaryBasal::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("superbolusTempBasalId")),
ForeignKey(
entity = TherapyEvent::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("noteId")),
ForeignKey(
entity = MealLink::class,
parentColumns = ["id"],
childColumns = ["referenceId"])],
indices = [Index("referenceId"), Index("bolusId"),
Index("carbsId"), Index("bolusCalcResultId"),
Index("superbolusTempBasalId"), Index("noteId")])
data class MealLink(
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = null,
var bolusId: Long? = null,
var carbsId: Long? = null,
var bolusCalcResultId: Long? = null,
var superbolusTempBasalId: Long? = null,
var noteId: Long? = null
@PrimaryKey(autoGenerate = true)
override var id: Long = 0,
override var version: Int = 0,
override var dateCreated: Long = -1,
override var isValid: Boolean = true,
override var referenceId: Long? = null,
@Embedded
override var interfaceIDs_backing: InterfaceIDs? = null,
var bolusId: Long? = null,
var carbsId: Long? = null,
var bolusCalcResultId: Long? = null,
var superbolusTempBasalId: Long? = null,
var noteId: Long? = null
) : TraceableDBEntry {
override val foreignKeysValid: Boolean
get() = super.foreignKeysValid && bolusId != 0L && carbsId != 0L &&
bolusCalcResultId != 0L && superbolusTempBasalId != 0L && noteId != 0L
bolusCalcResultId != 0L && superbolusTempBasalId != 0L && noteId != 0L
}

View file

@ -119,6 +119,7 @@ data class UserEntry(
constructor(ivalue: Int, unit: Units, condition:Boolean = true) : this(0.0, ivalue, 0, "", unit, condition)
constructor(lvalue: Long, unit: Units, condition:Boolean = true) : this(0.0,0, lvalue, "", unit, condition)
constructor(svalue: String, unit:Units) : this(0.0,0, 0, svalue, unit, svalue != "")
constructor(svalue: TherapyEvent.Type, unit:Units) : this(0.0,0, 0, svalue.text, unit)
constructor(dvalue: Double, unit:String) : this(dvalue,0, 0, "", Units.fromText(unit))
constructor(rStringRef: Int, nbParam: Long) : this(0.0, rStringRef, nbParam, "", Units.R_String, !rStringRef.equals(0)) // additionnal constructors for formated strings with additional values as parameters (define number of parameters as long

View file

@ -0,0 +1,43 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.*
/**
* Creates the MealLink
*/
class InsertMealLinkTransaction(
private val bolus: Bolus? = null,
private val carbs: Carbs? = null,
private val bolusCalculatorResult: BolusCalculatorResult? = null,
private val therapyEvent: TherapyEvent? = null,
private val superBolusTemporaryBasal: TemporaryBasal? = null
) : Transaction<InsertMealLinkTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
val bolusId = if (bolus != null) database.bolusDao.insert(bolus) else null
val carbsId = if (carbs != null) database.carbsDao.insert(carbs) else null
val bolusCalculatorResultId = if (bolusCalculatorResult != null) database.bolusCalculatorResultDao.insert(bolusCalculatorResult) else null
val temporaryBasalId = if (superBolusTemporaryBasal != null) database.temporaryBasalDao.insert(superBolusTemporaryBasal) else null
val therapyEventId = if (therapyEvent != null) database.therapyEventDao.insert(therapyEvent) else null
val mealLink = MealLink(
bolusId = bolusId,
carbsId = carbsId,
bolusCalcResultId = bolusCalculatorResultId,
superbolusTempBasalId = temporaryBasalId,
noteId = therapyEventId
)
database.mealLinkDao.insert(mealLink)
result.inserted.add(mealLink)
return result
}
class TransactionResult {
val inserted = mutableListOf<MealLink>()
}
}

View file

@ -31,6 +31,8 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
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.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.ExtendedBolus;
@ -591,13 +593,13 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
bolusMessage.setDuration(0);
bolusMessage.setExtendedAmount(0);
bolusMessage.setImmediateAmount(insulin);
bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.isSMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration, false));
bolusMessage.setVibration(sp.getBoolean(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? R.string.key_disable_vibration_auto : R.string.key_disable_vibration, false));
bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId();
bolusCancelled = false;
}
result.success(true).enacted(true);
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
t.isSMB = detailedBolusInfo.getBolusType() == Bolus.Type.SMB;
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(t);
bolusingEvent.setStatus(resourceHelper.gs(R.string.insight_delivered, 0d, insulin));
@ -609,14 +611,15 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
insightBolusID.timestamp = System.currentTimeMillis();
insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber();
databaseHelper.createOrUpdate(insightBolusID);
detailedBolusInfo.date = insightBolusID.timestamp;
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.pumpId = insightBolusID.id;
detailedBolusInfo.timestamp = insightBolusID.timestamp;
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(insightBolusID.id);
if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime != 0) {
DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.carbs = detailedBolusInfo.carbs;
carbInfo.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60L * 1000L;
carbInfo.source = Source.USER;
carbInfo.timestamp = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L;
carbInfo.setPumpType(InterfaceIDs.PumpType.USER);
treatmentsPlugin.addToHistoryTreatment(carbInfo, false);
detailedBolusInfo.carbTime = 0;
detailedBolusInfo.carbs = 0;
@ -1390,9 +1393,10 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
databaseHelper.createOrUpdate(bolusID);
if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = bolusID.timestamp;
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.pumpId = bolusID.id;
detailedBolusInfo.timestamp = bolusID.timestamp;
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(bolusID.id);
detailedBolusInfo.insulin = event.getImmediateAmount();
treatmentsPlugin.addToHistoryTreatment(detailedBolusInfo, true);
}
@ -1424,9 +1428,10 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
databaseHelper.createOrUpdate(bolusID);
if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = bolusID.timestamp;
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.pumpId = bolusID.id;
detailedBolusInfo.timestamp = bolusID.timestamp;
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT);
detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(bolusID.id);
detailedBolusInfo.insulin = event.getImmediateAmount();
treatmentsPlugin.addToHistoryTreatment(detailedBolusInfo, true);
}
@ -1553,7 +1558,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
private void logNote(long date, String note) {
if (repository.getTherapyEventByTimestamp(TherapyEvent.Type.NOTE, date) != null) return;
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, TherapyEvent.Type.NOTE, 0, note, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, null))
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, TherapyEvent.Type.NOTE, 0, note, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
@ -1575,7 +1580,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
private void uploadCareportalEvent(long date, TherapyEvent.Type event) {
if (repository.getTherapyEventByTimestamp(event, date) != null) return;
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, event, 0, null, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, null))
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, event, 0, null, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)

View file

@ -32,6 +32,7 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventRefreshOverview;
@ -879,15 +880,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
long now = System.currentTimeMillis();
detailedBolusInfo.date = now;
detailedBolusInfo.deliverAt = now; // not sure about that one
detailedBolusInfo.timestamp = now;
detailedBolusInfo.deliverAtTheLatest = now; // not sure about that one
activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true);
// we subtract insulin, exact amount will be visible with next remainingInsulin update.
medtronicPumpStatus.reservoirRemainingUnits -= detailedBolusInfo.insulin;
incrementStatistics(detailedBolusInfo.isSMB ? MedtronicConst.Statistics.SMBBoluses
incrementStatistics(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? MedtronicConst.Statistics.SMBBoluses
: MedtronicConst.Statistics.StandardBoluses);

View file

@ -22,6 +22,7 @@ import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.data.DetailedBolusInfo;
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.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.DbObjectBase;
@ -80,6 +81,7 @@ public class MedtronicHistoryData {
private final NSUpload nsUpload;
private final MedtronicUtil medtronicUtil;
private final MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder;
private final MedtronicPumpStatus medtronicPumpStatus;
private final DatabaseHelperInterface databaseHelper;
private final AppRepository repository;
@ -114,6 +116,7 @@ public class MedtronicHistoryData {
NSUpload nsUpload,
MedtronicUtil medtronicUtil,
MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder,
MedtronicPumpStatus medtronicPumpStatus,
DatabaseHelperInterface databaseHelperInterface,
AppRepository repository
) {
@ -126,6 +129,7 @@ public class MedtronicHistoryData {
this.nsUpload = nsUpload;
this.medtronicUtil = medtronicUtil;
this.medtronicPumpHistoryDecoder = medtronicPumpHistoryDecoder;
this.medtronicPumpStatus = medtronicPumpStatus;
this.databaseHelper = databaseHelperInterface;
this.repository = repository;
}
@ -982,9 +986,10 @@ public class MedtronicHistoryData {
case Normal: {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = tryToGetByLocalTime(bolus.atechDateTime);
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.pumpId = bolus.getPumpId();
detailedBolusInfo.timestamp = tryToGetByLocalTime(bolus.atechDateTime);
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.MEDTRONIC);
detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber);
detailedBolusInfo.setBolusPumpId(bolus.getPumpId());
detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount();
addCarbsFromEstimate(detailedBolusInfo, bolus);
@ -996,8 +1001,8 @@ public class MedtronicHistoryData {
bolus.setLinkedObject(detailedBolusInfo);
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.date,
detailedBolusInfo.pumpId, detailedBolusInfo.insulin, newRecord));
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp,
detailedBolusInfo.getBolusPumpId(), detailedBolusInfo.insulin, newRecord));
}
break;

View file

@ -31,6 +31,7 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
@ -72,7 +73,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.Comm
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandResumeDelivery;
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandSuspendDelivery;
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandUpdateAlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.data.ActiveBolus;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.data.RLHistoryItemOmnipod;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.definition.OmnipodErosStorageKeys;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.action.service.ExpirationReminderBuilder;
@ -349,8 +349,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
String activeBolusString = sp.getString(OmnipodErosStorageKeys.Preferences.ACTIVE_BOLUS, "");
aapsLogger.warn(LTag.PUMP, "Found active bolus in SP: {}. Adding Treatment.", activeBolusString);
try {
ActiveBolus activeBolus = aapsOmnipodUtil.getGsonInstance().fromJson(activeBolusString, ActiveBolus.class);
aapsOmnipodErosManager.addBolusToHistory(activeBolus.toDetailedBolusInfo(aapsLogger));
aapsOmnipodErosManager.addBolusToHistory(DetailedBolusInfo.Companion.fromJsonString(activeBolusString));
} catch (Exception ex) {
aapsLogger.error(LTag.PUMP, "Failed to add active bolus to history", ex);
}
@ -1087,7 +1086,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
PumpEnactResult result = executeCommand(OmnipodCommandType.SET_BOLUS, () -> aapsOmnipodErosManager.bolus(detailedBolusInfo));
if (result.getSuccess()) {
incrementStatistics(detailedBolusInfo.isSMB ? OmnipodErosStorageKeys.Statistics.SMB_BOLUSES_DELIVERED
incrementStatistics(detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? OmnipodErosStorageKeys.Statistics.SMB_BOLUSES_DELIVERED
: OmnipodErosStorageKeys.Statistics.STANDARD_BOLUSES_DELIVERED);
result.carbsDelivered(detailedBolusInfo.carbs);

View file

@ -1,79 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.data;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
// Used for storing active bolus during bolus,
// so we can recover it and add it to treatments after the app crashed or got killed
// Storing DetailedBolusInfo itself is no good because it contains a reference to Context
// and to JSONObject, which are both not serializable
// TODO add tests
public class ActiveBolus {
private long date;
private long lastKnownBolusTime;
private String eventType;
private double insulin;
private double carbs;
private int source;
private boolean isValid;
private double glucose;
private String glucoseType;
private int carbTime;
private String boluscalc;
private long pumpId;
private boolean isSMB;
private long deliverAt;
private String notes;
public static ActiveBolus fromDetailedBolusInfo(DetailedBolusInfo detailedBolusInfo) {
ActiveBolus activeBolus = new ActiveBolus();
activeBolus.date = detailedBolusInfo.date;
activeBolus.lastKnownBolusTime = detailedBolusInfo.lastKnownBolusTime;
activeBolus.eventType = detailedBolusInfo.eventType;
activeBolus.insulin = detailedBolusInfo.insulin;
activeBolus.carbs = detailedBolusInfo.carbs;
activeBolus.source = detailedBolusInfo.source;
activeBolus.isValid = detailedBolusInfo.isValid;
activeBolus.glucose = detailedBolusInfo.glucose;
activeBolus.glucoseType = detailedBolusInfo.glucoseType;
activeBolus.carbTime = detailedBolusInfo.carbTime;
activeBolus.boluscalc = detailedBolusInfo.boluscalc == null ? null : detailedBolusInfo.boluscalc.toString();
activeBolus.pumpId = detailedBolusInfo.pumpId;
activeBolus.isSMB = detailedBolusInfo.isSMB;
activeBolus.deliverAt = detailedBolusInfo.deliverAt;
activeBolus.notes = detailedBolusInfo.notes;
return activeBolus;
}
public DetailedBolusInfo toDetailedBolusInfo(AAPSLogger aapsLogger) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = date;
detailedBolusInfo.lastKnownBolusTime = lastKnownBolusTime;
detailedBolusInfo.eventType = eventType;
detailedBolusInfo.insulin = insulin;
detailedBolusInfo.carbs = carbs;
detailedBolusInfo.source = source;
detailedBolusInfo.isValid = isValid;
detailedBolusInfo.glucose = glucose;
detailedBolusInfo.glucoseType = glucoseType;
detailedBolusInfo.carbTime = carbTime;
if (!StringUtils.isEmpty(boluscalc)) {
try {
detailedBolusInfo.boluscalc = new JSONObject(boluscalc);
} catch (JSONException ex) {
// ignore
aapsLogger.warn(LTag.PUMP, "Could not parse bolusCalc string to JSON: " + boluscalc, ex);
}
}
detailedBolusInfo.pumpId = pumpId;
detailedBolusInfo.isSMB = isSMB;
detailedBolusInfo.deliverAt = deliverAt;
detailedBolusInfo.notes = notes;
return detailedBolusInfo;
}
}

View file

@ -19,6 +19,8 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
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.transactions.InsertTherapyEventIfNewTransaction;
import info.nightscout.androidaps.db.OmnipodHistoryRecord;
@ -41,7 +43,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.R;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.data.ActiveBolus;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.definition.OmnipodErosStorageKeys;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.definition.PodHistoryEntryType;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.message.response.StatusResponse;
@ -124,7 +125,6 @@ public class AapsOmnipodErosManager {
private boolean batteryChangeLoggingEnabled;
private final CompositeDisposable disposable = new CompositeDisposable();
private boolean aBoolean;
@Inject
public AapsOmnipodErosManager(OmnipodRileyLinkCommunicationManager communicationService,
@ -374,11 +374,11 @@ public class AapsOmnipodErosManager {
public PumpEnactResult bolus(DetailedBolusInfo detailedBolusInfo) {
OmnipodManager.BolusCommandResult bolusCommandResult;
boolean beepsEnabled = detailedBolusInfo.isSMB ? isSmbBeepsEnabled() : isBolusBeepsEnabled();
boolean beepsEnabled = detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? isSmbBeepsEnabled() : isBolusBeepsEnabled();
Date bolusStarted;
try {
bolusCommandResult = executeCommand(() -> delegate.bolus(PumpType.Omnipod_Eros.determineCorrectBolusSize(detailedBolusInfo.insulin), beepsEnabled, beepsEnabled, detailedBolusInfo.isSMB ? null :
bolusCommandResult = executeCommand(() -> delegate.bolus(PumpType.Omnipod_Eros.determineCorrectBolusSize(detailedBolusInfo.insulin), beepsEnabled, beepsEnabled, detailedBolusInfo.getBolusType() == Bolus.Type.SMB ? null :
(estimatedUnitsDelivered, percentage) -> {
EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE;
progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, detailedBolusInfo.insulin));
@ -395,15 +395,16 @@ public class AapsOmnipodErosManager {
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
if (detailedBolusInfo.isSMB) {
if (detailedBolusInfo.getBolusType() == Bolus.Type.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);
} else {
showErrorDialog(getStringResource(R.string.omnipod_eros_error_bolus_failed_uncertain), isNotificationUncertainBolusSoundEnabled() ? R.raw.boluserror : null);
}
}
detailedBolusInfo.date = bolusStarted.getTime();
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.timestamp = bolusStarted.getTime();
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.OMNIPOD_EROS);
detailedBolusInfo.setPumpSerial(serialNumber());
// Store the current bolus for in case the app crashes, gets killed, the phone dies or whatever before the bolus finishes
// If we have a stored value for the current bolus on startup, we'll create a Treatment for it
@ -423,8 +424,7 @@ public class AapsOmnipodErosManager {
//
// I discussed this with the AAPS team but nobody seems to care so we're stuck with this ugly workaround for now
try {
ActiveBolus activeBolus = ActiveBolus.fromDetailedBolusInfo(detailedBolusInfo);
sp.putString(OmnipodErosStorageKeys.Preferences.ACTIVE_BOLUS, aapsOmnipodUtil.getGsonInstance().toJson(activeBolus));
sp.putString(OmnipodErosStorageKeys.Preferences.ACTIVE_BOLUS, detailedBolusInfo.toJsonString());
aapsLogger.debug(LTag.PUMP, "Stored active bolus to SP for recovery");
} catch (Exception ex) {
aapsLogger.error(LTag.PUMP, "Failed to store active bolus to SP", ex);
@ -705,14 +705,16 @@ public class AapsOmnipodErosManager {
public void addBolusToHistory(DetailedBolusInfo originalDetailedBolusInfo) {
DetailedBolusInfo detailedBolusInfo = originalDetailedBolusInfo.copy();
detailedBolusInfo.pumpId = addSuccessToHistory(detailedBolusInfo.date, PodHistoryEntryType.SET_BOLUS, detailedBolusInfo.insulin + ";" + detailedBolusInfo.carbs);
detailedBolusInfo.setPumpType(InterfaceIDs.PumpType.OMNIPOD_EROS);
detailedBolusInfo.setPumpSerial(serialNumber());
detailedBolusInfo.setBolusPumpId(addSuccessToHistory(detailedBolusInfo.timestamp, PodHistoryEntryType.SET_BOLUS, detailedBolusInfo.insulin + ";" + detailedBolusInfo.carbs));
if (detailedBolusInfo.carbs > 0 && detailedBolusInfo.carbTime > 0) {
// split out a separate carbs record without a pumpId
DetailedBolusInfo carbInfo = new DetailedBolusInfo();
carbInfo.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60L * 1000L;
carbInfo.timestamp = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60L * 1000L;
carbInfo.carbs = detailedBolusInfo.carbs;
carbInfo.source = Source.USER;
carbInfo.setPumpType(InterfaceIDs.PumpType.USER);
activePlugin.getActiveTreatments().addToHistoryTreatment(carbInfo, false);
// remove carbs from bolusInfo to not trigger any unwanted code paths in
@ -1010,4 +1012,8 @@ public class AapsOmnipodErosManager {
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
));
}
public String serialNumber() {
return podStateManager.isPodInitialized() ? String.valueOf(podStateManager.getAddress()) : "-";
}
}