diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt index 011faded5b..15298fb768 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt @@ -66,7 +66,7 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment @ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment - @ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsMealLinkFragment + @ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusCarbsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment @ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt index 8883bb6c72..c0eadc1b56 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt @@ -234,8 +234,14 @@ class CarbsDialog : DialogFragmentWithDate() { lowTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()), highTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()) )).subscribe({ result -> - result.inserted.forEach { nsUpload.uploadTempTarget(it) } - result.updated.forEach { nsUpload.updateTempTarget(it) } + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted tt $it") + nsUpload.uploadTempTarget(it) + } + result.updated.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated tt $it") + nsUpload.updateTempTarget(it) + } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) }) @@ -250,8 +256,14 @@ class CarbsDialog : DialogFragmentWithDate() { lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()), highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()) )).subscribe({ result -> - result.inserted.forEach { nsUpload.uploadTempTarget(it) } - result.updated.forEach { nsUpload.updateTempTarget(it) } + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted tt $it") + nsUpload.uploadTempTarget(it) + } + result.updated.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated tt $it") + nsUpload.updateTempTarget(it) + } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) }) @@ -266,10 +278,16 @@ class CarbsDialog : DialogFragmentWithDate() { lowTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()), highTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()) )).subscribe({ result -> - result.inserted.forEach { nsUpload.uploadTempTarget(it) } - result.updated.forEach { nsUpload.updateTempTarget(it) } + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted tt $it") + nsUpload.uploadTempTarget(it) + } + result.updated.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated tt $it") + nsUpload.updateTempTarget(it) + } }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) + aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) }) } } @@ -280,33 +298,22 @@ class CarbsDialog : DialogFragmentWithDate() { detailedBolusInfo.context = context detailedBolusInfo.notes = notes detailedBolusInfo.carbsDuration = T.mins(duration.toLong()).msecs() - if (duration != 0 || timeOffset != 0) { - detailedBolusInfo.carbsTimestamp = time - disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction()) - .subscribe({ result -> - result.inserted.forEach { - uel.log(Action.CARBS, notes, - ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), - ValueWithUnit(carbsAfterConstraints, Units.G), - ValueWithUnit(timeOffset, Units.M, timeOffset != 0), - ValueWithUnit(duration, Units.H, duration != 0) - ) - nsUpload.uploadMealLinkRecord(it) - } - }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it) - }) - } else { - commandQueue.bolus(detailedBolusInfo, object : Callback() { - override fun run() { - if (!result.success) { - ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror) - } else - uel.log(Action.BOLUS, notes, ValueWithUnit(carbsAfterConstraints, Units.G)) + detailedBolusInfo.carbsTimestamp = time + uel.log(Action.CARBS, detailedBolusInfo.notes, + ValueWithUnit(detailedBolusInfo.timestamp, Units.Timestamp), + ValueWithUnit(detailedBolusInfo.carbs, Units.G), + ValueWithUnit(detailedBolusInfo.carbTime, Units.M, detailedBolusInfo.carbTime != 0), + ValueWithUnit(detailedBolusInfo.carbsDuration, Units.H, detailedBolusInfo.carbsDuration != 0L) + ) + commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (!result.success) { + ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror) + } else + uel.log(Action.BOLUS, notes, ValueWithUnit(carbsAfterConstraints, Units.G)) - } - }) - } + } + }) } if (useAlarm && carbs > 0 && timeOffset > 0) { carbTimer.scheduleReminder(dateUtil._now() + T.mins(timeOffset.toLong()).msecs()) diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt index ac07b5664e..4fe211c3c2 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt @@ -197,8 +197,14 @@ class InsulinDialog : DialogFragmentWithDate() { lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()), highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()) )).subscribe({ result -> - result.inserted.forEach { nsUpload.uploadTempTarget(it) } - result.updated.forEach { nsUpload.updateTempTarget(it) } + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted tt $it") + nsUpload.uploadTempTarget(it) + } + result.updated.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated tt $it") + nsUpload.updateTempTarget(it) + } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) }) @@ -209,19 +215,21 @@ class InsulinDialog : DialogFragmentWithDate() { detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.context = context detailedBolusInfo.notes = notes + detailedBolusInfo.timestamp = time + uel.log(Action.BOLUS_RECORD, notes, + ValueWithUnit(detailedBolusInfo.timestamp, Units.Timestamp), + ValueWithUnit(detailedBolusInfo.insulin, Units.U), + ValueWithUnit(timeOffset, Units.M, timeOffset != 0) + ) if (recordOnlyChecked) { - detailedBolusInfo.bolusTimestamp = time - disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction()) + disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction()) .subscribe({ result -> result.inserted.forEach { - uel.log(Action.BOLUS_RECORD, notes, - ValueWithUnit(it.bolus?.amount ?: 0.0, Units.U), - ValueWithUnit(timeOffset, Units.M, timeOffset != 0) - ) - nsUpload.uploadMealLinkRecord(it) + aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") + nsUpload.uploadBolusRecord(it, detailedBolusInfo.createTherapyEvent(), null) } }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it) + aapsLogger.error(LTag.BGSOURCE, "Error while saving bolus", it) }) } else { commandQueue.bolus(detailedBolusInfo, object : Callback() { diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt index e819e98c30..b7e567a88c 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt @@ -145,31 +145,38 @@ class TreatmentDialog : DialogFragmentWithDate() { detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.carbs = carbsAfterConstraints.toDouble() detailedBolusInfo.context = context - if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) { + uel.log(Action.TREATMENT, + ValueWithUnit(detailedBolusInfo.timestamp, Units.Timestamp), + ValueWithUnit(insulin, Units.U, insulin != 0.0), + ValueWithUnit(carbs, Units.G, carbs != 0) + ) + if (recordOnlyChecked) { + disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction()) + .subscribe({ result -> + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") + nsUpload.uploadBolusRecord(it, detailedBolusInfo.createTherapyEvent(), null) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving bolus", it) + }) + disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction()) + .subscribe({ result -> + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") + nsUpload.uploadCarbsRecord(it, detailedBolusInfo.createTherapyEvent()) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving carbs", it) + }) + } else { commandQueue.bolus(detailedBolusInfo, object : Callback() { override fun run() { if (!result.success) { ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) - } else - uel.log(Action.TREATMENT, - ValueWithUnit(insulin, Units.U, insulin != 0.0), - ValueWithUnit(carbs, Units.G, carbs != 0) - ) + } } }) - } else { - disposable += repository.runTransactionForResult(detailedBolusInfo.insertMealLinkTransaction()) - .subscribe({ result -> - result.inserted.forEach { - uel.log(Action.TREATMENT, - ValueWithUnit(insulin, Units.U, insulin != 0.0), - ValueWithUnit(carbs, Units.G, carbs != 0) - ) - nsUpload.uploadMealLinkRecord(it) - } - }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it) - }) } }) } diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt index 1327b08ab2..2ef57d940d 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt @@ -23,11 +23,9 @@ class WizardInfoDialog : DaggerDialogFragment() { @Inject lateinit var profileFunction: ProfileFunction private lateinit var data: BolusCalculatorResult - private lateinit var notes: String - fun setData(bolusCalculatorResult: BolusCalculatorResult, notes: String) { + fun setData(bolusCalculatorResult: BolusCalculatorResult) { this.data = bolusCalculatorResult - this.notes = notes } private var _binding: DialogWizardinfoBinding? = null @@ -82,7 +80,7 @@ class WizardInfoDialog : DaggerDialogFragment() { // Profile binding.profile.text = data.profileName // Notes - binding.notes.text = notes + binding.notes.text = data.note // Percentage binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, data.percentageCorrection) // Total diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt index 675788fc12..bb9b84edd0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.kt @@ -50,7 +50,7 @@ class TreatmentsFragment : DaggerFragment() { binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility() binding.treatments.setOnClickListener { - setFragment(TreatmentsMealLinkFragment()) + setFragment(TreatmentsBolusCarbsFragment()) setBackgroundColorOnSelected(it) } binding.extendedBoluses.setOnClickListener { @@ -77,7 +77,7 @@ class TreatmentsFragment : DaggerFragment() { setFragment(TreatmentsUserEntryFragment()) setBackgroundColorOnSelected(it) } - setFragment(TreatmentsMealLinkFragment()) + setFragment(TreatmentsBolusCarbsFragment()) setBackgroundColorOnSelected(binding.treatments) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsMealLinkFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt similarity index 52% rename from app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsMealLinkFragment.kt rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt index 84eef1d0b2..0d6ae81abb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsMealLinkFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt @@ -9,16 +9,16 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.Iob import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.Bolus -import info.nightscout.androidaps.database.entities.MealLinkLoaded +import info.nightscout.androidaps.database.entities.BolusCalculatorResult +import info.nightscout.androidaps.database.entities.Carbs import info.nightscout.androidaps.database.entities.UserEntry.* +import info.nightscout.androidaps.database.transactions.InvalidateBolusCalculatorResultTransaction import info.nightscout.androidaps.database.transactions.InvalidateBolusTransaction import info.nightscout.androidaps.database.transactions.InvalidateCarbsTransaction -import info.nightscout.androidaps.database.transactions.InvalidateMealLinkTransaction -import info.nightscout.androidaps.databinding.TreatmentsMealLinkFragmentBinding -import info.nightscout.androidaps.databinding.TreatmentsMealLinkItemBinding +import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsFragmentBinding +import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsItemBinding import info.nightscout.androidaps.dialogs.WizardInfoDialog import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventTreatmentChange @@ -49,7 +49,7 @@ import io.reactivex.rxkotlin.subscribeBy import java.util.concurrent.TimeUnit import javax.inject.Inject -class TreatmentsMealLinkFragment : DaggerFragment() { +class TreatmentsBolusCarbsFragment : DaggerFragment() { @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var sp: SP @@ -66,18 +66,24 @@ class TreatmentsMealLinkFragment : DaggerFragment() { @Inject lateinit var repository: AppRepository @Inject lateinit var activePlugin: ActivePluginProvider + class MealLink( + val bolus: Bolus? = null, + val carbs: Carbs? = null, + val bolusCalculatorResult: BolusCalculatorResult? = null + ) + private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() - private var _binding: TreatmentsMealLinkFragmentBinding? = null + private var _binding: TreatmentsBolusCarbsFragmentBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = - TreatmentsMealLinkFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root + TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -90,7 +96,7 @@ class TreatmentsMealLinkFragment : DaggerFragment() { uel.log(Action.TREATMENTS_NS_REFRESH) disposable += Completable.fromAction { - repository.deleteAllMealLinks() + repository.deleteAllBolusCalculatorResults() repository.deleteAllBoluses() repository.deleteAllCarbs() } @@ -109,29 +115,51 @@ class TreatmentsMealLinkFragment : DaggerFragment() { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.deletefuturetreatments) + "?", Runnable { uel.log(Action.DELETE_FUTURE_TREATMENTS) repository - .getMealLinkLoadedDataFromTime(dateUtil._now(), false) + .getBolusesDataFromTime(dateUtil._now(), false) .observeOn(aapsSchedulers.main) .subscribe { list -> - list.forEach { mealLinkLoaded -> - disposable += repository.runTransactionForResult(InvalidateMealLinkTransaction(mealLinkLoaded.mealLink.id)) + list.forEach { bolus -> + disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id)) .subscribe({ - if (mealLinkLoaded.bolus != null) { - val id = mealLinkLoaded.bolus!!.interfaceIDs.nightscoutId - if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) - else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.bolus!!.timestamp.toString()) - } - if (mealLinkLoaded.carbs != null) { - val id = mealLinkLoaded.carbs!!.interfaceIDs.nightscoutId - if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) - else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.carbs!!.timestamp.toString()) - } + val id = bolus.interfaceIDs.nightscoutId + if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) + else uploadQueue.removeByMongoId("dbAdd", bolus.timestamp.toString()) }, { - aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating MealLink", it) + aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating bolus", it) }) } - binding.deleteFutureTreatments.visibility = View.GONE } - + repository + .getCarbsDataFromTime(dateUtil._now(), false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> + list.forEach { carb -> + disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id)) + .subscribe({ + val id = carb.interfaceIDs.nightscoutId + if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) + else uploadQueue.removeByMongoId("dbAdd", carb.timestamp.toString()) + }, { + aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating carbs", it) + }) + } + } + repository + .getBolusCalculatorResultsDataFromTime(dateUtil._now(), false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> + list.forEach { bolusCalc -> + disposable += repository.runTransactionForResult(InvalidateBolusCalculatorResultTransaction(bolusCalc.id)) + .subscribe({ + val id = bolusCalc.interfaceIDs.nightscoutId + if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) + else uploadQueue.removeByMongoId("dbAdd", bolusCalc.timestamp.toString()) + }, { + aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating carbs", it) + }) + } + } + binding.deleteFutureTreatments.visibility = View.GONE }) } } @@ -142,23 +170,64 @@ class TreatmentsMealLinkFragment : DaggerFragment() { } } + private fun bolusMealLinksWithInvalid(now: Long) = repository + .getBolusesIncludingInvalidFromTime(now - millsToThePast, false) + .map { bolus -> bolus.map { MealLink(bolus = it) } } + + private fun carbsMealLinksWithInvalid(now: Long) = repository + .getCarbsIncludingInvalidFromTime(now - millsToThePast, false) + .map { carb -> carb.map { MealLink(carbs = it) } } + + private fun calcResultMealLinksWithInvalid(now: Long) = repository + .getBolusCalculatorResultsIncludingInvalidFromTime(now - millsToThePast, false) + .map { calc -> calc.map { MealLink(bolusCalculatorResult = it) } } + + private fun bolusMealLinks(now: Long) = repository + .getBolusesDataFromTime(now - millsToThePast, false) + .map { bolus -> bolus.map { MealLink(bolus = it) } } + + private fun carbsMealLinks(now: Long) = repository + .getCarbsDataFromTime(now - millsToThePast, false) + .map { carb -> carb.map { MealLink(carbs = it) } } + + private fun calcResultMealLinks(now: Long) = repository + .getBolusCalculatorResultsDataFromTime(now - millsToThePast, false) + .map { calc -> calc.map { MealLink(bolusCalculatorResult = it) } } + fun swapAdapter() { val now = System.currentTimeMillis() - disposable += - if (binding.showInvalidated.isChecked) - repository - .getMealLinkLoadedDataIncludingInvalidFromTime(now - millsToThePast, false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } - else - repository - .getMealLinkLoadedDataFromTime(now - millsToThePast, false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } - disposable += repository - .getMealLinkLoadedDataFromTime(now, false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() } + + if (binding.showInvalidated.isChecked) + disposable += carbsMealLinksWithInvalid(now) + .zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second } + .zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second } + .map { ml -> + ml.sortedBy { + it.carbs?.timestamp ?: it.bolus?.timestamp + ?: it.bolusCalculatorResult?.timestamp + } + } + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) + binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() + } + else + disposable += carbsMealLinks(now) + .zipWith(bolusMealLinks(now)) { first, second -> first + second } + .zipWith(calcResultMealLinks(now)) { first, second -> first + second } + .map { ml -> + ml.sortedBy { + it.carbs?.timestamp ?: it.bolus?.timestamp + ?: it.bolusCalculatorResult?.timestamp + } + } + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) + binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() + } + } @Synchronized @@ -195,10 +264,10 @@ class TreatmentsMealLinkFragment : DaggerFragment() { _binding = null } - inner class RecyclerViewAdapter internal constructor(var mealLinks: List) : RecyclerView.Adapter() { + inner class RecyclerViewAdapter internal constructor(var mealLinks: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder { - val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_meal_link_item, viewGroup, false) + val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false) return MealLinkLoadedViewHolder(v) } @@ -206,36 +275,40 @@ class TreatmentsMealLinkFragment : DaggerFragment() { val profile = profileFunction.getProfile() ?: return val ml = mealLinks[position] - // MealLink - holder.binding.date.text = dateUtil.dateAndTimeString(ml.mealLink.timestamp) - val iob = ml.bolus?.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia) - ?: Iob() - holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib) - if (iob.iobContrib != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.carbs.currentTextColor) - if (ml.mealLink.timestamp > dateUtil._now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor) - holder.binding.mealOrCorrection.text = - when (ml.bolus?.type) { - Bolus.Type.SMB -> "SMB" - Bolus.Type.NORMAL -> resourceHelper.gs(R.string.mealbolus) - else -> "" - } - holder.binding.calculation.visibility = (ml.bolusCalculatorResult != null).toVisibility() + // Metadata + holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility() + ml.bolusCalculatorResult?.let { bolusCalculatorResult -> + holder.binding.date.text = dateUtil.dateAndTimeString(bolusCalculatorResult.timestamp) + } // Bolus - holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus?.isValid == true || binding.showInvalidated.isChecked)).toVisibility() - holder.binding.bolusDate.text = dateUtil.timeString(ml.bolus?.timestamp ?: 0L) - holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, ml.bolus?.amount ?: 0.0) - holder.binding.bolusNs.visibility = (NSUpload.isIdValid(ml.bolus?.interfaceIDs?.nightscoutId)).toVisibility() - holder.binding.bolusPump.visibility = (ml.bolus?.interfaceIDs?.pumpId != null).toVisibility() - holder.binding.bolusInvalid.visibility = (ml.bolus?.isValid == true).not().toVisibility() - + holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility() + ml.bolus?.let { bolus -> + holder.binding.bolusDate.text = dateUtil.timeString(bolus.timestamp) + holder.binding.insulin.text = resourceHelper.gs(R.string.formatinsulinunits, bolus.amount) + holder.binding.bolusNs.visibility = (NSUpload.isIdValid(bolus.interfaceIDs.nightscoutId)).toVisibility() + holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility() + holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility() + val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia) + holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib) + if (iob.iobContrib != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.carbs.currentTextColor) + if (bolus.timestamp > dateUtil._now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor) + holder.binding.mealOrCorrection.text = + when (ml.bolus.type) { + Bolus.Type.SMB -> "SMB" + Bolus.Type.NORMAL -> resourceHelper.gs(R.string.mealbolus) + else -> "" + } + } // Carbs - holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs?.isValid == true || binding.showInvalidated.isChecked)).toVisibility() - holder.binding.carbsDate.text = dateUtil.timeString(ml.carbs?.timestamp ?: 0L) - holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, ml.carbs?.amount?.toInt() ?: 0) - holder.binding.carbsNs.visibility = (NSUpload.isIdValid(ml.carbs?.interfaceIDs?.nightscoutId)).toVisibility() - holder.binding.carbsPump.visibility = (ml.carbs?.interfaceIDs?.pumpId != null).toVisibility() - holder.binding.carbsInvalid.visibility = (ml.carbs?.isValid == true).not().toVisibility() + holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility() + ml.carbs?.let { carbs -> + holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp) + holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, carbs.amount.toInt()) + holder.binding.carbsNs.visibility = (NSUpload.isIdValid(carbs.interfaceIDs.nightscoutId)).toVisibility() + holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility() + holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility() + } holder.binding.bolusRemove.visibility = (ml.bolus?.isValid == true).toVisibility() holder.binding.carbsRemove.visibility = (ml.carbs?.isValid == true).toVisibility() @@ -250,38 +323,37 @@ class TreatmentsMealLinkFragment : DaggerFragment() { inner class MealLinkLoadedViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) { - val binding = TreatmentsMealLinkItemBinding.bind(view) + val binding = TreatmentsBolusCarbsItemBinding.bind(view) init { binding.calculation.setOnClickListener { - val mealLinkLoaded = it.tag as MealLinkLoaded + val mealLinkLoaded = it.tag as MealLink mealLinkLoaded.bolusCalculatorResult?.let { bolusCalculatorResult -> WizardInfoDialog().also { wizardDialog -> - wizardDialog.setData(bolusCalculatorResult, mealLinkLoaded.therapyEvent?.note ?: "") + wizardDialog.setData(bolusCalculatorResult) wizardDialog.show(childFragmentManager, "WizardInfoDialog") } } } binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.bolusRemove.setOnClickListener { - val mealLinkLoaded = it.tag as MealLinkLoaded? ?: return@setOnClickListener + binding.bolusRemove.setOnClickListener { ml -> + val bolus = (ml.tag as MealLink?)?.bolus ?: return@setOnClickListener activity?.let { activity -> val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " + - resourceHelper.gs(R.string.formatinsulinunits, mealLinkLoaded.bolus!!.amount) + "\n" + - // resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, mealLinkLoaded.carbs.toInt()) + "\n" + - resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(mealLinkLoaded.bolus!!.timestamp) + resourceHelper.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + + resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp) OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable { uel.log( Action.TREATMENT_REMOVED, - ValueWithUnit(mealLinkLoaded.bolus!!.timestamp, Units.Timestamp), - ValueWithUnit(mealLinkLoaded.bolus!!.amount, Units.U) + ValueWithUnit(bolus.timestamp, Units.Timestamp), + ValueWithUnit(bolus.amount, Units.U) // ValueWithUnit(mealLinkLoaded.carbs.toInt(), Units.G) ) - disposable += repository.runTransactionForResult(InvalidateBolusTransaction(mealLinkLoaded.bolus!!.id)) + disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id)) .subscribe({ - val id = mealLinkLoaded.bolus!!.interfaceIDs.nightscoutId + val id = bolus.interfaceIDs.nightscoutId if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) - else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.bolus!!.timestamp.toString()) + else uploadQueue.removeByMongoId("dbAdd", bolus.timestamp.toString()) }, { aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating bolus", it) }) @@ -289,25 +361,23 @@ class TreatmentsMealLinkFragment : DaggerFragment() { } } binding.bolusRemove.paintFlags = binding.bolusRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.carbsRemove.setOnClickListener { - val mealLinkLoaded = it.tag as MealLinkLoaded? ?: return@setOnClickListener + binding.carbsRemove.setOnClickListener { ml -> + val carb = (ml.tag as MealLink?)?.carbs ?: return@setOnClickListener activity?.let { activity -> - val text = resourceHelper.gs(R.string.configbuilder_insulin) + ": " + - resourceHelper.gs(R.string.formatinsulinunits, mealLinkLoaded.bolus!!.amount) + "\n" + - // resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, mealLinkLoaded.carbs.toInt()) + "\n" + - resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(mealLinkLoaded.bolus!!.timestamp) + val text = resourceHelper.gs(R.string.carbs) + ": " + + resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, carb.amount.toInt()) + "\n" + + resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carb.timestamp) OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable { uel.log( Action.TREATMENT_REMOVED, - ValueWithUnit(mealLinkLoaded.bolus!!.timestamp, Units.Timestamp), - ValueWithUnit(mealLinkLoaded.bolus!!.amount, Units.U) - // ValueWithUnit(mealLinkLoaded.carbs.toInt(), Units.G) + ValueWithUnit(carb.timestamp, Units.Timestamp), + ValueWithUnit(carb.amount, Units.G) ) - disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(mealLinkLoaded.carbs!!.id)) + disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id)) .subscribe({ - val id = mealLinkLoaded.carbs!!.interfaceIDs.nightscoutId + val id = carb.interfaceIDs.nightscoutId if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) - else uploadQueue.removeByMongoId("dbAdd", mealLinkLoaded.carbs!!.timestamp.toString()) + else uploadQueue.removeByMongoId("dbAdd", carb.timestamp.toString()) }, { aapsLogger.error(LTag.DATATREATMENTS, "Error while invalidating carbs", it) }) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.kt b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.kt index c5d11f3627..e70b15a458 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.kt @@ -13,6 +13,8 @@ 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.AppRepository +import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.dialogs.BolusProgressDialog import info.nightscout.androidaps.events.EventBolusRequested import info.nightscout.androidaps.events.EventNewBasalProfile @@ -23,14 +25,17 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.queue.commands.* import info.nightscout.androidaps.queue.commands.Command.CommandType +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper @@ -38,51 +43,11 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import java.util.* import javax.inject.Inject import javax.inject.Singleton -/** - * Created by mike on 08.11.2017. - * - * - * DATA FLOW: - * --------- - * - * - * (request) - > ConfigBuilder.getCommandQueue().bolus(...) - * - * - * app no longer waits for result but passes Callback - * - * - * request is added to queue, if another request of the same type already exists in queue, it's removed prior adding - * but if request of the same type is currently executed (probably important only for bolus which is running long time), new request is declined - * new QueueThread is created and started if current if finished - * CommandReadStatus is added automatically before command if queue is empty - * - * - * biggest change is we don't need exec pump commands in Handler because it's finished immediately - * command queueing if not realized by stacking in different Handlers and threads anymore but by internal queue with better control - * - * - * QueueThread calls ConfigBuilder#connect which is passed to getActivePump().connect - * connect should be executed on background and return immediately. afterwards isConnecting() is expected to be true - * - * - * while isConnecting() == true GUI is updated by posting connection progress - * - * - * if connect is successful: isConnected() becomes true, isConnecting() becomes false - * CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish). - * callback with result is called after finish automatically - * if connect failed: isConnected() becomes false, isConnecting() becomes false - * connect() is called again - * - * - * when queue is empty, disconnect is called - */ - @Singleton open class CommandQueue @Inject constructor( private val injector: HasAndroidInjector, @@ -96,7 +61,10 @@ open class CommandQueue @Inject constructor( private val context: Context, private val sp: SP, private val buildHelper: BuildHelper, - private val fabricPrivacy: FabricPrivacy + private val dateUtil: DateUtil, + private val repository: AppRepository, + private val fabricPrivacy: FabricPrivacy, + private val nsUpload: NSUpload ) : CommandQueueProvider { private val disposable = CompositeDisposable() @@ -209,7 +177,7 @@ open class CommandQueue @Inject constructor( override fun independentConnect(reason: String, callback: Callback?) { aapsLogger.debug(LTag.PUMPQUEUE, "Starting new queue") - val tempCommandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp, buildHelper, fabricPrivacy) + val tempCommandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp, buildHelper, dateUtil, repository, fabricPrivacy, nsUpload) tempCommandQueue.readStatus(reason, callback) } @@ -229,6 +197,28 @@ open class CommandQueue @Inject constructor( // returns true if command is queued @Synchronized override fun bolus(detailedBolusInfo: DetailedBolusInfo, callback: Callback?): Boolean { + // Check if pump store carbs + // If not, it's not necessary add command to the queue and initiate connection + // Assuming carbs in the future and carbs with duration are NOT stores anyway + if (detailedBolusInfo.carbs > 0) + if (!activePlugin.get().activePump.pumpDescription.storesCarbInfo + || detailedBolusInfo.carbsDuration != 0L + || detailedBolusInfo.carbsTimestamp ?: detailedBolusInfo.timestamp > dateUtil._now() + ) { + disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction()) + .subscribe({ result -> + result.inserted.forEach { + aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") + nsUpload.uploadCarbsRecord(it, detailedBolusInfo.createTherapyEvent()) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving carbs", it) + }) + // Do not process carbs anymore + detailedBolusInfo.carbs = 0.0 + // if no insulin just exit + if (detailedBolusInfo.insulin == 0.0) return true + } var type = if (detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) CommandType.SMB_BOLUS else CommandType.BOLUS if (type == CommandType.SMB_BOLUS) { if (isRunning(CommandType.BOLUS) || isRunning(CommandType.SMB_BOLUS) || bolusInQueue()) { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt index 079386be10..db404d9235 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt @@ -13,8 +13,8 @@ import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.BolusCalculatorResult import info.nightscout.androidaps.database.entities.TemporaryTarget -import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.UserEntry.* +import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger @@ -277,7 +277,8 @@ class BolusWizard @Inject constructor( wasTempTargetUsed = useTT, totalInsulin = calculatedTotalInsulin, percentageCorrection = percentageCorrection, - profileName = profileName + profileName = profileName, + note = notes ) private fun confirmMessageAfterConstraints(advisor: Boolean): Spanned { @@ -408,36 +409,31 @@ class BolusWizard @Inject constructor( carbTime = this@BolusWizard.carbTime bolusCalculatorResult = createBolusCalculatorResult() notes = this@BolusWizard.notes - if (insulin > 0 || pump.pumpDescription.storesCarbInfo) { + uel.log(Action.BOLUS, notes, + ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent), + ValueWithUnit(insulinAfterConstraints, Units.U), + ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0), + ValueWithUnit(carbTime, Units.M, carbTime != 0) + ) + if (insulin > 0 || carbs > 0) { commandQueue.bolus(this, object : Callback() { override fun run() { if (!result.success) { ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror) - } else - uel.log(Action.BOLUS, notes, - ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent), - ValueWithUnit(insulinAfterConstraints, Units.U), - ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0), - ValueWithUnit(carbTime, Units.M, carbTime != 0) - ) + } } }) - } else { - disposable += repository.runTransactionForResult(insertMealLinkTransaction()) - .subscribe({ result -> - result.inserted.forEach { inserted -> - uel.log(Action.BOLUS, notes, - ValueWithUnit(eventType.toDBbEventType(), Units.TherapyEvent), - ValueWithUnit(insulinAfterConstraints, Units.U), - ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0), - ValueWithUnit(carbTime, Units.M, carbTime != 0) - ) - nsUpload.uploadMealLinkRecord(inserted) - } - }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it) - }) } + disposable += repository.runTransactionForResult(InsertOrUpdateBolusCalculatorResultTransaction(bolusCalculatorResult!!)) + .subscribe({ result -> + result.inserted.forEach { inserted -> + aapsLogger.debug(LTag.DATABASE, "Inserted bolusCalculatorResult $inserted") + nsUpload.uploadBolusCalc(this) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving meal link", it) + }) + } if (useAlarm && carbs > 0 && carbTime > 0) { carbTimer.scheduleReminder(dateUtil._now() + T.mins(carbTime.toLong()).msecs()) diff --git a/app/src/main/res/layout/treatments_meal_link_fragment.xml b/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml similarity index 99% rename from app/src/main/res/layout/treatments_meal_link_fragment.xml rename to app/src/main/res/layout/treatments_bolus_carbs_fragment.xml index 18db21e378..83b2d9284c 100644 --- a/app/src/main/res/layout/treatments_meal_link_fragment.xml +++ b/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - tools:context=".plugins.treatments.fragments.TreatmentsBolusFragment"> + tools:context=".plugins.treatments.fragments.TreatmentsBolusCarbsFragment"> - - - - - - - + + + + + + 0) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", therapyEvent.getType().getText()); - data.put("insulin", bolus.getAmount()); - data.put("created_at", DateUtil.toISOString(bolus.getTimestamp())); - data.put("date", bolus.getTimestamp()); - data.put("isSMB", bolus.getType() == Bolus.Type.SMB); - if (bolus.getInterfaceIDs().getPumpId() != null) - data.put("pumpId", bolus.getInterfaceIDs().getPumpId()); - if (therapyEvent.getGlucose() != null) - data.put("glucose", therapyEvent.getGlucose()); - if (therapyEvent.getGlucoseType() != null) - data.put("glucoseType", therapyEvent.getGlucoseType().getText()); - if (mealLinkLoaded.getBolusCalculatorResult() != null) - data.put("bolusCalc", new Gson().toJson(mealLinkLoaded.getBolusCalculatorResult())); - if (therapyEvent.getNote() != null) - data.put("notes", therapyEvent.getNote()); - uploadCareportalEntryToNS(data, bolus.getTimestamp()); - } catch (JSONException e) { - e.printStackTrace(); - } + public void uploadCarbsRecord(@NonNull Carbs carbs, @NonNull TherapyEvent therapyEvent) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", therapyEvent.getType().getText()); + data.put("carbs", carbs.getAmount()); + data.put("created_at", DateUtil.toISOString(carbs.getTimestamp())); + data.put("date", carbs.getTimestamp()); + if (carbs.getDuration() != 0) + data.put("duration", carbs.getDuration()); + if (carbs.getInterfaceIDs().getPumpId() != null) + data.put("pumpId", carbs.getInterfaceIDs().getPumpId()); + if (therapyEvent.getGlucose() != null) + data.put("glucose", therapyEvent.getGlucose()); + if (therapyEvent.getGlucoseType() != null) + data.put("glucoseType", therapyEvent.getGlucoseType().getText()); + if (therapyEvent.getNote() != null) + data.put("notes", therapyEvent.getNote()); + uploadCareportalEntryToNS(data, carbs.getTimestamp()); + } catch (JSONException e) { + e.printStackTrace(); } - if (carbs != null && therapyEvent != null && carbs.getAmount() > 0) { - try { - JSONObject data = new JSONObject(); - data.put("eventType", therapyEvent.getType().getText()); - data.put("carbs", carbs.getAmount()); - data.put("created_at", DateUtil.toISOString(carbs.getTimestamp())); - data.put("date", carbs.getTimestamp()); - if (carbs.getDuration() != 0) - data.put("duration", carbs.getDuration()); - if (carbs.getInterfaceIDs().getPumpId() != null) - data.put("pumpId", carbs.getInterfaceIDs().getPumpId()); - if (therapyEvent.getGlucose() != null) - data.put("glucose", therapyEvent.getGlucose()); - if (therapyEvent.getGlucoseType() != null) - data.put("glucoseType", therapyEvent.getGlucoseType().getText()); - if (therapyEvent.getNote() != null) - data.put("notes", therapyEvent.getNote()); - uploadCareportalEntryToNS(data, carbs.getTimestamp()); - } catch (JSONException e) { - e.printStackTrace(); + } + + public void uploadBolusRecord(@NonNull Bolus bolus, @NonNull TherapyEvent therapyEvent, @Nullable BolusCalculatorResult bolusCalculatorResult) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", therapyEvent.getType().getText()); + data.put("insulin", bolus.getAmount()); + data.put("created_at", DateUtil.toISOString(bolus.getTimestamp())); + data.put("date", bolus.getTimestamp()); + data.put("isSMB", bolus.getType() == Bolus.Type.SMB); + if (bolus.getInterfaceIDs().getPumpId() != null) + data.put("pumpId", bolus.getInterfaceIDs().getPumpId()); + if (therapyEvent.getGlucose() != null) + data.put("glucose", therapyEvent.getGlucose()); + if (therapyEvent.getGlucoseType() != null) + data.put("glucoseType", therapyEvent.getGlucoseType().getText()); + if (bolusCalculatorResult != null) + data.put("bolusCalculatorResult", new Gson().toJson(bolusCalculatorResult)); + if (therapyEvent.getNote() != null) + data.put("notes", therapyEvent.getNote()); + uploadCareportalEntryToNS(data, bolus.getTimestamp()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void uploadBolusCalc(@NonNull DetailedBolusInfo detailedBolusInfo) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", detailedBolusInfo.getEventType().toDBbEventType().getText()); + data.put("created_at", DateUtil.toISOString(detailedBolusInfo.timestamp)); + data.put("date", detailedBolusInfo.timestamp); + if (detailedBolusInfo.getMgdlGlucose() != null) { + data.put("glucose", detailedBolusInfo.getMgdlGlucose()); + data.put("units", Constants.MGDL); } + if (detailedBolusInfo.getGlucoseType() != null) + data.put("glucoseType", detailedBolusInfo.getGlucoseType().getText()); + if (detailedBolusInfo.getBolusCalculatorResult() != null) + data.put("bolusCalculatorResult", new Gson().toJson(detailedBolusInfo.getBolusCalculatorResult())); + if (detailedBolusInfo.getNotes() != null) + data.put("notes", detailedBolusInfo.getNotes()); + uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp); + } catch (JSONException e) { + e.printStackTrace(); } } diff --git a/database/schemas/info.nightscout.androidaps.database.AppDatabase/8.json b/database/schemas/info.nightscout.androidaps.database.AppDatabase/8.json index 581dafb92f..3d0a4f7f7d 100644 --- a/database/schemas/info.nightscout.androidaps.database.AppDatabase/8.json +++ b/database/schemas/info.nightscout.androidaps.database.AppDatabase/8.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 8, - "identityHash": "c38f6acf42463481d39fe05be1fd3b55", + "identityHash": "2e4a472793f7dd21528ddcb540500f1b", "entities": [ { "tableName": "apsResults", @@ -350,7 +350,7 @@ }, { "tableName": "bolusCalculatorResults", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `targetBGLow` REAL NOT NULL, `targetBGHigh` REAL NOT NULL, `isf` REAL NOT NULL, `ic` REAL NOT NULL, `bolusIOB` REAL NOT NULL, `wasBolusIOBUsed` INTEGER NOT NULL, `basalIOB` REAL NOT NULL, `wasBasalIOBUsed` INTEGER NOT NULL, `glucoseValue` REAL NOT NULL, `wasGlucoseUsed` INTEGER NOT NULL, `glucoseDifference` REAL NOT NULL, `glucoseInsulin` REAL NOT NULL, `glucoseTrend` REAL NOT NULL, `wasTrendUsed` INTEGER NOT NULL, `trendInsulin` REAL NOT NULL, `cob` REAL NOT NULL, `wasCOBUsed` INTEGER NOT NULL, `cobInsulin` REAL NOT NULL, `carbs` REAL NOT NULL, `wereCarbsUsed` INTEGER NOT NULL, `carbsInsulin` REAL NOT NULL, `otherCorrection` REAL NOT NULL, `wasSuperbolusUsed` INTEGER NOT NULL, `superbolusInsulin` REAL NOT NULL, `wasTempTargetUsed` INTEGER NOT NULL, `totalInsulin` REAL NOT NULL, `percentageCorrection` INTEGER NOT NULL, `profileName` TEXT NOT NULL, `note` TEXT NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`referenceId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", "fields": [ { "fieldPath": "id", @@ -562,6 +562,12 @@ "affinity": "TEXT", "notNull": true }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": true + }, { "fieldPath": "interfaceIDs_backing.nightscoutSystemId", "columnName": "nightscoutSystemId", @@ -2220,250 +2226,6 @@ } ] }, - { - "tableName": "mealLinks", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `timestamp` INTEGER NOT NULL, `utcOffset` INTEGER NOT NULL, `bolusId` INTEGER, `carbsId` INTEGER, `bolusCalcResultId` INTEGER, `superbolusTempBasalId` INTEGER, `noteId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`carbsId`) REFERENCES `carbs`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`bolusCalcResultId`) REFERENCES `bolusCalculatorResults`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`superbolusTempBasalId`) REFERENCES `temporaryBasals`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`noteId`) REFERENCES `therapyEvents`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `mealLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "version", - "columnName": "version", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "dateCreated", - "columnName": "dateCreated", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isValid", - "columnName": "isValid", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "referenceId", - "columnName": "referenceId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "timestamp", - "columnName": "timestamp", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "utcOffset", - "columnName": "utcOffset", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "bolusId", - "columnName": "bolusId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "carbsId", - "columnName": "carbsId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "bolusCalcResultId", - "columnName": "bolusCalcResultId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "superbolusTempBasalId", - "columnName": "superbolusTempBasalId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "noteId", - "columnName": "noteId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.nightscoutSystemId", - "columnName": "nightscoutSystemId", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.nightscoutId", - "columnName": "nightscoutId", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.pumpType", - "columnName": "pumpType", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.pumpSerial", - "columnName": "pumpSerial", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.pumpId", - "columnName": "pumpId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.startId", - "columnName": "startId", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "interfaceIDs_backing.endId", - "columnName": "endId", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_mealLinks_referenceId", - "unique": false, - "columnNames": [ - "referenceId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_referenceId` ON `${TABLE_NAME}` (`referenceId`)" - }, - { - "name": "index_mealLinks_bolusId", - "unique": false, - "columnNames": [ - "bolusId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_bolusId` ON `${TABLE_NAME}` (`bolusId`)" - }, - { - "name": "index_mealLinks_carbsId", - "unique": false, - "columnNames": [ - "carbsId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_carbsId` ON `${TABLE_NAME}` (`carbsId`)" - }, - { - "name": "index_mealLinks_bolusCalcResultId", - "unique": false, - "columnNames": [ - "bolusCalcResultId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_bolusCalcResultId` ON `${TABLE_NAME}` (`bolusCalcResultId`)" - }, - { - "name": "index_mealLinks_superbolusTempBasalId", - "unique": false, - "columnNames": [ - "superbolusTempBasalId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_superbolusTempBasalId` ON `${TABLE_NAME}` (`superbolusTempBasalId`)" - }, - { - "name": "index_mealLinks_noteId", - "unique": false, - "columnNames": [ - "noteId" - ], - "createSql": "CREATE INDEX IF NOT EXISTS `index_mealLinks_noteId` ON `${TABLE_NAME}` (`noteId`)" - } - ], - "foreignKeys": [ - { - "table": "boluses", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "bolusId" - ], - "referencedColumns": [ - "id" - ] - }, - { - "table": "carbs", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "carbsId" - ], - "referencedColumns": [ - "id" - ] - }, - { - "table": "bolusCalculatorResults", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "bolusCalcResultId" - ], - "referencedColumns": [ - "id" - ] - }, - { - "table": "temporaryBasals", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "superbolusTempBasalId" - ], - "referencedColumns": [ - "id" - ] - }, - { - "table": "therapyEvents", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "noteId" - ], - "referencedColumns": [ - "id" - ] - }, - { - "table": "mealLinks", - "onDelete": "NO ACTION", - "onUpdate": "NO ACTION", - "columns": [ - "referenceId" - ], - "referencedColumns": [ - "id" - ] - } - ] - }, { "tableName": "multiwaveBolusLinks", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `bolusId` INTEGER NOT NULL, `extendedBolusId` INTEGER NOT NULL, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER, FOREIGN KEY(`bolusId`) REFERENCES `boluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`extendedBolusId`) REFERENCES `extendedBoluses`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`referenceId`) REFERENCES `multiwaveBolusLinks`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", @@ -2942,7 +2704,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c38f6acf42463481d39fe05be1fd3b55')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2e4a472793f7dd21528ddcb540500f1b')" ] } } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt b/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt index ddbf9f1d63..aa1bb34071 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppDatabase.kt @@ -12,7 +12,7 @@ const val DATABASE_VERSION = 8 entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class, EffectiveProfileSwitch::class, ExtendedBolus::class, GlucoseValue::class, ProfileSwitch::class, TemporaryBasal::class, TemporaryTarget::class, TherapyEvent::class, TotalDailyDose::class, APSResultLink::class, - MealLink::class, MultiwaveBolusLink::class, PreferenceChange::class, VersionChange::class, UserEntry::class, + MultiwaveBolusLink::class, PreferenceChange::class, VersionChange::class, UserEntry::class, Food::class], exportSchema = true) @TypeConverters(Converters::class) @@ -34,8 +34,6 @@ internal abstract class AppDatabase : RoomDatabase() { abstract val carbsDao: CarbsDao - abstract val mealLinkDao: MealLinkDao - abstract val temporaryTargetDao: TemporaryTargetDao abstract val apsResultLinkDao: APSResultLinkDao diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt index 20d0a8022f..0b16c6733d 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -175,28 +175,48 @@ open class AppRepository @Inject internal constructor( fun deleteAllFoods() = database.foodDao.deleteAllEntries() - // MEAL LINK - fun getMealLinkLoadedDataFromTime(timestamp: Long, ascending: Boolean): Single> = - database.mealLinkDao.getMealLinkLoadedFromTime(timestamp) + // BOLUS + fun getBolusesDataFromTime(timestamp: Long, ascending: Boolean): Single> = + database.bolusDao.getBolusesFromTime(timestamp) .map { if (!ascending) it.reversed() else it } .subscribeOn(Schedulers.io()) - fun getMealLinkLoadedDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = - database.mealLinkDao.getMealLinkLoadedIncludingInvalidFromTime(timestamp) + fun getBolusesIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = + database.bolusDao.getBolusesIncludingInvalidFromTime(timestamp) .map { if (!ascending) it.reversed() else it } .subscribeOn(Schedulers.io()) fun deleteAllBoluses() = database.bolusDao.deleteAllEntries() + // CARBS + fun getCarbsDataFromTime(timestamp: Long, ascending: Boolean): Single> = + database.carbsDao.getCarbsFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getCarbsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = + database.carbsDao.getCarbsIncludingInvalidFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + fun deleteAllCarbs() = database.carbsDao.deleteAllEntries() + // CARBS + fun getBolusCalculatorResultsDataFromTime(timestamp: Long, ascending: Boolean): Single> = + database.bolusCalculatorResultDao.getBolusCalculatorResultsFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + + fun getBolusCalculatorResultsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single> = + database.bolusCalculatorResultDao.getBolusCalculatorResultsIncludingInvalidFromTime(timestamp) + .map { if (!ascending) it.reversed() else it } + .subscribeOn(Schedulers.io()) + fun deleteAllBolusCalculatorResults() = database.bolusCalculatorResultDao.deleteAllEntries() - fun deleteAllMealLinks() = - database.mealLinkDao.deleteAllEntries() } @Suppress("USELESS_CAST") diff --git a/database/src/main/java/info/nightscout/androidaps/database/DelegatedAppDatabase.kt b/database/src/main/java/info/nightscout/androidaps/database/DelegatedAppDatabase.kt index f9058a1d51..9f29abfcd6 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/DelegatedAppDatabase.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/DelegatedAppDatabase.kt @@ -14,7 +14,6 @@ internal class DelegatedAppDatabase(val changes: MutableList, val datab val multiwaveBolusLinkDao: MultiwaveBolusLinkDao = DelegatedMultiwaveBolusLinkDao(changes, database.multiwaveBolusLinkDao) val totalDailyDoseDao: TotalDailyDoseDao = DelegatedTotalDailyDoseDao(changes, database.totalDailyDoseDao) val carbsDao: CarbsDao = DelegatedCarbsDao(changes, database.carbsDao) - val mealLinkDao: MealLinkDao = DelegatedMealLinkDao(changes, database.mealLinkDao) val temporaryTargetDao: TemporaryTargetDao = DelegatedTemporaryTargetDao(changes, database.temporaryTargetDao) val apsResultLinkDao: APSResultLinkDao = DelegatedAPSResultLinkLinkDao(changes, database.apsResultLinkDao) val bolusCalculatorResultDao: BolusCalculatorResultDao = DelegatedBolusCalculatorResultDao(changes, database.bolusCalculatorResultDao) diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt index a4602a7d73..ffa7f7ec1c 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt @@ -14,5 +14,12 @@ internal interface BolusCalculatorResultDao : TraceableDao= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getBolusCalculatorResultsFromTime(timestamp: Long): Single> + + @Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getBolusCalculatorResultsIncludingInvalidFromTime(timestamp: Long): Single> } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt index 18e0ae0121..967b36c7a2 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt @@ -3,7 +3,6 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query import info.nightscout.androidaps.database.TABLE_BOLUSES -import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.entities.Bolus import io.reactivex.Single @@ -16,4 +15,10 @@ internal interface BolusDao : TraceableDao { @Query("DELETE FROM $TABLE_BOLUSES") override fun deleteAllEntries() + + @Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getBolusesFromTime(timestamp: Long): Single> + + @Query("SELECT * FROM $TABLE_BOLUSES WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getBolusesIncludingInvalidFromTime(timestamp: Long): Single> } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt index 09d24908d0..af4f086b66 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt @@ -15,4 +15,10 @@ internal interface CarbsDao : TraceableDao { @Query("DELETE FROM $TABLE_CARBS") override fun deleteAllEntries() + + @Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getCarbsFromTime(timestamp: Long): Single> + + @Query("SELECT * FROM $TABLE_CARBS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") + fun getCarbsIncludingInvalidFromTime(timestamp: Long): Single> } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/MealLinkDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/MealLinkDao.kt deleted file mode 100644 index ef50a0f10a..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/MealLinkDao.kt +++ /dev/null @@ -1,28 +0,0 @@ -package info.nightscout.androidaps.database.daos - -import androidx.room.Dao -import androidx.room.Query -import androidx.room.Transaction -import info.nightscout.androidaps.database.TABLE_MEAL_LINKS -import info.nightscout.androidaps.database.entities.MealLink -import info.nightscout.androidaps.database.entities.MealLinkLoaded -import io.reactivex.Single - -@Suppress("FunctionName") -@Dao -internal interface MealLinkDao : TraceableDao { - - @Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE id = :id") - override fun findById(id: Long): MealLink? - - @Query("DELETE FROM $TABLE_MEAL_LINKS") - override fun deleteAllEntries() - - @Transaction - @Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE isValid = 1 AND timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") - fun getMealLinkLoadedFromTime(timestamp: Long): Single> - - @Transaction - @Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC") - fun getMealLinkLoadedIncludingInvalidFromTime(timestamp: Long): Single> -} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt index d7865779b7..df275b1837 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt @@ -2,10 +2,8 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_MEAL_LINKS import info.nightscout.androidaps.database.TABLE_MULTIWAVE_BOLUS_LINKS import info.nightscout.androidaps.database.entities.MultiwaveBolusLink -import io.reactivex.Single @Suppress("FunctionName") @Dao @@ -14,6 +12,6 @@ internal interface MultiwaveBolusLinkDao : TraceableDao { @Query("SELECT * FROM $TABLE_MULTIWAVE_BOLUS_LINKS WHERE id = :id") override fun findById(id: Long): MultiwaveBolusLink? - @Query("DELETE FROM $TABLE_MEAL_LINKS") + @Query("DELETE FROM $TABLE_MULTIWAVE_BOLUS_LINKS") override fun deleteAllEntries() } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/delegated/DelegatedMealLinkDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/delegated/DelegatedMealLinkDao.kt deleted file mode 100644 index a568dd5aed..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/delegated/DelegatedMealLinkDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package info.nightscout.androidaps.database.daos.delegated - -import info.nightscout.androidaps.database.daos.MealLinkDao -import info.nightscout.androidaps.database.entities.MealLink -import info.nightscout.androidaps.database.interfaces.DBEntry - -internal class DelegatedMealLinkDao(changes: MutableList, private val dao: MealLinkDao) : DelegatedDao(changes), MealLinkDao by dao { - - override fun insertNewEntry(entry: MealLink): Long { - changes.add(entry) - return dao.insertNewEntry(entry) - } - - override fun updateExistingEntry(entry: MealLink): Long { - changes.add(entry) - return dao.updateExistingEntry(entry) - } -} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/BolusCalculatorResult.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/BolusCalculatorResult.kt index ebc02089d4..e88699f9ea 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/BolusCalculatorResult.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/BolusCalculatorResult.kt @@ -51,5 +51,6 @@ data class BolusCalculatorResult( var wasTempTargetUsed: Boolean, var totalInsulin: Double, var percentageCorrection: Int, - var profileName: String + var profileName: String, + var note: String ) : TraceableDBEntry, DBEntryWithTime \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/MealLink.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/MealLink.kt deleted file mode 100644 index 45d8ab75f4..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/MealLink.kt +++ /dev/null @@ -1,61 +0,0 @@ -package info.nightscout.androidaps.database.entities - -import androidx.room.* -import info.nightscout.androidaps.database.TABLE_MEAL_LINKS -import info.nightscout.androidaps.database.embedments.InterfaceIDs -import info.nightscout.androidaps.database.interfaces.DBEntryWithTime -import info.nightscout.androidaps.database.interfaces.TraceableDBEntry -import java.util.* - -@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")]) -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, - override var timestamp: Long, - override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(), - @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, DBEntryWithTime { - - override val foreignKeysValid: Boolean - get() = super.foreignKeysValid && bolusId != 0L && carbsId != 0L && - bolusCalcResultId != 0L && superbolusTempBasalId != 0L && noteId != 0L -} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/MealLinkLoaded.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/MealLinkLoaded.kt deleted file mode 100644 index 82e46d79f2..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/MealLinkLoaded.kt +++ /dev/null @@ -1,33 +0,0 @@ -package info.nightscout.androidaps.database.entities - -import androidx.room.Embedded -import androidx.room.Relation - -data class MealLinkLoaded constructor( - @Embedded val mealLink: MealLink, - @Relation( - entity = Bolus::class, - parentColumn = "bolusId", - entityColumn = "id") - val bolus: Bolus?, - @Relation( - entity = Carbs::class, - parentColumn = "carbsId", - entityColumn = "id") - val carbs: Carbs?, - @Relation( - entity = BolusCalculatorResult::class, - parentColumn = "bolusCalcResultId", - entityColumn = "id") - val bolusCalculatorResult: BolusCalculatorResult?, - @Relation( - entity = TemporaryBasal::class, - parentColumn = "superbolusTempBasalId", - entityColumn = "id") - val superBolusTemporaryBasal: TemporaryBasal?, - @Relation( - entity = TherapyEvent::class, - parentColumn = "noteId", - entityColumn = "id") - val therapyEvent: TherapyEvent? -) \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertMealLinkTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertMealLinkTransaction.kt deleted file mode 100644 index f145081dd0..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertMealLinkTransaction.kt +++ /dev/null @@ -1,45 +0,0 @@ -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() { - - 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( - timestamp = System.currentTimeMillis(), - bolusId = bolusId, - carbsId = carbsId, - bolusCalcResultId = bolusCalculatorResultId, - superbolusTempBasalId = temporaryBasalId, - noteId = therapyEventId - ) - - database.mealLinkDao.insert(mealLink) - val full = MealLinkLoaded(mealLink, bolus, carbs, bolusCalculatorResult, superBolusTemporaryBasal, therapyEvent) - result.inserted.add(full) - - return result - } - - class TransactionResult { - - val inserted = mutableListOf() - } -} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusCalculatorResultTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusCalculatorResultTransaction.kt new file mode 100644 index 0000000000..dfef194370 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusCalculatorResultTransaction.kt @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.BolusCalculatorResult + +/** + * Creates or updates the BolusCalculatorResult + */ +class InsertOrUpdateBolusCalculatorResultTransaction( + private val bolusCalculatorResult: BolusCalculatorResult +) : Transaction() { + + override fun run(): TransactionResult { + val result = TransactionResult() + val current = database.bolusCalculatorResultDao.findById(bolusCalculatorResult.id) + if (current == null) { + database.bolusCalculatorResultDao.insertNewEntry(bolusCalculatorResult) + result.inserted.add(bolusCalculatorResult) + } else { + database.bolusCalculatorResultDao.updateExistingEntry(bolusCalculatorResult) + result.updated.add(bolusCalculatorResult) + } + return result + } + + class TransactionResult { + + val inserted = mutableListOf() + val updated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusTransaction.kt new file mode 100644 index 0000000000..d7df6bedb3 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateBolusTransaction.kt @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.embedments.InsulinConfiguration +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.Bolus + +/** + * Creates or updates the Bolus + */ +class InsertOrUpdateBolusTransaction( + private val bolus: Bolus +) : Transaction() { + + constructor( + timestamp: Long, + amount: Double, + type: Bolus.Type, + isBasalInsulin: Boolean = false, + insulinConfiguration: InsulinConfiguration? = null, + interfaceIDs_backing: InterfaceIDs? = null + ) : this(Bolus( + timestamp = timestamp, + amount = amount, + type = type, + isBasalInsulin = isBasalInsulin, + insulinConfiguration = insulinConfiguration, + interfaceIDs_backing = interfaceIDs_backing + )) + + override fun run(): TransactionResult { + val result = TransactionResult() + val current = database.bolusDao.findById(bolus.id) + if (current == null) { + database.bolusDao.insertNewEntry(bolus) + result.inserted.add(bolus) + } else { + database.bolusDao.updateExistingEntry(bolus) + result.updated.add(bolus) + } + return result + } + + class TransactionResult { + + val inserted = mutableListOf() + val updated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateCarbsTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateCarbsTransaction.kt new file mode 100644 index 0000000000..2cf4406206 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InsertOrUpdateCarbsTransaction.kt @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.database.transactions + +import info.nightscout.androidaps.database.embedments.InterfaceIDs +import info.nightscout.androidaps.database.entities.Carbs + +/** + * Creates or updates the Carbs + */ +class InsertOrUpdateCarbsTransaction( + private val carbs: Carbs +) : Transaction() { + + constructor( + timestamp: Long, + amount: Double, + duration: Long, + interfaceIDs_backing: InterfaceIDs? = null + ) : this(Carbs( + timestamp = timestamp, + amount = amount, + duration = duration, + interfaceIDs_backing = interfaceIDs_backing + )) + + override fun run(): TransactionResult { + val result = TransactionResult() + val current = database.carbsDao.findById(carbs.id) + if (current == null) { + database.carbsDao.insertNewEntry(carbs) + result.inserted.add(carbs) + } else { + database.carbsDao.updateExistingEntry(carbs) + result.updated.add(carbs) + } + return result + } + + class TransactionResult { + + val inserted = mutableListOf() + val updated = mutableListOf() + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateBolusCalculatorResultTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateBolusCalculatorResultTransaction.kt new file mode 100644 index 0000000000..b2932f71c6 --- /dev/null +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateBolusCalculatorResultTransaction.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.database.transactions + +class InvalidateBolusCalculatorResultTransaction(val id: Long) : Transaction() { + + override fun run() { + val bolusCalculatorResult = database.bolusCalculatorResultDao.findById(id) + ?: throw IllegalArgumentException("There is no such BolusCalculatorResult with the specified ID.") + + bolusCalculatorResult.isValid = false + database.bolusCalculatorResultDao.updateExistingEntry(bolusCalculatorResult) + } +} \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateMealLinkTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateMealLinkTransaction.kt deleted file mode 100644 index 631260bdd1..0000000000 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/InvalidateMealLinkTransaction.kt +++ /dev/null @@ -1,42 +0,0 @@ -package info.nightscout.androidaps.database.transactions - -class InvalidateMealLinkTransaction(val id: Long) : Transaction() { - - override fun run() { - val mealLink = database.mealLinkDao.findById(id) - ?: throw IllegalArgumentException("There is no such MealLink with the specified ID.") - - if (mealLink.bolusId != null) { - val bolus = database.bolusDao.findById(id) - ?: throw IllegalArgumentException("There is no such Bolus with the specified ID.") - bolus.isValid = false - database.bolusDao.updateExistingEntry(bolus) - } - - if (mealLink.carbsId != null) { - val carbs = database.carbsDao.findById(id) - ?: throw IllegalArgumentException("There is no such Carbs with the specified ID.") - carbs.isValid = false - database.carbsDao.updateExistingEntry(carbs) - } - - if (mealLink.bolusCalcResultId != null) { - val bolusCalculatorResult = database.bolusCalculatorResultDao.findById(id) - ?: throw IllegalArgumentException("There is no such BolusCalculatorResult with the specified ID.") - bolusCalculatorResult.isValid = false - database.bolusCalculatorResultDao.updateExistingEntry(bolusCalculatorResult) - } - - // TemporaryBasal is not invalidated for safety reason - - if (mealLink.noteId != null) { - val therapyEvent = database.therapyEventDao.findById(id) - ?: throw IllegalArgumentException("There is no such TherapyEvent with the specified ID.") - therapyEvent.isValid = false - database.therapyEventDao.updateExistingEntry(therapyEvent) - } - - mealLink.isValid = false - database.mealLinkDao.updateExistingEntry(mealLink) - } -} \ No newline at end of file