remove MealLink.class

This commit is contained in:
Milos Kozak 2021-03-25 23:52:08 +01:00
parent 7f0fe881b6
commit ff001b0add
32 changed files with 606 additions and 810 deletions

View file

@ -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

View file

@ -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())

View file

@ -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() {

View file

@ -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)
})
}
})
}

View file

@ -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

View file

@ -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)
}

View file

@ -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<MealLinkLoaded>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_meal_link_item, viewGroup, false)
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)
})

View file

@ -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()) {

View file

@ -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())

View file

@ -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">
<LinearLayout
android:layout_width="match_parent"

View file

@ -13,6 +13,7 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/metadata_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
@ -35,22 +36,6 @@
android:text="1.1.2000"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/treatments_iob_label_string" />
<TextView
android:id="@+id/iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -68,16 +53,6 @@
android:textColor="@color/colorCalculatorButton"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/meal_or_correction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Meal"
android:textAlignment="textEnd"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
@ -119,6 +94,22 @@
android:layout_marginEnd="30dp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/treatments_iob_label_string" />
<TextView
android:id="@+id/iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -126,6 +117,15 @@
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/meal_or_correction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Meal"
android:textAlignment="textEnd"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/bolus_ns"
android:layout_width="wrap_content"

View file

@ -7,7 +7,8 @@ import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertMealLinkTransaction
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusTransaction
import info.nightscout.androidaps.database.transactions.InsertOrUpdateCarbsTransaction
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.T
@ -40,7 +41,6 @@ class DetailedBolusInfo {
var bolusTimestamp: Long? = null
var carbsPumpId: Long? = null
var carbsTimestamp: Long? = null
var superBolusTemporaryBasal: TemporaryBasal? = null
enum class MeterType(val text: String) {
FINGER("Finger"),
@ -106,24 +106,20 @@ class DetailedBolusInfo {
fun createCarbs(): Carbs? =
if (carbs != 0.0)
Carbs(
timestamp = carbsTimestamp ?: T.mins(timestamp).msecs(),
timestamp = carbsTimestamp ?: timestamp + T.mins(carbTime.toLong()).msecs(),
amount = carbs,
duration = carbsDuration
)
else null
fun insertMealLinkTransaction(): InsertMealLinkTransaction {
// For NS make sure timestamps of bolus and carbs are different to avoid unwanted deduplication
bolusTimestamp = bolusTimestamp ?: timestamp
carbsTimestamp = carbsTimestamp ?: timestamp
if (bolusTimestamp == carbsTimestamp) carbsTimestamp = carbsTimestamp!! + 1000
return InsertMealLinkTransaction(
bolus = createBolus(),
carbs = createCarbs(),
bolusCalculatorResult = bolusCalculatorResult,
therapyEvent = createTherapyEvent(),
superBolusTemporaryBasal = superBolusTemporaryBasal
)
fun insertCarbsTransaction(): InsertOrUpdateCarbsTransaction {
if (carbs == 0.0) throw IllegalStateException("carbs == 0.0")
return InsertOrUpdateCarbsTransaction(createCarbs()!!)
}
fun insertBolusTransaction(): InsertOrUpdateBolusTransaction {
if (insulin == 0.0) throw IllegalStateException("insulin == 0.0")
return InsertOrUpdateBolusTransaction(createBolus()!!)
}
fun toJsonString(): String =
@ -146,11 +142,13 @@ class DetailedBolusInfo {
n.mgdlGlucose = mgdlGlucose
n.glucoseType = glucoseType
n.bolusType = bolusType
n.carbsDuration = carbsDuration
n.pumpType = pumpType
n.pumpSerial = pumpSerial
n.bolusPumpId = bolusPumpId
n.carbsPumpId = carbsPumpId
n.carbsTimestamp = carbsTimestamp
return n
}

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.nsclient;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
@ -20,9 +21,9 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
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.GlucoseValue;
import info.nightscout.androidaps.database.entities.MealLinkLoaded;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.db.DbRequest;
@ -280,54 +281,72 @@ public class NSUpload {
*/
}
public void uploadMealLinkRecord(MealLinkLoaded mealLinkLoaded) {
Bolus bolus = mealLinkLoaded.getBolus();
Carbs carbs = mealLinkLoaded.getCarbs();
TherapyEvent therapyEvent = mealLinkLoaded.getTherapyEvent();
if (bolus != null && therapyEvent != null && bolus.getAmount() > 0) {
try {
JSONObject data = new JSONObject();
data.put("eventType", therapyEvent.getType().getText());
data.put("insulin", bolus.getAmount());
data.put("created_at", DateUtil.toISOString(bolus.getTimestamp()));
data.put("date", bolus.getTimestamp());
data.put("isSMB", bolus.getType() == Bolus.Type.SMB);
if (bolus.getInterfaceIDs().getPumpId() != null)
data.put("pumpId", bolus.getInterfaceIDs().getPumpId());
if (therapyEvent.getGlucose() != null)
data.put("glucose", therapyEvent.getGlucose());
if (therapyEvent.getGlucoseType() != null)
data.put("glucoseType", therapyEvent.getGlucoseType().getText());
if (mealLinkLoaded.getBolusCalculatorResult() != null)
data.put("bolusCalc", new Gson().toJson(mealLinkLoaded.getBolusCalculatorResult()));
if (therapyEvent.getNote() != null)
data.put("notes", therapyEvent.getNote());
uploadCareportalEntryToNS(data, bolus.getTimestamp());
} catch (JSONException e) {
e.printStackTrace();
}
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();
}
}

View file

@ -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')"
]
}
}

View file

@ -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

View file

@ -175,28 +175,48 @@ open class AppRepository @Inject internal constructor(
fun deleteAllFoods() =
database.foodDao.deleteAllEntries()
// MEAL LINK
fun getMealLinkLoadedDataFromTime(timestamp: Long, ascending: Boolean): Single<List<MealLinkLoaded>> =
database.mealLinkDao.getMealLinkLoadedFromTime(timestamp)
// BOLUS
fun getBolusesDataFromTime(timestamp: Long, ascending: Boolean): Single<List<Bolus>> =
database.bolusDao.getBolusesFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getMealLinkLoadedDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<MealLinkLoaded>> =
database.mealLinkDao.getMealLinkLoadedIncludingInvalidFromTime(timestamp)
fun getBolusesIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<Bolus>> =
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<List<Carbs>> =
database.carbsDao.getCarbsFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getCarbsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<Carbs>> =
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<List<BolusCalculatorResult>> =
database.bolusCalculatorResultDao.getBolusCalculatorResultsFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getBolusCalculatorResultsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<BolusCalculatorResult>> =
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")

View file

@ -14,7 +14,6 @@ internal class DelegatedAppDatabase(val changes: MutableList<DBEntry>, 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)

View file

@ -14,5 +14,12 @@ internal interface BolusCalculatorResultDao : TraceableDao<BolusCalculatorResult
override fun findById(id: Long): BolusCalculatorResult?
@Query("DELETE FROM $TABLE_BOLUS_CALCULATOR_RESULTS")
override fun deleteAllEntries()
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE isValid = 1 AND timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getBolusCalculatorResultsFromTime(timestamp: Long): Single<List<BolusCalculatorResult>>
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getBolusCalculatorResultsIncludingInvalidFromTime(timestamp: Long): Single<List<BolusCalculatorResult>>
}

View file

@ -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<Bolus> {
@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<List<Bolus>>
@Query("SELECT * FROM $TABLE_BOLUSES WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getBolusesIncludingInvalidFromTime(timestamp: Long): Single<List<Bolus>>
}

View file

@ -15,4 +15,10 @@ internal interface CarbsDao : TraceableDao<Carbs> {
@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<List<Carbs>>
@Query("SELECT * FROM $TABLE_CARBS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getCarbsIncludingInvalidFromTime(timestamp: Long): Single<List<Carbs>>
}

View file

@ -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<MealLink> {
@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<List<MealLinkLoaded>>
@Transaction
@Query("SELECT * FROM $TABLE_MEAL_LINKS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getMealLinkLoadedIncludingInvalidFromTime(timestamp: Long): Single<List<MealLinkLoaded>>
}

View file

@ -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<MultiwaveBolusLink> {
@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()
}

View file

@ -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<DBEntry>, 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)
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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?
)

View file

@ -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<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(
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<MealLinkLoaded>()
}
}

View file

@ -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<InsertOrUpdateBolusCalculatorResultTransaction.TransactionResult>() {
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<BolusCalculatorResult>()
val updated = mutableListOf<BolusCalculatorResult>()
}
}

View file

@ -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<InsertOrUpdateBolusTransaction.TransactionResult>() {
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<Bolus>()
val updated = mutableListOf<Bolus>()
}
}

View file

@ -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<InsertOrUpdateCarbsTransaction.TransactionResult>() {
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<Carbs>()
val updated = mutableListOf<Carbs>()
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
class InvalidateBolusCalculatorResultTransaction(val id: Long) : Transaction<Unit>() {
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)
}
}

View file

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