Merge branch 'dev' of https://github.com/nightscout/AndroidAPS into dev
This commit is contained in:
commit
4bf3879377
69 changed files with 1816 additions and 1318 deletions
|
@ -109,7 +109,7 @@ android {
|
|||
defaultConfig {
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "3.0.0.1-dev-h"
|
||||
version "3.0.0.1-dev-i"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||
|
|
|
@ -13,7 +13,6 @@ import dagger.android.HasAndroidInjector
|
|||
import info.nightscout.androidaps.data.ProfileSealed
|
||||
import info.nightscout.androidaps.database.interfaces.end
|
||||
import info.nightscout.androidaps.extensions.directionToIcon
|
||||
import info.nightscout.androidaps.extensions.isInProgress
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
|
@ -78,7 +77,7 @@ class Widget : AppWidgetProvider() {
|
|||
|
||||
// Create an Intent to launch MainActivity when clicked
|
||||
val intent = Intent(context, MainActivity::class.java).also { it.action = intentAction }
|
||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
|
||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
// Widgets allow click handlers to only launch pending intents
|
||||
views.setOnClickPendingIntent(R.id.widget_layout, pendingIntent)
|
||||
|
||||
|
@ -105,7 +104,11 @@ class Widget : AppWidgetProvider() {
|
|||
}
|
||||
)
|
||||
views.setImageViewResource(R.id.arrow, trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
|
||||
//binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor(context))
|
||||
views.setInt(R.id.arrow, "setColorFilter", when {
|
||||
overviewData.isLow -> rh.gc(R.color.low)
|
||||
overviewData.isHigh -> rh.gc(R.color.high)
|
||||
else -> rh.gc(R.color.inrange)
|
||||
})
|
||||
|
||||
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
||||
if (glucoseStatus != null) {
|
||||
|
@ -127,21 +130,21 @@ class Widget : AppWidgetProvider() {
|
|||
}
|
||||
|
||||
private fun updateTemporaryBasal(views: RemoteViews) {
|
||||
views.setTextViewText(R.id.base_basal, overviewData.temporaryBasalText)
|
||||
views.setTextColor(R.id.base_basal, overviewData.temporaryBasalColor)
|
||||
views.setImageViewResource(R.id.base_basal_icon, overviewData.temporaryBasalIcon)
|
||||
views.setTextViewText(R.id.base_basal, overviewData.temporaryBasalText(iobCobCalculator))
|
||||
views.setTextColor(R.id.base_basal, overviewData.temporaryBasalColor(iobCobCalculator))
|
||||
views.setImageViewResource(R.id.base_basal_icon, overviewData.temporaryBasalIcon(iobCobCalculator))
|
||||
}
|
||||
|
||||
private fun updateExtendedBolus(views: RemoteViews) {
|
||||
val pump = activePlugin.activePump
|
||||
views.setTextViewText(R.id.extended_bolus, overviewData.extendedBolusText)
|
||||
views.setTextViewText(R.id.extended_bolus, overviewData.extendedBolusText(iobCobCalculator))
|
||||
views.setViewVisibility(R.id.extended_layout, (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility())
|
||||
}
|
||||
|
||||
private fun updateIobCob(views: RemoteViews) {
|
||||
views.setTextViewText(R.id.iob, overviewData.iobText)
|
||||
views.setTextViewText(R.id.iob, overviewData.iobText(iobCobCalculator))
|
||||
// cob
|
||||
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, isDev = false) ?: rh.gs(R.string.value_unavailable_short)
|
||||
var cobText = overviewData.cobInfo(iobCobCalculator).displayText(rh, dateUtil, isDev = false) ?: rh.gs(R.string.value_unavailable_short)
|
||||
|
||||
val constraintsProcessed = loop.lastRun?.constraintsProcessed
|
||||
val lastRun = loop.lastRun
|
||||
|
@ -158,7 +161,6 @@ class Widget : AppWidgetProvider() {
|
|||
|
||||
private fun updateTemporaryTarget(views: RemoteViews) {
|
||||
val units = profileFunction.getUnits()
|
||||
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
|
||||
val tempTarget = overviewData.temporaryTarget
|
||||
if (tempTarget != null) {
|
||||
// this is crashing, use background as text for now
|
||||
|
@ -210,12 +212,12 @@ class Widget : AppWidgetProvider() {
|
|||
views.setTextColor(R.id.active_profile, profileTextColor)
|
||||
}
|
||||
|
||||
fun updateSensitivity(views: RemoteViews) {
|
||||
private fun updateSensitivity(views: RemoteViews) {
|
||||
if (sp.getBoolean(R.string.key_openapsama_useautosens, false) && constraintChecker.isAutosensModeEnabled().value())
|
||||
views.setImageViewResource(R.id.sensitivity_icon, R.drawable.ic_swap_vert_black_48dp_green)
|
||||
else
|
||||
views.setImageViewResource(R.id.sensitivity_icon, R.drawable.ic_x_swap_vert)
|
||||
views.setTextViewText(R.id.sensitivity, overviewData.lastAutosensData?.let { autosensData ->
|
||||
views.setTextViewText(R.id.sensitivity, overviewData.lastAutosensData(iobCobCalculator)?.let { autosensData ->
|
||||
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
|
||||
} ?: "")
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package info.nightscout.androidaps.activities
|
|||
import android.annotation.SuppressLint
|
||||
import android.app.DatePickerDialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.ViewGroup
|
||||
|
@ -19,21 +18,18 @@ import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
|||
import info.nightscout.androidaps.events.EventCustomCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.extensions.toVisibilityKeepSpace
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.Loop
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewGraph
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventBucketedDataCreated
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
|
@ -42,6 +38,7 @@ import info.nightscout.androidaps.utils.T
|
|||
import info.nightscout.androidaps.utils.Translator
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
|
@ -59,9 +56,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var activePlugin: ActivePlugin
|
||||
@Inject lateinit var buildHelper: BuildHelper
|
||||
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
|
||||
@Inject lateinit var sensitivityAAPSPlugin: SensitivityAAPSPlugin
|
||||
@Inject lateinit var sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var overviewMenus: OverviewMenus
|
||||
|
@ -72,6 +66,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
@Inject lateinit var translator: Translator
|
||||
@Inject lateinit var context: Context
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var calculationWorkflow: CalculationWorkflow
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
|
@ -94,6 +89,17 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
setContentView(binding.root)
|
||||
|
||||
// We don't want to use injected singletons but own instance working on top of different data
|
||||
overviewData =
|
||||
OverviewData(
|
||||
aapsLogger,
|
||||
rh,
|
||||
dateUtil,
|
||||
sp,
|
||||
activePlugin,
|
||||
defaultValueHelper,
|
||||
profileFunction,
|
||||
repository
|
||||
)
|
||||
iobCobCalculator =
|
||||
IobCobCalculatorPlugin(
|
||||
injector,
|
||||
|
@ -104,32 +110,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
rh,
|
||||
profileFunction,
|
||||
activePlugin,
|
||||
sensitivityOref1Plugin,
|
||||
sensitivityAAPSPlugin,
|
||||
sensitivityWeightedAveragePlugin,
|
||||
fabricPrivacy,
|
||||
dateUtil,
|
||||
repository,
|
||||
context,
|
||||
dataWorker
|
||||
)
|
||||
overviewData =
|
||||
OverviewData(
|
||||
injector,
|
||||
aapsLogger,
|
||||
rh,
|
||||
dateUtil,
|
||||
sp,
|
||||
activePlugin,
|
||||
defaultValueHelper,
|
||||
profileFunction,
|
||||
config,
|
||||
loop,
|
||||
nsDeviceStatus,
|
||||
repository,
|
||||
overviewMenus,
|
||||
iobCobCalculator,
|
||||
translator
|
||||
overviewData,
|
||||
calculationWorkflow
|
||||
)
|
||||
|
||||
binding.left.setOnClickListener {
|
||||
|
@ -217,7 +202,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
override fun onPause() {
|
||||
super.onPause()
|
||||
disposable.clear()
|
||||
iobCobCalculator.stopCalculation("onPause")
|
||||
calculationWorkflow.stopCalculation(CalculationWorkflow.HISTORY_CALCULATION, "onPause")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -239,22 +224,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
disposable += rxBus
|
||||
.toObservable(EventIobCalculationProgress::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
if (it.cause is EventCustomCalculationFinished)
|
||||
binding.overviewIobcalculationprogess.text = it.progressPct.toString() + "%"
|
||||
}, fabricPrivacy::logException)
|
||||
.subscribe({ updateCalcProgress(it.pass.finalPercent(it.progressPct)) }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.toObservable(EventUpdateOverviewGraph::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateGUI("EventRefreshOverview") }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventBucketedDataCreated::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
||||
rxBus.send(EventRefreshOverview("EventBucketedDataCreated"))
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
if (overviewData.fromTime == 0L) {
|
||||
// set start of current day
|
||||
|
@ -310,17 +284,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
@Suppress("SameParameterValue")
|
||||
private fun loadAll(from: String) {
|
||||
updateDate()
|
||||
Thread {
|
||||
overviewData.prepareBgData(from)
|
||||
overviewData.prepareTreatmentsData(from)
|
||||
rxBus.send(EventRefreshOverview("loadAll_$from"))
|
||||
overviewData.prepareTemporaryTargetData(from)
|
||||
rxBus.send(EventRefreshOverview("loadAll_$from"))
|
||||
overviewData.prepareBasalData(from)
|
||||
rxBus.send(EventRefreshOverview(from))
|
||||
aapsLogger.debug(LTag.UI, "loadAll $from finished")
|
||||
runCalculation(from)
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun setTime(start: Long) {
|
||||
|
@ -341,22 +305,32 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun runCalculation(from: String) {
|
||||
iobCobCalculator.runCalculation(from, overviewData.toTime, bgDataReload = true, limitDataToOldestAvailable = false, cause = EventCustomCalculationFinished())
|
||||
calculationWorkflow.runCalculation(
|
||||
CalculationWorkflow.HISTORY_CALCULATION,
|
||||
iobCobCalculator,
|
||||
overviewData,
|
||||
from,
|
||||
overviewData.toTime,
|
||||
bgDataReload = true,
|
||||
limitDataToOldestAvailable = false,
|
||||
cause = EventCustomCalculationFinished(),
|
||||
runLoop = false
|
||||
)
|
||||
}
|
||||
|
||||
@Volatile
|
||||
var runningRefresh = false
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
private fun refreshLoop(from: String) {
|
||||
if (runningRefresh) return
|
||||
runningRefresh = true
|
||||
overviewData.prepareIobAutosensData(from)
|
||||
rxBus.send(EventRefreshOverview(from))
|
||||
aapsLogger.debug(LTag.UI, "refreshLoop finished")
|
||||
runningRefresh = false
|
||||
}
|
||||
|
||||
fun updateDate() {
|
||||
private fun updateDate() {
|
||||
binding.date.text = dateUtil.dateAndTimeString(overviewData.fromTime)
|
||||
binding.zoom.text = rangeToDisplay.toString()
|
||||
}
|
||||
|
@ -440,4 +414,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
secondaryGraphsData[g].performUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCalcProgress(percent: Int) {
|
||||
binding.progressBar.progress = percent
|
||||
binding.progressBar.visibility = (percent != 100).toVisibilityKeepSpace()
|
||||
}
|
||||
}
|
|
@ -24,9 +24,7 @@ import info.nightscout.androidaps.database.transactions.InvalidateCarbsTransacti
|
|||
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
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.iobCalc
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
|
@ -170,16 +168,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
.observeOn(aapsSchedulers.main)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -334,7 +322,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -342,7 +330,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import info.nightscout.androidaps.database.transactions.InvalidateTherapyEventTr
|
|||
import info.nightscout.androidaps.databinding.TreatmentsCareportalFragmentBinding
|
||||
import info.nightscout.androidaps.databinding.TreatmentsCareportalItemBinding
|
||||
import info.nightscout.androidaps.events.EventTherapyEventChange
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
|
@ -128,11 +127,6 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
.observeOn(aapsSchedulers.main)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -216,7 +210,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -224,7 +218,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import info.nightscout.androidaps.database.transactions.InvalidateExtendedBolusT
|
|||
import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusFragmentBinding
|
||||
import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusItemBinding
|
||||
import info.nightscout.androidaps.events.EventExtendedBolusChange
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.iobCalc
|
||||
import info.nightscout.androidaps.extensions.isInProgress
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
|
@ -105,11 +104,6 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -203,7 +197,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -211,7 +205,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding
|
|||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.getCustomizedName
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
|
@ -47,7 +46,6 @@ import io.reactivex.rxjava3.core.Completable
|
|||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||
|
@ -162,11 +160,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
|||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -306,7 +299,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -314,7 +307,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding
|
|||
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.friendlyDescription
|
||||
import info.nightscout.androidaps.extensions.highValueToUnitsToString
|
||||
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
|
||||
|
@ -134,11 +133,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -235,7 +229,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -243,7 +237,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,7 @@ import info.nightscout.androidaps.database.transactions.InvalidateExtendedBolusT
|
|||
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransaction
|
||||
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsFragmentBinding
|
||||
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsItemBinding
|
||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.iobCalc
|
||||
import info.nightscout.androidaps.extensions.toStringFull
|
||||
import info.nightscout.androidaps.extensions.toTemporaryBasal
|
||||
|
@ -141,15 +139,6 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -251,7 +240,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
showInvalidated = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -259,7 +248,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
showInvalidated = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
|||
import info.nightscout.androidaps.databinding.TreatmentsUserEntryFragmentBinding
|
||||
import info.nightscout.androidaps.databinding.TreatmentsUserEntryItemBinding
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.interfaces.ImportExportPrefs
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
|
@ -30,7 +29,6 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
|||
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||
|
@ -99,11 +97,6 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
|||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentUpdateGui::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -172,7 +165,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
|||
showLoop = true
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_loop_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -180,7 +173,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
|||
showLoop = false
|
||||
updateMenuVisibility()
|
||||
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_hide_records))
|
||||
rxBus.send(EventTreatmentUpdateGui())
|
||||
swapAdapter()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,11 @@ class CompatDBHelper @Inject constructor(
|
|||
rxBus.send(EventExtendedBolusChange())
|
||||
rxBus.send(EventNewHistoryData(timestamp, false))
|
||||
}
|
||||
it.filterIsInstance<EffectiveProfileSwitch>().firstOrNull()?.let { eps ->
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventEffectiveProfileSwitchChanged $eps")
|
||||
rxBus.send(EventEffectiveProfileSwitchChanged(eps))
|
||||
rxBus.send(EventNewHistoryData(eps.timestamp, false))
|
||||
}
|
||||
it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let { tt ->
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange $tt")
|
||||
rxBus.send(EventTempTargetChange())
|
||||
|
@ -76,10 +81,6 @@ class CompatDBHelper @Inject constructor(
|
|||
aapsLogger.debug(LTag.DATABASE, "Firing EventProfileSwitchChanged $ps")
|
||||
rxBus.send(EventProfileSwitchChanged())
|
||||
}
|
||||
it.filterIsInstance<EffectiveProfileSwitch>().firstOrNull()?.let { eps ->
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventEffectiveProfileSwitchChanged $eps")
|
||||
rxBus.send(EventEffectiveProfileSwitchChanged(eps))
|
||||
}
|
||||
it.filterIsInstance<OfflineEvent>().firstOrNull()?.let { oe ->
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventOfflineChange $oe")
|
||||
rxBus.send(EventOfflineChange())
|
||||
|
|
|
@ -8,8 +8,6 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
|
|||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Worker
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOrefWorker
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
|
@ -21,6 +19,4 @@ abstract class APSModule {
|
|||
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
|
||||
@ContributesAndroidInjector abstract fun iobCobWorkerInjector(): IobCobOrefWorker
|
||||
@ContributesAndroidInjector abstract fun iobCobOref1WorkerInjector(): IobCobOref1Worker
|
||||
}
|
|
@ -46,6 +46,7 @@ import javax.inject.Singleton
|
|||
OmnipodDashModule::class,
|
||||
OmnipodErosModule::class,
|
||||
APSModule::class,
|
||||
WorkflowModule::class,
|
||||
PreferencesModule::class,
|
||||
OverviewModule::class,
|
||||
DataClassesModule::class,
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package info.nightscout.androidaps.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.*
|
||||
import info.nightscout.androidaps.workflow.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class WorkflowModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun iobCobWorkerInjector(): IobCobOrefWorker
|
||||
@ContributesAndroidInjector abstract fun iobCobOref1WorkerInjector(): IobCobOref1Worker
|
||||
@ContributesAndroidInjector abstract fun prepareIobAutosensDataWorkerInjector(): PrepareIobAutosensGraphDataWorker
|
||||
@ContributesAndroidInjector abstract fun prepareBasalDataWorkerInjector(): PrepareBasalDataWorker
|
||||
@ContributesAndroidInjector abstract fun prepareTemporaryTargetDataWorkerInjector(): PrepareTemporaryTargetDataWorker
|
||||
@ContributesAndroidInjector abstract fun prepareTreatmentsDataWorkerInjector(): PrepareTreatmentsDataWorker
|
||||
@ContributesAndroidInjector abstract fun loadIobCobResultsWorkerInjector(): UpdateIobCobSensWorker
|
||||
@ContributesAndroidInjector abstract fun preparePredictionsWorkerInjector(): PreparePredictionsWorker
|
||||
@ContributesAndroidInjector abstract fun updateGraphAndIobWorkerInjector(): UpdateGraphWorker
|
||||
@ContributesAndroidInjector abstract fun prepareBgDataWorkerInjector(): PrepareBgDataWorker
|
||||
@ContributesAndroidInjector abstract fun prepareBucketedDataWorkerInjector(): PrepareBucketedDataWorker
|
||||
@ContributesAndroidInjector abstract fun loadBgDataWorkerInjector(): LoadBgDataWorker
|
||||
@ContributesAndroidInjector abstract fun invokeLoopWorkerInjector(): InvokeLoopWorker
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
class EventReloadProfileSwitchData : Event()
|
|
@ -1,3 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
class EventTreatmentUpdateGui : EventUpdateGui()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventLoopInvoked : Event()
|
|
@ -10,11 +10,13 @@ import android.content.Intent
|
|||
import android.os.SystemClock
|
||||
import androidx.core.app.NotificationCompat
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.*
|
||||
import info.nightscout.androidaps.BuildConfig
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainActivity
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.annotations.OpenForTesting
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.data.PumpEnactResult
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
|
@ -25,13 +27,13 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
|
|||
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentOfflineEventTransaction
|
||||
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
|
||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventNewBG
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||
import info.nightscout.androidaps.extensions.convertedToPercent
|
||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.interfaces.Loop.LastRun
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
||||
|
@ -51,13 +53,10 @@ import info.nightscout.androidaps.utils.DateUtil
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||
import info.nightscout.androidaps.extensions.convertedToPercent
|
||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
|
@ -88,7 +87,8 @@ class LoopPlugin @Inject constructor(
|
|||
private val uel: UserEntryLogger,
|
||||
private val repository: AppRepository,
|
||||
private val runningConfiguration: RunningConfiguration
|
||||
) : PluginBase(PluginDescription()
|
||||
) : PluginBase(
|
||||
PluginDescription()
|
||||
.mainType(PluginType.LOOP)
|
||||
.fragmentClass(LoopFragment::class.java.name)
|
||||
.pluginIcon(R.drawable.ic_loop_closed_white)
|
||||
|
@ -101,7 +101,7 @@ class LoopPlugin @Inject constructor(
|
|||
), Loop {
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private var lastBgTriggeredRun: Long = 0
|
||||
override var lastBgTriggeredRun: Long = 0
|
||||
private var carbsSuggestionsSuspendedUntil: Long = 0
|
||||
private var prevCarbsreq = 0
|
||||
override var lastRun: LastRun? = null
|
||||
|
@ -109,39 +109,19 @@ class LoopPlugin @Inject constructor(
|
|||
override fun onStart() {
|
||||
createNotificationChannel()
|
||||
super.onStart()
|
||||
disposable.add(rxBus
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempTargetChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ invoke("EventTempTargetChange", true) }, fabricPrivacy::logException)
|
||||
)
|
||||
/*
|
||||
This method is triggered once autosens calculation has completed, so the LoopPlugin
|
||||
has current data to work with. However, autosens calculation can be triggered by multiple
|
||||
sources and currently only a new BG should trigger a loop run. Hence we return early if
|
||||
the event causing the calculation is not EventNewBg.
|
||||
<p>
|
||||
*/
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ event: EventAutosensCalculationFinished ->
|
||||
// Autosens calculation not triggered by a new BG
|
||||
if (event.cause !is EventNewBG) return@subscribe
|
||||
val glucoseValue = iobCobCalculator.ads.actualBg() ?: return@subscribe
|
||||
// BG outdated
|
||||
// already looped with that value
|
||||
if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe
|
||||
lastBgTriggeredRun = glucoseValue.timestamp
|
||||
invoke("AutosenseCalculation for $glucoseValue", true)
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
@SuppressLint("WrongConstant") val channel = NotificationChannel(CHANNEL_ID,
|
||||
@SuppressLint("WrongConstant") val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
NotificationManager.IMPORTANCE_HIGH)
|
||||
CHANNEL_ID,
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
)
|
||||
mNotificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
|
@ -255,7 +235,7 @@ class LoopPlugin @Inject constructor(
|
|||
if (apsResult == null) {
|
||||
rxBus.send(EventLoopSetLastRunGui(rh.gs(R.string.noapsselected)))
|
||||
return
|
||||
} else rxBus.send(EventLoopInvoked())
|
||||
}
|
||||
|
||||
if (!isEmptyQueue()) {
|
||||
aapsLogger.debug(LTag.APS, rh.gs(R.string.pumpbusy))
|
||||
|
@ -296,9 +276,11 @@ class LoopPlugin @Inject constructor(
|
|||
lastRun.lastTBRRequest = 0
|
||||
lastRun.lastSMBEnact = 0
|
||||
lastRun.lastSMBRequest = 0
|
||||
buildDeviceStatus(dateUtil, this, iobCobCalculator, profileFunction,
|
||||
buildDeviceStatus(
|
||||
dateUtil, this, iobCobCalculator, profileFunction,
|
||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION
|
||||
)?.also {
|
||||
repository.insert(it)
|
||||
}
|
||||
|
||||
|
@ -316,7 +298,11 @@ class LoopPlugin @Inject constructor(
|
|||
if (closedLoopEnabled.value()) {
|
||||
if (allowNotification) {
|
||||
if (resultAfterConstraints.isCarbsRequired
|
||||
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)) {
|
||||
&& resultAfterConstraints.carbsReq >= sp.getInt(
|
||||
R.string.key_smb_enable_carbs_suggestions_threshold,
|
||||
0
|
||||
) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)
|
||||
) {
|
||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
|
||||
rxBus.send(EventNewNotification(carbReqLocal))
|
||||
|
@ -353,9 +339,11 @@ class LoopPlugin @Inject constructor(
|
|||
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(Constants.notificationID, builder.build())
|
||||
uel.log(Action.CAREPORTAL, Sources.Loop, rh.gs(R.string.carbsreq, resultAfterConstraints.carbsReq, resultAfterConstraints.carbsReqWithin),
|
||||
uel.log(
|
||||
Action.CAREPORTAL, Sources.Loop, rh.gs(R.string.carbsreq, resultAfterConstraints.carbsReq, resultAfterConstraints.carbsReqWithin),
|
||||
ValueWithUnit.Gram(resultAfterConstraints.carbsReq),
|
||||
ValueWithUnit.Minute(resultAfterConstraints.carbsReqWithin))
|
||||
ValueWithUnit.Minute(resultAfterConstraints.carbsReqWithin)
|
||||
)
|
||||
rxBus.send(EventNewOpenLoopNotification())
|
||||
|
||||
//only send to wear if Native notifications are turned off
|
||||
|
@ -373,7 +361,8 @@ class LoopPlugin @Inject constructor(
|
|||
}
|
||||
}
|
||||
if (resultAfterConstraints.isChangeRequested
|
||||
&& !commandQueue.bolusInQueue()) {
|
||||
&& !commandQueue.bolusInQueue()
|
||||
) {
|
||||
val waiting = PumpEnactResult(injector)
|
||||
waiting.queued = true
|
||||
if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
|
||||
|
@ -486,9 +475,11 @@ class LoopPlugin @Inject constructor(
|
|||
lastRun.lastTBRRequest = lastRun.lastAPSRun
|
||||
lastRun.lastTBREnact = dateUtil.now()
|
||||
lastRun.lastOpenModeAccept = dateUtil.now()
|
||||
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction,
|
||||
buildDeviceStatus(
|
||||
dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction,
|
||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION
|
||||
)?.also {
|
||||
repository.insert(it)
|
||||
}
|
||||
sp.incInt(R.string.key_ObjectivesmanualEnacts)
|
||||
|
@ -531,8 +522,10 @@ class LoopPlugin @Inject constructor(
|
|||
commandQueue.cancelTempBasal(false, callback)
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0)
|
||||
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run()
|
||||
callback?.result(
|
||||
PumpEnactResult(injector).absolute(request.rate).duration(0)
|
||||
.enacted(false).success(true).comment(R.string.basal_set_correctly)
|
||||
)?.run()
|
||||
}
|
||||
} else if (request.usePercent && allowPercentage()) {
|
||||
if (request.percent == 100 && request.duration == 0) {
|
||||
|
@ -542,32 +535,52 @@ class LoopPlugin @Inject constructor(
|
|||
commandQueue.cancelTempBasal(false, callback)
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0)
|
||||
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run()
|
||||
callback?.result(
|
||||
PumpEnactResult(injector).percent(request.percent).duration(0)
|
||||
.enacted(false).success(true).comment(R.string.basal_set_correctly)
|
||||
)?.run()
|
||||
}
|
||||
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(now, profile)) {
|
||||
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(
|
||||
now,
|
||||
profile
|
||||
)
|
||||
) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).percent(request.percent)
|
||||
callback?.result(
|
||||
PumpEnactResult(injector).percent(request.percent)
|
||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||
.comment(R.string.let_temp_basal_run))?.run()
|
||||
.comment(R.string.let_temp_basal_run)
|
||||
)?.run()
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
|
||||
uel.log(Action.TEMP_BASAL, Sources.Loop,
|
||||
uel.log(
|
||||
Action.TEMP_BASAL, Sources.Loop,
|
||||
ValueWithUnit.Percent(request.percent),
|
||||
ValueWithUnit.Minute(request.duration))
|
||||
ValueWithUnit.Minute(request.duration)
|
||||
)
|
||||
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
||||
}
|
||||
} else {
|
||||
if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.convertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) {
|
||||
if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(
|
||||
request.rate - activeTemp.convertedToAbsolute(
|
||||
now,
|
||||
profile
|
||||
)
|
||||
) < pump.pumpDescription.basalStep
|
||||
) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile))
|
||||
callback?.result(
|
||||
PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile))
|
||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||
.comment(R.string.let_temp_basal_run))?.run()
|
||||
.comment(R.string.let_temp_basal_run)
|
||||
)?.run()
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
|
||||
uel.log(Action.TEMP_BASAL, Sources.Loop,
|
||||
uel.log(
|
||||
Action.TEMP_BASAL, Sources.Loop,
|
||||
ValueWithUnit.UnitPerHour(request.rate),
|
||||
ValueWithUnit.Minute(request.duration))
|
||||
ValueWithUnit.Minute(request.duration)
|
||||
)
|
||||
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
||||
}
|
||||
}
|
||||
|
@ -581,9 +594,11 @@ class LoopPlugin @Inject constructor(
|
|||
val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
|
||||
if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
|
||||
callback?.result(PumpEnactResult(injector)
|
||||
callback?.result(
|
||||
PumpEnactResult(injector)
|
||||
.comment(R.string.smb_frequency_exceeded)
|
||||
.enacted(false).success(false))?.run()
|
||||
.enacted(false).success(false)
|
||||
)?.run()
|
||||
return
|
||||
}
|
||||
if (!pump.isInitialized()) {
|
||||
|
|
|
@ -169,6 +169,9 @@ class PluginStore @Inject constructor(
|
|||
override val activeSafety: Safety
|
||||
get() = getSpecificPluginsListByInterface(Safety::class.java).first() as Safety
|
||||
|
||||
override val activeIobCobCalculator: IobCobCalculator
|
||||
get() = getSpecificPluginsListByInterface(IobCobCalculator::class.java).first() as IobCobCalculator
|
||||
|
||||
override fun getPluginsList(): ArrayList<PluginBase> = ArrayList(plugins)
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,11 @@ import android.content.pm.ResolveInfo
|
|||
import android.os.Bundle
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.events.Event
|
||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.extensions.durationInMinutes
|
||||
import info.nightscout.androidaps.extensions.toStringFull
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
||||
|
@ -25,6 +24,8 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -68,26 +69,6 @@ class DataBroadcastPlugin @Inject constructor(
|
|||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTreatmentChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
|
|
|
@ -170,8 +170,7 @@ class NSClientPlugin @Inject constructor(
|
|||
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
aapsLogger.debug(LTag.NSCLIENT, "Service is connected")
|
||||
val mLocalBinder = service as NSClientService.LocalBinder
|
||||
@Suppress("UNNECESSARY_SAFE_CALL")
|
||||
val mLocalBinder = service as NSClientService.LocalBinder?
|
||||
nsClientService = mLocalBinder?.serviceInstance // is null when running in roboelectric
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,42 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.DashPathEffect
|
||||
import android.graphics.Paint
|
||||
import androidx.annotation.ColorInt
|
||||
import com.jjoe64.graphview.series.BarGraphSeries
|
||||
import com.jjoe64.graphview.series.DataPoint
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||
import info.nightscout.androidaps.extensions.*
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.extensions.convertedToPercent
|
||||
import info.nightscout.androidaps.extensions.isInProgress
|
||||
import info.nightscout.androidaps.extensions.toStringFull
|
||||
import info.nightscout.androidaps.extensions.toStringShort
|
||||
import info.nightscout.androidaps.extensions.valueToUnits
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.FixedLineGraphSeries
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@Singleton
|
||||
class OverviewData @Inject constructor(
|
||||
private val injector: HasAndroidInjector,
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val rh: ResourceHelper,
|
||||
private val dateUtil: DateUtil,
|
||||
|
@ -48,13 +44,7 @@ class OverviewData @Inject constructor(
|
|||
private val activePlugin: ActivePlugin,
|
||||
private val defaultValueHelper: DefaultValueHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val config: Config,
|
||||
private val loop: Loop,
|
||||
private val nsDeviceStatus: NSDeviceStatus,
|
||||
private val repository: AppRepository,
|
||||
private val overviewMenus: OverviewMenus,
|
||||
private val iobCobCalculator: IobCobCalculator,
|
||||
private val translator: Translator
|
||||
private val repository: AppRepository
|
||||
) {
|
||||
|
||||
var rangeToDisplay = 6 // for graph
|
||||
|
@ -65,13 +55,6 @@ class OverviewData @Inject constructor(
|
|||
fun reset() {
|
||||
pumpStatus = ""
|
||||
calcProgressPct = 100
|
||||
lastBg = null
|
||||
bolusIob = null
|
||||
basalIob = null
|
||||
cobInfo = null
|
||||
lastCarbsTime = 0L
|
||||
temporaryTarget = null
|
||||
lastAutosensData = null
|
||||
bgReadingsArray = ArrayList()
|
||||
bucketedGraphSeries = PointsWithLabelGraphSeries()
|
||||
bgReadingGraphSeries = PointsWithLabelGraphSeries()
|
||||
|
@ -128,7 +111,12 @@ class OverviewData @Inject constructor(
|
|||
* BG
|
||||
*/
|
||||
|
||||
var lastBg: GlucoseValue? = null
|
||||
val lastBg: GlucoseValue?
|
||||
get() =
|
||||
repository.getLastGlucoseValueWrapped().blockingGet().let { gvWrapped ->
|
||||
if (gvWrapped is ValueWrapper.Existing) gvWrapped.value
|
||||
else null
|
||||
}
|
||||
|
||||
val isLow: Boolean
|
||||
get() = lastBg?.let { lastBg ->
|
||||
|
@ -165,8 +153,7 @@ class OverviewData @Inject constructor(
|
|||
* TEMPORARY BASAL
|
||||
*/
|
||||
|
||||
val temporaryBasalText: String
|
||||
get() =
|
||||
fun temporaryBasalText(iobCobCalculator: IobCobCalculator): String =
|
||||
profileFunction.getProfile()?.let { profile ->
|
||||
var temporaryBasal = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())
|
||||
if (temporaryBasal?.isInProgress == false) temporaryBasal = null
|
||||
|
@ -174,8 +161,8 @@ class OverviewData @Inject constructor(
|
|||
?: rh.gs(R.string.pump_basebasalrate, profile.getBasal())
|
||||
} ?: rh.gs(R.string.notavailable)
|
||||
|
||||
val temporaryBasalDialogText: String
|
||||
get() = profileFunction.getProfile()?.let { profile ->
|
||||
fun temporaryBasalDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||
profileFunction.getProfile()?.let { profile ->
|
||||
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
||||
"${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}" +
|
||||
"\n" + rh.gs(R.string.tempbasal_label) + ": " + temporaryBasal.toStringFull(profile, dateUtil)
|
||||
|
@ -183,8 +170,7 @@ class OverviewData @Inject constructor(
|
|||
?: "${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}"
|
||||
} ?: rh.gs(R.string.notavailable)
|
||||
|
||||
val temporaryBasalIcon: Int
|
||||
get() =
|
||||
fun temporaryBasalIcon(iobCobCalculator: IobCobCalculator): Int =
|
||||
profileFunction.getProfile()?.let { profile ->
|
||||
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
||||
val percentRate = temporaryBasal.convertedToPercent(dateUtil.now(), profile)
|
||||
|
@ -196,63 +182,66 @@ class OverviewData @Inject constructor(
|
|||
}
|
||||
} ?: R.drawable.ic_cp_basal_no_tbr
|
||||
|
||||
val temporaryBasalColor: Int
|
||||
get() = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { rh.gc(R.color.basal) }
|
||||
?: rh.gc(R.color.defaulttextcolor)
|
||||
// will be removed if a solution of getting the right color for widget is solved
|
||||
fun temporaryBasalColor(iobCobCalculator: IobCobCalculator): Int =
|
||||
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { rh.gc(R.color.basal) }
|
||||
?: rh.gc(R.color.textAppearancemediumDark)
|
||||
|
||||
fun temporaryBasalColor(context: Context?, iobCobCalculator: IobCobCalculator): Int = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { rh.gac(context , R.attr.basal) }
|
||||
?: rh.gac(context, R.attr.textAppearancemediumColor)
|
||||
|
||||
/*
|
||||
* EXTENDED BOLUS
|
||||
*/
|
||||
|
||||
val extendedBolusText: String
|
||||
get() =
|
||||
fun extendedBolusText(iobCobCalculator: IobCobCalculator): String =
|
||||
iobCobCalculator.getExtendedBolus(dateUtil.now())?.let { extendedBolus ->
|
||||
if (!extendedBolus.isInProgress(dateUtil)) ""
|
||||
else if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
||||
else ""
|
||||
} ?: ""
|
||||
|
||||
val extendedBolusDialogText: String
|
||||
get() = iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil) ?: ""
|
||||
fun extendedBolusDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||
iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil) ?: ""
|
||||
|
||||
/*
|
||||
* IOB, COB
|
||||
*/
|
||||
|
||||
var bolusIob: IobTotal? = null
|
||||
var basalIob: IobTotal? = null
|
||||
var cobInfo: CobInfo? = null
|
||||
var lastCarbsTime: Long = 0L
|
||||
fun bolusIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromBolus().round()
|
||||
fun basalIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
|
||||
fun cobInfo(iobCobCalculator: IobCobCalculator): CobInfo = iobCobCalculator.getCobInfo(true, "Overview COB")
|
||||
|
||||
val iobText: String
|
||||
get() =
|
||||
bolusIob?.let { bolusIob ->
|
||||
basalIob?.let { basalIob ->
|
||||
rh.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob)
|
||||
} ?: rh.gs(R.string.value_unavailable_short)
|
||||
} ?: rh.gs(R.string.value_unavailable_short)
|
||||
val lastCarbsTime: Long
|
||||
get() = repository.getLastCarbsRecordWrapped().blockingGet().let { lastCarbs ->
|
||||
if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
|
||||
}
|
||||
|
||||
val iobDialogText: String
|
||||
get() =
|
||||
bolusIob?.let { bolusIob ->
|
||||
basalIob?.let { basalIob ->
|
||||
rh.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + "\n" +
|
||||
rh.gs(R.string.bolus) + ": " + rh.gs(R.string.formatinsulinunits, bolusIob.iob) + "\n" +
|
||||
rh.gs(R.string.basal) + ": " + rh.gs(R.string.formatinsulinunits, basalIob.basaliob)
|
||||
} ?: rh.gs(R.string.value_unavailable_short)
|
||||
} ?: rh.gs(R.string.value_unavailable_short)
|
||||
fun iobText(iobCobCalculator: IobCobCalculator): String =
|
||||
rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob)
|
||||
|
||||
fun iobDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||
rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob) + "\n" +
|
||||
rh.gs(R.string.bolus) + ": " + rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob) + "\n" +
|
||||
rh.gs(R.string.basal) + ": " + rh.gs(R.string.formatinsulinunits, basalIob(iobCobCalculator).basaliob)
|
||||
|
||||
/*
|
||||
* TEMP TARGET
|
||||
*/
|
||||
|
||||
var temporaryTarget: TemporaryTarget? = null
|
||||
val temporaryTarget: TemporaryTarget?
|
||||
get() =
|
||||
repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet().let { tempTarget ->
|
||||
if (tempTarget is ValueWrapper.Existing) tempTarget.value
|
||||
else null
|
||||
}
|
||||
|
||||
/*
|
||||
* SENSITIVITY
|
||||
*/
|
||||
|
||||
var lastAutosensData: AutosensData? = null
|
||||
fun lastAutosensData(iobCobCalculator: IobCobCalculator) = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
|
||||
|
||||
/*
|
||||
* Graphs
|
||||
*/
|
||||
|
@ -312,532 +301,4 @@ class OverviewData @Inject constructor(
|
|||
val dsMinScale = Scale()
|
||||
var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
|
||||
@Synchronized
|
||||
@Suppress("SameParameterValue", "UNUSED_PARAMETER")
|
||||
fun prepareBgData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
maxBgValue = Double.MIN_VALUE
|
||||
bgReadingsArray = repository.compatGetBgReadingsDataFromTime(fromTime, toTime, false).blockingGet()
|
||||
val bgListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
for (bg in bgReadingsArray) {
|
||||
if (bg.timestamp < fromTime || bg.timestamp > toTime) continue
|
||||
if (bg.value > maxBgValue) maxBgValue = bg.value
|
||||
bgListArray.add(GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh))
|
||||
}
|
||||
bgListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
||||
bgReadingGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
||||
maxBgValue = Profile.fromMgdlToUnits(maxBgValue, profileFunction.getUnits())
|
||||
if (defaultValueHelper.determineHighLine() > maxBgValue) maxBgValue = defaultValueHelper.determineHighLine()
|
||||
maxBgValue = addUpperChartMargin(maxBgValue)
|
||||
// profiler.log(LTag.UI, "prepareBgData() $from", start)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Synchronized
|
||||
fun preparePredictions(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
val apsResult = if (config.APS) loop.lastRun?.constraintsProcessed else nsDeviceStatus.getAPSResult(injector)
|
||||
val predictionsAvailable = if (config.APS) loop.lastRun?.request?.hasPredictions == true else config.NSCLIENT
|
||||
val menuChartSettings = overviewMenus.setting
|
||||
// align to hours
|
||||
val calendar = Calendar.getInstance().also {
|
||||
it.timeInMillis = System.currentTimeMillis()
|
||||
it[Calendar.MILLISECOND] = 0
|
||||
it[Calendar.SECOND] = 0
|
||||
it[Calendar.MINUTE] = 0
|
||||
it.add(Calendar.HOUR, 1)
|
||||
}
|
||||
if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) {
|
||||
var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt()
|
||||
predictionHours = min(2, predictionHours)
|
||||
predictionHours = max(0, predictionHours)
|
||||
val hoursToFetch = rangeToDisplay - predictionHours
|
||||
toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
||||
fromTime = toTime - T.hours(hoursToFetch.toLong()).msecs()
|
||||
endTime = toTime + T.hours(predictionHours.toLong()).msecs()
|
||||
} else {
|
||||
toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
||||
fromTime = toTime - T.hours(rangeToDisplay.toLong()).msecs()
|
||||
endTime = toTime
|
||||
}
|
||||
|
||||
val bgListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
val predictions: MutableList<GlucoseValueDataPoint>? = apsResult?.predictions
|
||||
?.map { bg -> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh) }
|
||||
?.toMutableList()
|
||||
if (predictions != null) {
|
||||
predictions.sortWith { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }
|
||||
for (prediction in predictions) if (prediction.data.value >= 40) bgListArray.add(prediction)
|
||||
}
|
||||
predictionsGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
||||
// profiler.log(LTag.UI, "preparePredictions() $from", start)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Suppress("SameParameterValue", "UNUSED_PARAMETER")
|
||||
fun prepareBucketedData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
val bucketedData = iobCobCalculator.ads.getBucketedDataTableCopy() ?: return
|
||||
if (bucketedData.isEmpty()) {
|
||||
aapsLogger.debug("No bucketed data.")
|
||||
return
|
||||
}
|
||||
val bucketedListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
for (inMemoryGlucoseValue in bucketedData) {
|
||||
if (inMemoryGlucoseValue.timestamp < fromTime || inMemoryGlucoseValue.timestamp > toTime) continue
|
||||
bucketedListArray.add(InMemoryGlucoseValueDataPoint(inMemoryGlucoseValue, profileFunction, rh))
|
||||
}
|
||||
bucketedListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
||||
bucketedGraphSeries = PointsWithLabelGraphSeries(Array(bucketedListArray.size) { i -> bucketedListArray[i] })
|
||||
// profiler.log(LTag.UI, "prepareBucketedData() $from", start)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Synchronized
|
||||
fun prepareBasalData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
maxBasalValueFound = 0.0
|
||||
val baseBasalArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val tempBasalArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val basalLineArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val absoluteBasalLineArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
var lastLineBasal = 0.0
|
||||
var lastAbsoluteLineBasal = -1.0
|
||||
var lastBaseBasal = 0.0
|
||||
var lastTempBasal = 0.0
|
||||
var time = fromTime
|
||||
while (time < toTime) {
|
||||
val profile = profileFunction.getProfile(time)
|
||||
if (profile == null) {
|
||||
time += 60 * 1000L
|
||||
continue
|
||||
}
|
||||
val basalData = iobCobCalculator.getBasalData(profile, time)
|
||||
val baseBasalValue = basalData.basal
|
||||
var absoluteLineValue = baseBasalValue
|
||||
var tempBasalValue = 0.0
|
||||
var basal = 0.0
|
||||
if (basalData.isTempBasalRunning) {
|
||||
tempBasalValue = basalData.tempBasalAbsolute
|
||||
absoluteLineValue = tempBasalValue
|
||||
if (tempBasalValue != lastTempBasal) {
|
||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(time, tempBasalValue.also { basal = it }, basalScale))
|
||||
}
|
||||
if (lastBaseBasal != 0.0) {
|
||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(time, 0.0, basalScale))
|
||||
lastBaseBasal = 0.0
|
||||
}
|
||||
} else {
|
||||
if (baseBasalValue != lastBaseBasal) {
|
||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(time, baseBasalValue.also { basal = it }, basalScale))
|
||||
lastBaseBasal = baseBasalValue
|
||||
}
|
||||
if (lastTempBasal != 0.0) {
|
||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(time, 0.0, basalScale))
|
||||
}
|
||||
}
|
||||
if (baseBasalValue != lastLineBasal) {
|
||||
basalLineArray.add(ScaledDataPoint(time, lastLineBasal, basalScale))
|
||||
basalLineArray.add(ScaledDataPoint(time, baseBasalValue, basalScale))
|
||||
}
|
||||
if (absoluteLineValue != lastAbsoluteLineBasal) {
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(time, lastAbsoluteLineBasal, basalScale))
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(time, basal, basalScale))
|
||||
}
|
||||
lastAbsoluteLineBasal = absoluteLineValue
|
||||
lastLineBasal = baseBasalValue
|
||||
lastTempBasal = tempBasalValue
|
||||
maxBasalValueFound = max(maxBasalValueFound, max(tempBasalValue, baseBasalValue))
|
||||
time += 60 * 1000L
|
||||
}
|
||||
|
||||
// final points
|
||||
basalLineArray.add(ScaledDataPoint(toTime, lastLineBasal, basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(toTime, lastBaseBasal, basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(toTime, lastTempBasal, basalScale))
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(toTime, lastAbsoluteLineBasal, basalScale))
|
||||
|
||||
// create series
|
||||
baseBasalGraphSeries = LineGraphSeries(Array(baseBasalArray.size) { i -> baseBasalArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = rh.gc(R.color.basebasal)
|
||||
it.thickness = 0
|
||||
}
|
||||
tempBasalGraphSeries = LineGraphSeries(Array(tempBasalArray.size) { i -> tempBasalArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = rh.gc(R.color.tempbasal)
|
||||
it.thickness = 0
|
||||
}
|
||||
basalLineGraphSeries = LineGraphSeries(Array(basalLineArray.size) { i -> basalLineArray[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(2f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.basal)
|
||||
})
|
||||
}
|
||||
absoluteBasalGraphSeries = LineGraphSeries(Array(absoluteBasalLineArray.size) { i -> absoluteBasalLineArray[i] }).also {
|
||||
it.setCustomPaint(Paint().also { absolutePaint ->
|
||||
absolutePaint.style = Paint.Style.STROKE
|
||||
absolutePaint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
||||
absolutePaint.color = rh.gc(R.color.basal)
|
||||
})
|
||||
}
|
||||
// profiler.log(LTag.UI, "prepareBasalData() $from", start)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Synchronized
|
||||
fun prepareTemporaryTargetData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
val profile = profileFunction.getProfile() ?: return
|
||||
val units = profileFunction.getUnits()
|
||||
var toTime = toTime
|
||||
val targetsSeriesArray: MutableList<DataPoint> = java.util.ArrayList()
|
||||
var lastTarget = -1.0
|
||||
loop.lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) }
|
||||
var time = fromTime
|
||||
while (time < toTime) {
|
||||
val tt = repository.getTemporaryTargetActiveAt(time).blockingGet()
|
||||
val value: Double = if (tt is ValueWrapper.Existing) {
|
||||
Profile.fromMgdlToUnits(tt.value.target(), units)
|
||||
} else {
|
||||
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
|
||||
}
|
||||
if (lastTarget != value) {
|
||||
if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget))
|
||||
targetsSeriesArray.add(DataPoint(time.toDouble(), value))
|
||||
}
|
||||
lastTarget = value
|
||||
time += 5 * 60 * 1000L
|
||||
}
|
||||
// final point
|
||||
targetsSeriesArray.add(DataPoint(toTime.toDouble(), lastTarget))
|
||||
// create series
|
||||
temporaryTargetSeries = LineGraphSeries(Array(targetsSeriesArray.size) { i -> targetsSeriesArray[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.tempTargetBackground)
|
||||
it.thickness = 2
|
||||
}
|
||||
// profiler.log(LTag.UI, "prepareTemporaryTargetData() $from", start)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Synchronized
|
||||
fun prepareTreatmentsData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
maxTreatmentsValue = 0.0
|
||||
val filteredTreatments: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
repository.getBolusesDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
||||
.map { BolusDataPoint(it, rh, activePlugin, defaultValueHelper) }
|
||||
.filter { it.data.type == Bolus.Type.NORMAL || it.data.type == Bolus.Type.SMB }
|
||||
.forEach {
|
||||
it.y = getNearestBg(it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
repository.getCarbsDataFromTimeToTimeExpanded(fromTime, endTime, true).blockingGet()
|
||||
.map { CarbsDataPoint(it, rh) }
|
||||
.forEach {
|
||||
it.y = getNearestBg(it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
|
||||
// ProfileSwitch
|
||||
repository.getEffectiveProfileSwitchDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
||||
.map { EffectiveProfileSwitchDataPoint(it,rh) }
|
||||
.forEach(filteredTreatments::add)
|
||||
|
||||
// OfflineEvent
|
||||
repository.getOfflineEventDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
||||
.map {
|
||||
TherapyEventDataPoint(
|
||||
TherapyEvent(timestamp = it.timestamp, duration = it.duration, type = TherapyEvent.Type.APS_OFFLINE, glucoseUnit = TherapyEvent.GlucoseUnit.MMOL),
|
||||
rh,
|
||||
profileFunction,
|
||||
translator
|
||||
)
|
||||
}
|
||||
.forEach(filteredTreatments::add)
|
||||
|
||||
// Extended bolus
|
||||
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
||||
repository.getExtendedBolusDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
||||
.map { ExtendedBolusDataPoint(it, rh) }
|
||||
.filter { it.duration != 0L }
|
||||
.forEach {
|
||||
it.y = getNearestBg(it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Careportal
|
||||
repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet()
|
||||
.map { TherapyEventDataPoint(it, rh, profileFunction, translator) }
|
||||
.filterTimeframe(fromTime, endTime)
|
||||
.forEach {
|
||||
if (it.y == 0.0) it.y = getNearestBg(it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
|
||||
// increase maxY if a treatment forces it's own height that's higher than a BG value
|
||||
filteredTreatments.map { it.y }
|
||||
.maxOrNull()
|
||||
?.let(::addUpperChartMargin)
|
||||
?.let { maxTreatmentsValue = maxOf(maxTreatmentsValue, it) }
|
||||
|
||||
treatmentsSeries = PointsWithLabelGraphSeries(filteredTreatments.toTypedArray())
|
||||
// profiler.log(LTag.UI, "prepareTreatmentsData() $from", start)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Synchronized
|
||||
fun prepareIobAutosensData(from: String) {
|
||||
// val start = dateUtil.now()
|
||||
val iobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val absIobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
maxIobValueFound = Double.MIN_VALUE
|
||||
var lastIob = 0.0
|
||||
var absLastIob = 0.0
|
||||
var time = fromTime
|
||||
|
||||
val minFailOverActiveList: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
val cobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
maxCobValueFound = Double.MIN_VALUE
|
||||
var lastCob = 0
|
||||
|
||||
val actArrayHist: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val actArrayPrediction: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val now = dateUtil.now().toDouble()
|
||||
maxIAValue = 0.0
|
||||
|
||||
val bgiArrayHist: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val bgiArrayPrediction: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
maxBGIValue = Double.MIN_VALUE
|
||||
|
||||
val devArray: MutableList<OverviewPlugin.DeviationDataPoint> = java.util.ArrayList()
|
||||
maxDevValueFound = Double.MIN_VALUE
|
||||
|
||||
val ratioArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105%
|
||||
minRatioValueFound = -5.0
|
||||
|
||||
val dsMaxArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
val dsMinArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
||||
maxFromMaxValueFound = Double.MIN_VALUE
|
||||
maxFromMinValueFound = Double.MIN_VALUE
|
||||
|
||||
val adsData = iobCobCalculator.ads.clone()
|
||||
|
||||
while (time <= toTime) {
|
||||
val profile = profileFunction.getProfile(time)
|
||||
if (profile == null) {
|
||||
time += 5 * 60 * 1000L
|
||||
continue
|
||||
}
|
||||
// IOB
|
||||
val iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
|
||||
val baseBasalIob = iobCobCalculator.calculateAbsoluteIobFromBaseBasals(time)
|
||||
val absIob = IobTotal.combine(iob, baseBasalIob)
|
||||
val autosensData = adsData.getAutosensDataAtTime(time)
|
||||
if (abs(lastIob - iob.iob) > 0.02) {
|
||||
if (abs(lastIob - iob.iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
|
||||
iobArray.add(ScaledDataPoint(time, iob.iob, iobScale))
|
||||
maxIobValueFound = maxOf(maxIobValueFound, abs(iob.iob))
|
||||
lastIob = iob.iob
|
||||
}
|
||||
if (abs(absLastIob - absIob.iob) > 0.02) {
|
||||
if (abs(absLastIob - absIob.iob) > 0.2) absIobArray.add(ScaledDataPoint(time, absLastIob, iobScale))
|
||||
absIobArray.add(ScaledDataPoint(time, absIob.iob, iobScale))
|
||||
maxIobValueFound = maxOf(maxIobValueFound, abs(absIob.iob))
|
||||
absLastIob = absIob.iob
|
||||
}
|
||||
|
||||
// COB
|
||||
if (autosensData != null) {
|
||||
val cob = autosensData.cob.toInt()
|
||||
if (cob != lastCob) {
|
||||
if (autosensData.carbsFromBolus > 0) cobArray.add(ScaledDataPoint(time, lastCob.toDouble(), cobScale))
|
||||
cobArray.add(ScaledDataPoint(time, cob.toDouble(), cobScale))
|
||||
maxCobValueFound = max(maxCobValueFound, cob.toDouble())
|
||||
lastCob = cob
|
||||
}
|
||||
if (autosensData.failOverToMinAbsorptionRate) {
|
||||
autosensData.scale = cobScale
|
||||
autosensData.chartTime = time
|
||||
minFailOverActiveList.add(autosensData)
|
||||
}
|
||||
}
|
||||
|
||||
// ACTIVITY
|
||||
if (time <= now) actArrayHist.add(ScaledDataPoint(time, iob.activity, actScale))
|
||||
else actArrayPrediction.add(ScaledDataPoint(time, iob.activity, actScale))
|
||||
maxIAValue = max(maxIAValue, abs(iob.activity))
|
||||
|
||||
// BGI
|
||||
val devBgiScale = overviewMenus.isEnabledIn(OverviewMenus.CharType.DEV) == overviewMenus.isEnabledIn(OverviewMenus.CharType.BGI)
|
||||
val deviation = if (devBgiScale) autosensData?.deviation ?: 0.0 else 0.0
|
||||
val bgi: Double = iob.activity * profile.getIsfMgdl(time) * 5.0
|
||||
if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, bgiScale))
|
||||
else bgiArrayPrediction.add(ScaledDataPoint(time, bgi, bgiScale))
|
||||
maxBGIValue = max(maxBGIValue, max(abs(bgi), deviation))
|
||||
|
||||
// DEVIATIONS
|
||||
if (autosensData != null) {
|
||||
var color = rh.gc(R.color.deviationblack) // "="
|
||||
if (autosensData.type == "" || autosensData.type == "non-meal") {
|
||||
if (autosensData.pastSensitivity == "C") color = rh.gc(R.color.deviationgrey)
|
||||
if (autosensData.pastSensitivity == "+") color = rh.gc(R.color.deviationgreen)
|
||||
if (autosensData.pastSensitivity == "-") color = rh.gc(R.color.deviationred)
|
||||
} else if (autosensData.type == "uam") {
|
||||
color = rh.gc(R.color.uam)
|
||||
} else if (autosensData.type == "csf") {
|
||||
color = rh.gc(R.color.deviationgrey)
|
||||
}
|
||||
devArray.add(OverviewPlugin.DeviationDataPoint(time.toDouble(), autosensData.deviation, color, devScale))
|
||||
maxDevValueFound = maxOf(maxDevValueFound, abs(autosensData.deviation), abs(bgi))
|
||||
}
|
||||
|
||||
// RATIO
|
||||
if (autosensData != null) {
|
||||
ratioArray.add(ScaledDataPoint(time, 100.0 * (autosensData.autosensResult.ratio - 1), ratioScale))
|
||||
maxRatioValueFound = max(maxRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
||||
minRatioValueFound = min(minRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
||||
}
|
||||
|
||||
// DEV SLOPE
|
||||
if (autosensData != null) {
|
||||
dsMaxArray.add(ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale))
|
||||
dsMinArray.add(ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale))
|
||||
maxFromMaxValueFound = max(maxFromMaxValueFound, abs(autosensData.slopeFromMaxDeviation))
|
||||
maxFromMinValueFound = max(maxFromMinValueFound, abs(autosensData.slopeFromMinDeviation))
|
||||
}
|
||||
|
||||
time += 5 * 60 * 1000L
|
||||
}
|
||||
// IOB
|
||||
iobSeries = FixedLineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
||||
it.color = rh.gc(R.color.iob)
|
||||
it.thickness = 3
|
||||
}
|
||||
absIobSeries = FixedLineGraphSeries(Array(absIobArray.size) { i -> absIobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
||||
it.color = rh.gc(R.color.iob)
|
||||
it.thickness = 3
|
||||
}
|
||||
|
||||
if (overviewMenus.setting[0][OverviewMenus.CharType.PRE.ordinal]) {
|
||||
val autosensData = adsData.getLastAutosensData("GraphData", aapsLogger, dateUtil)
|
||||
val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult()
|
||||
val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
|
||||
val iobPrediction: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
val iobPredictionArray = iobCobCalculator.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
||||
for (i in iobPredictionArray) {
|
||||
iobPrediction.add(i.setColor(rh.gc(R.color.iobPredAS)))
|
||||
maxIobValueFound = max(maxIobValueFound, abs(i.iob))
|
||||
}
|
||||
iobPredictions1Series = PointsWithLabelGraphSeries(Array(iobPrediction.size) { i -> iobPrediction[i] })
|
||||
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray))
|
||||
/*
|
||||
val iobPrediction2: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
||||
val iobPredictionArray2 = iobCobCalculator.calculateIobArrayForSMB(AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
||||
for (i in iobPredictionArray2) {
|
||||
iobPrediction2.add(i.setColor(rh.gc(R.color.iobPred)))
|
||||
maxIobValueFound = max(maxIobValueFound, abs(i.iob))
|
||||
}
|
||||
iobPredictions2Series = PointsWithLabelGraphSeries(Array(iobPrediction2.size) { i -> iobPrediction2[i] })
|
||||
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(1.0) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray2))
|
||||
*/
|
||||
} else {
|
||||
iobPredictions1Series = PointsWithLabelGraphSeries()
|
||||
//iobPredictions2Series = PointsWithLabelGraphSeries()
|
||||
}
|
||||
|
||||
// COB
|
||||
cobSeries = FixedLineGraphSeries(Array(cobArray.size) { i -> cobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.cob) //50%
|
||||
it.color = rh.gc(R.color.cob)
|
||||
it.thickness = 3
|
||||
}
|
||||
cobMinFailOverSeries = PointsWithLabelGraphSeries(Array(minFailOverActiveList.size) { i -> minFailOverActiveList[i] })
|
||||
|
||||
// ACTIVITY
|
||||
activitySeries = FixedLineGraphSeries(Array(actArrayHist.size) { i -> actArrayHist[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.activity)
|
||||
it.thickness = 3
|
||||
}
|
||||
activityPredictionSeries = FixedLineGraphSeries(Array(actArrayPrediction.size) { i -> actArrayPrediction[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = 3f
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.activity)
|
||||
})
|
||||
}
|
||||
|
||||
// BGI
|
||||
minusBgiSeries = FixedLineGraphSeries(Array(bgiArrayHist.size) { i -> bgiArrayHist[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.bgi)
|
||||
it.thickness = 3
|
||||
}
|
||||
minusBgiHistSeries = FixedLineGraphSeries(Array(bgiArrayPrediction.size) { i -> bgiArrayPrediction[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = 3f
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.bgi)
|
||||
})
|
||||
}
|
||||
|
||||
// DEVIATIONS
|
||||
deviationsSeries = BarGraphSeries(Array(devArray.size) { i -> devArray[i] }).also {
|
||||
it.setValueDependentColor { data: OverviewPlugin.DeviationDataPoint -> data.color }
|
||||
}
|
||||
|
||||
// RATIO
|
||||
ratioSeries = LineGraphSeries(Array(ratioArray.size) { i -> ratioArray[i] }).also {
|
||||
it.color = rh.gc(R.color.ratio)
|
||||
it.thickness = 3
|
||||
}
|
||||
|
||||
// DEV SLOPE
|
||||
dsMaxSeries = LineGraphSeries(Array(dsMaxArray.size) { i -> dsMaxArray[i] }).also {
|
||||
it.color = rh.gc(R.color.devslopepos)
|
||||
it.thickness = 3
|
||||
}
|
||||
dsMinSeries = LineGraphSeries(Array(dsMinArray.size) { i -> dsMinArray[i] }).also {
|
||||
it.color = rh.gc(R.color.devslopeneg)
|
||||
it.thickness = 3
|
||||
}
|
||||
|
||||
// profiler.log(LTag.UI, "prepareIobAutosensData() $from", start)
|
||||
}
|
||||
|
||||
private fun addUpperChartMargin(maxBgValue: Double) =
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4
|
||||
|
||||
private fun getNearestBg(date: Long): Double {
|
||||
bgReadingsArray.let { bgReadingsArray ->
|
||||
for (reading in bgReadingsArray) {
|
||||
if (reading.timestamp > date) continue
|
||||
return Profile.fromMgdlToUnits(reading.value, profileFunction.getUnits())
|
||||
}
|
||||
return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].value, profileFunction.getUnits())
|
||||
else Profile.fromMgdlToUnits(100.0, profileFunction.getUnits())
|
||||
}
|
||||
}
|
||||
|
||||
private fun <E : DataPointWithLabelInterface> List<E>.filterTimeframe(fromTime: Long, endTime: Long): List<E> =
|
||||
filter { it.x + it.duration >= fromTime && it.x <= endTime }
|
||||
|
||||
}
|
||||
|
|
|
@ -36,13 +36,9 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
|||
import info.nightscout.androidaps.database.interfaces.end
|
||||
import info.nightscout.androidaps.databinding.OverviewFragmentBinding
|
||||
import info.nightscout.androidaps.dialogs.*
|
||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.extensions.directionToIcon
|
||||
import info.nightscout.androidaps.extensions.isInProgress
|
||||
import info.nightscout.androidaps.extensions.runOnUiThread
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
|
@ -188,10 +184,6 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
overviewData.rangeToDisplay += 6
|
||||
overviewData.rangeToDisplay = if (overviewData.rangeToDisplay > 24) 6 else overviewData.rangeToDisplay
|
||||
sp.putInt(R.string.key_rangetodisplay, overviewData.rangeToDisplay)
|
||||
overviewData.initRange()
|
||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
||||
updateGraph("rangeChange")
|
||||
rxBus.send(EventPreferenceChange(rh, R.string.key_rangetodisplay))
|
||||
sp.putBoolean(R.string.key_objectiveusescale, true)
|
||||
false
|
||||
|
@ -227,113 +219,106 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
@Synchronized
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewTime::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTime(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewCalcProgress::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateCalcProgress(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewProfile::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateProfile(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewTemporaryBasal::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTemporaryBasal(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewExtendedBolus::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateExtendedBolus(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewTemporaryTarget::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTemporaryTarget(it.from) }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewBg::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateBg(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updateCalcProgress() }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewIobCob::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateIobCob(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updateIobCob() }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewSensitivity::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateSensitivity(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updateSensitivity() }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewGraph::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateGraph(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updateGraph() }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewPumpStatus::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updatePumpStatus(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updatePumpStatus() }, fabricPrivacy::logException)
|
||||
disposable += activePlugin.activeOverview.overviewBus
|
||||
.toObservable(EventUpdateOverviewNotification::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateNotification(it.from) }, fabricPrivacy::logException)
|
||||
.subscribe({ updateNotification() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventNewBG::class.java)
|
||||
.debounce(1L, TimeUnit.SECONDS)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateBg() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
if (it.now) overviewPlugin.refreshLoop(it.from)
|
||||
else scheduleUpdateGUI(it.from)
|
||||
if (it.now) refreshAll()
|
||||
else scheduleUpdateGUI()
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAcceptOpenLoopChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ scheduleUpdateGUI("EventAcceptOpenLoopChange") }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventInitializationChanged::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTime("EventInitializationChanged") }, fabricPrivacy::logException)
|
||||
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ scheduleUpdateGUI("EventPreferenceChange") }, fabricPrivacy::logException)
|
||||
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventNewOpenLoopNotification::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ scheduleUpdateGUI("EventNewOpenLoopNotification") }, fabricPrivacy::logException)
|
||||
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventPumpStatusChanged::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.delay(30, TimeUnit.MILLISECONDS, aapsSchedulers.main)
|
||||
.subscribe({
|
||||
overviewData.pumpStatus = it.getStatus(rh)
|
||||
updatePumpStatus("EventPumpStatusChanged")
|
||||
updatePumpStatus()
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateProfile() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempTargetChange::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTemporaryTarget() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateExtendedBolus() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ updateTemporaryBasal() }, fabricPrivacy::logException)
|
||||
|
||||
refreshLoop = Runnable {
|
||||
overviewPlugin.refreshLoop("refreshLoop")
|
||||
refreshAll()
|
||||
handler.postDelayed(refreshLoop, 60 * 1000L)
|
||||
}
|
||||
handler.postDelayed(refreshLoop, 60 * 1000L)
|
||||
|
||||
updateTime("onResume")
|
||||
updateCalcProgress("onResume")
|
||||
updateProfile("onResume")
|
||||
updateTemporaryBasal("onResume")
|
||||
updateExtendedBolus("onResume")
|
||||
updateTemporaryTarget("onResume")
|
||||
updateBg("onResume")
|
||||
updateIobCob("onResume")
|
||||
updateSensitivity("onResume")
|
||||
updateGraph("onResume")
|
||||
updatePumpStatus("onResume")
|
||||
updateNotification("onResume")
|
||||
refreshAll()
|
||||
updatePumpStatus()
|
||||
updateCalcProgress()
|
||||
}
|
||||
|
||||
fun refreshAll() {
|
||||
runOnUiThread {
|
||||
updateBg()
|
||||
updateTime()
|
||||
updateProfile()
|
||||
updateTemporaryBasal()
|
||||
updateExtendedBolus()
|
||||
updateTemporaryTarget()
|
||||
updateIobCob()
|
||||
updateSensitivity()
|
||||
updateGraph()
|
||||
updateNotification()
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -752,11 +737,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
|
||||
var task: Runnable? = null
|
||||
|
||||
private fun scheduleUpdateGUI(from: String) {
|
||||
private fun scheduleUpdateGUI() {
|
||||
class UpdateRunnable : Runnable {
|
||||
|
||||
override fun run() {
|
||||
overviewPlugin.refreshLoop(from)
|
||||
refreshAll()
|
||||
task = null
|
||||
}
|
||||
}
|
||||
|
@ -766,8 +751,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateBg(from: String) {
|
||||
fun updateBg() {
|
||||
val units = profileFunction.getUnits()
|
||||
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
|
||||
?: rh.gs(R.string.notavailable)
|
||||
|
@ -816,8 +800,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateProfile(from: String) {
|
||||
fun updateProfile() {
|
||||
val profileBackgroundColor =
|
||||
profileFunction.getProfile()?.let {
|
||||
if (it is ProfileSealed.EPS) {
|
||||
|
@ -849,28 +832,25 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
binding.activeProfile.setTextColor(profileTextColor)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateTemporaryBasal(from: String) {
|
||||
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText
|
||||
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor)
|
||||
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon)
|
||||
private fun updateTemporaryBasal() {
|
||||
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText(iobCobCalculator)
|
||||
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor(context, iobCobCalculator))
|
||||
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon(iobCobCalculator))
|
||||
binding.infoLayout.basalLayout.setOnClickListener {
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText) }
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText(iobCobCalculator)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateExtendedBolus(from: String) {
|
||||
private fun updateExtendedBolus() {
|
||||
val pump = activePlugin.activePump
|
||||
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText
|
||||
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText(iobCobCalculator)
|
||||
binding.infoLayout.extendedLayout.setOnClickListener {
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText) }
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText(iobCobCalculator)) }
|
||||
}
|
||||
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateTime(from: String) {
|
||||
fun updateTime() {
|
||||
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
|
||||
// Status lights
|
||||
val pump = activePlugin.activePump
|
||||
|
@ -901,14 +881,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
processAps()
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateIobCob(from: String) {
|
||||
binding.infoLayout.iob.text = overviewData.iobText
|
||||
fun updateIobCob() {
|
||||
binding.infoLayout.iob.text = overviewData.iobText(iobCobCalculator)
|
||||
binding.infoLayout.iobLayout.setOnClickListener {
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText) }
|
||||
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText(iobCobCalculator)) }
|
||||
}
|
||||
// cob
|
||||
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
|
||||
var cobText = overviewData.cobInfo(iobCobCalculator).displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
|
||||
|
||||
val constraintsProcessed = loop.lastRun?.constraintsProcessed
|
||||
val lastRun = loop.lastRun
|
||||
|
@ -929,10 +908,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateTemporaryTarget(from: String) {
|
||||
fun updateTemporaryTarget() {
|
||||
val units = profileFunction.getUnits()
|
||||
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
|
||||
val tempTarget = overviewData.temporaryTarget
|
||||
if (tempTarget != null) {
|
||||
binding.tempTarget.setTextColor(rh.gac(context, R.attr.ribbonTextWarningColor))
|
||||
|
@ -957,8 +934,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateGraph(from: String) {
|
||||
private fun updateGraph() {
|
||||
val pump = activePlugin.activePump
|
||||
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
|
||||
val menuChartSettings = overviewMenus.setting
|
||||
|
@ -1036,14 +1012,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateCalcProgress(from: String) {
|
||||
private fun updateCalcProgress() {
|
||||
binding.progressBar.progress = overviewData.calcProgressPct
|
||||
binding.progressBar.visibility = (overviewData.calcProgressPct != 100).toVisibility()
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateSensitivity(from: String) {
|
||||
private fun updateSensitivity() {
|
||||
if (sp.getBoolean(R.string.key_openapsama_useautosens, false) && constraintChecker.isAutosensModeEnabled().value()) {
|
||||
binding.infoLayout.sensitivityIcon.setImageResource(R.drawable.ic_swap_vert_black_48dp_green)
|
||||
} else {
|
||||
|
@ -1051,20 +1025,18 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
}
|
||||
|
||||
binding.infoLayout.sensitivity.text =
|
||||
overviewData.lastAutosensData?.let { autosensData ->
|
||||
overviewData.lastAutosensData(iobCobCalculator)?.let { autosensData ->
|
||||
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updatePumpStatus(from: String) {
|
||||
private fun updatePumpStatus() {
|
||||
val status = overviewData.pumpStatus
|
||||
binding.pumpStatus.text = status
|
||||
binding.pumpStatusLayout.visibility = (status != "").toVisibility()
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun updateNotification(from: String) {
|
||||
private fun updateNotification() {
|
||||
binding.notifications.let { notificationStore.updateNotifications(it) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,25 +4,26 @@ import androidx.preference.PreferenceFragmentCompat
|
|||
import androidx.preference.SwitchPreference
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||
import info.nightscout.androidaps.extensions.*
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.Overview
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.*
|
||||
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.events.EventUpdateOverviewCalcProgress
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewNotification
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventBucketedDataCreated
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
|
@ -41,9 +42,6 @@ class OverviewPlugin @Inject constructor(
|
|||
private val aapsSchedulers: AapsSchedulers,
|
||||
rh: ResourceHelper,
|
||||
private val config: Config,
|
||||
private val dateUtil: DateUtil,
|
||||
private val iobCobCalculator: IobCobCalculator,
|
||||
private val repository: AppRepository,
|
||||
private val overviewData: OverviewData,
|
||||
private val overviewMenus: OverviewMenus
|
||||
) : PluginBase(
|
||||
|
@ -89,62 +87,9 @@ class OverviewPlugin @Inject constructor(
|
|||
disposable += rxBus
|
||||
.toObservable(EventIobCalculationProgress::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ overviewData.calcProgressPct = it.progressPct; overviewBus.send(EventUpdateOverviewCalcProgress("EventIobCalculationProgress")) }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ overviewBus.send(EventUpdateOverviewTemporaryBasal("EventTempBasalChange")) }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ overviewBus.send(EventUpdateOverviewExtendedBolus("EventExtendedBolusChange")) }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventNewBG::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ loadBg("EventNewBG") }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempTargetChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ loadTemporaryTarget("EventTempTargetChange") }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
loadIobCobResults("EventTreatmentChange")
|
||||
overviewData.prepareTreatmentsData("EventTreatmentChange")
|
||||
overviewBus.send(EventUpdateOverviewGraph("EventTreatmentChange"))
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTherapyEventChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
overviewData.prepareTreatmentsData("EventTherapyEventChange")
|
||||
overviewBus.send(EventUpdateOverviewGraph("EventTherapyEventChange"))
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventBucketedDataCreated::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
||||
overviewBus.send(EventUpdateOverviewGraph("EventBucketedDataCreated"))
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventLoopInvoked::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ overviewData.preparePredictions("EventLoopInvoked") }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
loadProfile("EventEffectiveProfileSwitchChanged")
|
||||
overviewData.prepareBasalData("EventEffectiveProfileSwitchChanged")
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
if (it.cause !is EventCustomCalculationFinished) refreshLoop("EventAutosensCalculationFinished")
|
||||
overviewData.calcProgressPct = it.pass.finalPercent(it.progressPct)
|
||||
overviewBus.send(EventUpdateOverviewCalcProgress("EventIobCalculationProgress"))
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventPumpStatusChanged::class.java)
|
||||
|
@ -152,20 +97,7 @@ class OverviewPlugin @Inject constructor(
|
|||
.subscribe({
|
||||
overviewData.pumpStatus = it.getStatus(rh)
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ event ->
|
||||
if (event.isChanged(rh, R.string.key_units)) {
|
||||
overviewData.reset()
|
||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
||||
overviewBus.send(EventUpdateOverviewGraph("EventBucketedDataCreated"))
|
||||
loadAll("EventPreferenceChange")
|
||||
}
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
Thread { loadAll("onResume") }.start()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -243,7 +175,7 @@ class OverviewPlugin @Inject constructor(
|
|||
.storeDouble(R.string.key_statuslights_bat_critical, sp, rh)
|
||||
.storeInt(R.string.key_boluswizard_percentage, sp, rh)
|
||||
}
|
||||
|
||||
/*
|
||||
@Volatile
|
||||
var runningRefresh = false
|
||||
override fun refreshLoop(from: String) {
|
||||
|
@ -284,38 +216,5 @@ class OverviewPlugin @Inject constructor(
|
|||
overviewBus.send(EventUpdateOverviewGraph(from))
|
||||
aapsLogger.debug(LTag.UI, "loadAll finished")
|
||||
}
|
||||
|
||||
private fun loadProfile(from: String) {
|
||||
overviewBus.send(EventUpdateOverviewProfile(from))
|
||||
}
|
||||
|
||||
private fun loadTemporaryTarget(from: String) {
|
||||
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
||||
if (tempTarget is ValueWrapper.Existing) overviewData.temporaryTarget = tempTarget.value
|
||||
else overviewData.temporaryTarget = null
|
||||
overviewBus.send(EventUpdateOverviewTemporaryTarget(from))
|
||||
}
|
||||
|
||||
private fun loadAsData(from: String) {
|
||||
overviewData.lastAutosensData = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
|
||||
overviewBus.send(EventUpdateOverviewSensitivity(from))
|
||||
}
|
||||
|
||||
private fun loadBg(from: String) {
|
||||
val gvWrapped = repository.getLastGlucoseValueWrapped().blockingGet()
|
||||
if (gvWrapped is ValueWrapper.Existing) overviewData.lastBg = gvWrapped.value
|
||||
else overviewData.lastBg = null
|
||||
overviewBus.send(EventUpdateOverviewBg(from))
|
||||
}
|
||||
|
||||
private fun loadIobCobResults(from: String) {
|
||||
overviewData.bolusIob = iobCobCalculator.calculateIobFromBolus().round()
|
||||
overviewData.basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
|
||||
overviewData.cobInfo = iobCobCalculator.getCobInfo(true, "Overview COB")
|
||||
val lastCarbs = repository.getLastCarbsRecordWrapped().blockingGet()
|
||||
overviewData.lastCarbsTime = if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
|
||||
|
||||
overviewBus.send(EventUpdateOverviewIobCob(from))
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewBg(val from: String) : Event()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewExtendedBolus(val from: String) : Event()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewProfile(val from: String) : Event()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewTemporaryBasal(val from: String) : Event()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewTemporaryTarget(val from: String) : Event()
|
|
@ -1,5 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventUpdateOverviewTime(val from: String) : Event()
|
|
@ -9,17 +9,20 @@ import androidx.core.app.RemoteInput
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.extensions.toStringShort
|
||||
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import javax.inject.Inject
|
||||
|
@ -72,26 +75,10 @@ class PersistentNotificationPlugin @Inject constructor(
|
|||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventTreatmentChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventInitializationChanged::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
||||
|
||||
import android.content.Context
|
||||
import android.os.SystemClock
|
||||
import androidx.collection.LongSparseArray
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
|
@ -24,21 +18,19 @@ import info.nightscout.androidaps.extensions.convertedToAbsolute
|
|||
import info.nightscout.androidaps.extensions.iobCalc
|
||||
import info.nightscout.androidaps.extensions.toTemporaryBasal
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
|
@ -63,14 +55,11 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
rh: ResourceHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val activePlugin: ActivePlugin,
|
||||
private val sensitivityOref1Plugin: SensitivityOref1Plugin,
|
||||
private val sensitivityAAPSPlugin: SensitivityAAPSPlugin,
|
||||
private val sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
|
||||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val dateUtil: DateUtil,
|
||||
private val repository: AppRepository,
|
||||
private val context: Context,
|
||||
private val dataWorker: DataWorker
|
||||
val overviewData: OverviewData,
|
||||
private val calculationWorkflow: CalculationWorkflow
|
||||
) : PluginBase(
|
||||
PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
|
@ -91,8 +80,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
private val dataLock = Any()
|
||||
private var thread: Thread? = null
|
||||
|
||||
private val jobGroupName = "calculation"
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// EventConfigBuilderChange
|
||||
|
@ -126,14 +113,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
resetDataAndRunCalculation("onEventPreferenceChange", event)
|
||||
}
|
||||
}, fabricPrivacy::logException)
|
||||
// EventAppInitialized
|
||||
disposable += rxBus
|
||||
.toObservable(EventAppInitialized::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe(
|
||||
{ event -> runCalculation("onEventAppInitialized", System.currentTimeMillis(), bgDataReload = true, limitDataToOldestAvailable = true, cause = event) },
|
||||
fabricPrivacy::logException
|
||||
)
|
||||
// EventNewHistoryData
|
||||
disposable += rxBus
|
||||
.toObservable(EventNewHistoryData::class.java)
|
||||
|
@ -147,10 +126,10 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
}
|
||||
|
||||
private fun resetDataAndRunCalculation(reason: String, event: Event?) {
|
||||
stopCalculation(reason)
|
||||
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,reason)
|
||||
clearCache()
|
||||
ads.reset()
|
||||
runCalculation(reason, System.currentTimeMillis(), bgDataReload = false, limitDataToOldestAvailable = true, cause = event)
|
||||
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, reason, System.currentTimeMillis(), bgDataReload = false, limitDataToOldestAvailable = true, cause = event, runLoop = true)
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
|
@ -310,11 +289,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
override fun getMealDataWithWaitingForCalculationFinish(): MealData {
|
||||
val result = MealData()
|
||||
val now = System.currentTimeMillis()
|
||||
val maxAbsorptionHours: Double = if (sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled()) {
|
||||
sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||
} else {
|
||||
sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||
}
|
||||
val maxAbsorptionHours: Double = activePlugin.activeSensitivity.maxAbsorptionHours()
|
||||
val absorptionTimeAgo = now - (maxAbsorptionHours * T.hours(1).msecs()).toLong()
|
||||
repository.getCarbsDataFromTimeToTimeExpanded(absorptionTimeAgo + 1, now, true)
|
||||
.blockingGet()
|
||||
|
@ -374,34 +349,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
return sb.toString()
|
||||
}
|
||||
|
||||
fun stopCalculation(from: String) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Stopping calculation thread: $from")
|
||||
WorkManager.getInstance(context).cancelUniqueWork(jobGroupName)
|
||||
val workStatus = WorkManager.getInstance(context).getWorkInfosForUniqueWork(jobGroupName).get()
|
||||
while (workStatus.size >= 1 && workStatus[0].state == WorkInfo.State.RUNNING)
|
||||
SystemClock.sleep(100)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Calculation thread stopped: $from")
|
||||
}
|
||||
|
||||
fun runCalculation(from: String, end: Long, bgDataReload: Boolean, limitDataToOldestAvailable: Boolean, cause: Event?) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Starting calculation worker: $from to ${dateUtil.dateAndTimeAndSecondsString(end)}")
|
||||
|
||||
val iobCalculation =
|
||||
if (sensitivityOref1Plugin.isEnabled())
|
||||
OneTimeWorkRequest.Builder(IobCobOref1Worker::class.java)
|
||||
.setInputData(
|
||||
dataWorker.storeInputData(IobCobOref1Worker.IobCobOref1WorkerData(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause))
|
||||
).build()
|
||||
else
|
||||
OneTimeWorkRequest.Builder(IobCobOref1Worker::class.java)
|
||||
.setInputData(
|
||||
dataWorker.storeInputData(IobCobOrefWorker.IobCobOrefWorkerData(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause))
|
||||
).build()
|
||||
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.REPLACE, iobCalculation)
|
||||
}
|
||||
|
||||
// Limit rate of EventNewHistoryData
|
||||
private val historyWorker = Executors.newSingleThreadScheduledExecutor()
|
||||
private var scheduledHistoryPost: ScheduledFuture<*>? = null
|
||||
|
@ -443,7 +390,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
// When historical data is changed (coming from NS etc) finished calculations after this date must be invalidated
|
||||
private fun newHistoryData(oldDataTimestamp: Long, bgDataReload: Boolean, event: Event) {
|
||||
//log.debug("Locking onNewHistoryData");
|
||||
stopCalculation("onEventNewHistoryData")
|
||||
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,"onEventNewHistoryData")
|
||||
synchronized(dataLock) {
|
||||
|
||||
// clear up 5 min back for proper COB calculation
|
||||
|
@ -467,7 +414,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
}
|
||||
ads.newHistoryData(time, aapsLogger, dateUtil)
|
||||
}
|
||||
runCalculation(event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event)
|
||||
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event, runLoop = true)
|
||||
//log.debug("Releasing onNewHistoryData");
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import info.nightscout.androidaps.utils.Profiler
|
|||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
|
@ -62,6 +63,7 @@ class IobCobOref1Worker(
|
|||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var calculationWorkflow: CalculationWorkflow
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
|
@ -69,10 +71,9 @@ class IobCobOref1Worker(
|
|||
|
||||
class IobCobOref1WorkerData(
|
||||
val injector: HasAndroidInjector,
|
||||
val iobCobCalculatorPlugin: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val from: String,
|
||||
val end: Long,
|
||||
val bgDataReload: Boolean,
|
||||
val limitDataToOldestAvailable: Boolean,
|
||||
val cause: Event?
|
||||
)
|
||||
|
@ -90,13 +91,9 @@ class IobCobOref1Worker(
|
|||
return Result.failure(workDataOf("Error" to "app still initializing"))
|
||||
}
|
||||
//log.debug("Locking calculateSensitivityData");
|
||||
val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
|
||||
if (data.bgDataReload) {
|
||||
data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
|
||||
data.iobCobCalculatorPlugin.clearCache()
|
||||
}
|
||||
val oldestTimeWithData = data.iobCobCalculator.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
|
||||
// work on local copy and set back when finished
|
||||
val ads = data.iobCobCalculatorPlugin.ads.clone()
|
||||
val ads = data.iobCobCalculator.ads.clone()
|
||||
val bucketedData = ads.bucketedData
|
||||
val autosensDataTable = ads.autosensDataTable
|
||||
if (bucketedData == null || bucketedData.size < 3) {
|
||||
|
@ -108,8 +105,7 @@ class IobCobOref1Worker(
|
|||
var previous = autosensDataTable[prevDataTime]
|
||||
// start from oldest to be able sub cob
|
||||
for (i in bucketedData.size - 4 downTo 0) {
|
||||
val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
|
||||
rxBus.send(EventIobCalculationProgress(100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||
if (isStopped) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
|
||||
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
|
||||
|
@ -145,7 +141,7 @@ class IobCobOref1Worker(
|
|||
autosensData.bg = bg
|
||||
delta = bg - bucketedData[i + 1].value
|
||||
avgDelta = (bg - bucketedData[i + 3].value) / 3
|
||||
val iob = data.iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
|
||||
val iob = data.iobCobCalculator.calculateFromTreatmentsAndTemps(bgTime, profile)
|
||||
val bgi = -iob.activity * sens * 5
|
||||
val deviation = delta - bgi
|
||||
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
|
||||
|
@ -332,13 +328,13 @@ class IobCobOref1Worker(
|
|||
autosensData.autosensResult = sensitivity
|
||||
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
|
||||
}
|
||||
data.iobCobCalculatorPlugin.ads = ads
|
||||
data.iobCobCalculator.ads = ads
|
||||
Thread {
|
||||
SystemClock.sleep(1000)
|
||||
rxBus.send(EventAutosensCalculationFinished(data.cause))
|
||||
}.start()
|
||||
} finally {
|
||||
rxBus.send(EventIobCalculationProgress(100, data.cause))
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100, data.cause))
|
||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
|
||||
profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start)
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import info.nightscout.androidaps.utils.Profiler
|
|||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
|
@ -69,7 +70,6 @@ class IobCobOrefWorker @Inject internal constructor(
|
|||
val iobCobCalculatorPlugin: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val from: String,
|
||||
val end: Long,
|
||||
val bgDataReload: Boolean,
|
||||
val limitDataToOldestAvailable: Boolean,
|
||||
val cause: Event?
|
||||
)
|
||||
|
@ -87,10 +87,6 @@ class IobCobOrefWorker @Inject internal constructor(
|
|||
}
|
||||
//log.debug("Locking calculateSensitivityData");
|
||||
val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
|
||||
if (data.bgDataReload) {
|
||||
data.iobCobCalculatorPlugin.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
|
||||
data.iobCobCalculatorPlugin.clearCache()
|
||||
}
|
||||
// work on local copy and set back when finished
|
||||
val ads = data.iobCobCalculatorPlugin.ads.clone()
|
||||
val bucketedData = ads.bucketedData
|
||||
|
@ -104,8 +100,7 @@ class IobCobOrefWorker @Inject internal constructor(
|
|||
var previous = autosensDataTable[prevDataTime]
|
||||
// start from oldest to be able sub cob
|
||||
for (i in bucketedData.size - 4 downTo 0) {
|
||||
val progress = i.toString() + if (buildHelper.isDev()) " (${data.from})" else ""
|
||||
rxBus.send(EventIobCalculationProgress(100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||
if (isStopped) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
|
||||
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
|
||||
|
@ -282,7 +277,7 @@ class IobCobOrefWorker @Inject internal constructor(
|
|||
rxBus.send(EventAutosensCalculationFinished(data.cause))
|
||||
}.start()
|
||||
} finally {
|
||||
rxBus.send(EventIobCalculationProgress(100, data.cause))
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100, data.cause))
|
||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
|
||||
profiler.log(LTag.AUTOSENS, "IobCobThread", start)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||
|
||||
class EventIobCalculationProgress(val progressPct: Int, val cause: Event?) : Event()
|
||||
class EventIobCalculationProgress(val pass: CalculationWorkflow.ProgressData, val progressPct: Int, val cause: Event?) : Event()
|
|
@ -137,6 +137,8 @@ class SensitivityAAPSPlugin @Inject constructor(
|
|||
return output
|
||||
}
|
||||
|
||||
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||
|
||||
override val id: SensitivityType
|
||||
get() = SensitivityType.SENSITIVITY_AAPS
|
||||
|
||||
|
|
|
@ -204,6 +204,8 @@ class SensitivityOref1Plugin @Inject constructor(
|
|||
return output
|
||||
}
|
||||
|
||||
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||
|
||||
override fun configuration(): JSONObject {
|
||||
val c = JSONObject()
|
||||
try {
|
||||
|
|
|
@ -157,6 +157,8 @@ class SensitivityWeightedAveragePlugin @Inject constructor(
|
|||
return output
|
||||
}
|
||||
|
||||
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||
|
||||
override val id: SensitivityType
|
||||
get() = SensitivityType.SENSITIVITY_WEIGHTED
|
||||
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import android.os.SystemClock
|
||||
import androidx.work.*
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.events.Event
|
||||
import info.nightscout.androidaps.events.EventAppInitialized
|
||||
import info.nightscout.androidaps.events.EventOfflineChange
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventTherapyEventChange
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Worker
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOrefWorker
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class CalculationWorkflow @Inject constructor(
|
||||
aapsSchedulers: AapsSchedulers,
|
||||
rh: ResourceHelper,
|
||||
rxBus: RxBus,
|
||||
private val context: Context,
|
||||
private val injector: HasAndroidInjector,
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val dateUtil: DateUtil,
|
||||
private val sensitivityOref1Plugin: SensitivityOref1Plugin,
|
||||
private val dataWorker: DataWorker,
|
||||
private val activePlugin: ActivePlugin
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
const val MAIN_CALCULATION = "calculation"
|
||||
const val HISTORY_CALCULATION = "history_calculation"
|
||||
const val JOB = "job"
|
||||
}
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private val iobCobCalculator: IobCobCalculator
|
||||
get() = activePlugin.activeIobCobCalculator // cross-dependency CalculationWorkflow x IobCobCalculator
|
||||
private val overviewData: OverviewData
|
||||
get() = (iobCobCalculator as IobCobCalculatorPlugin).overviewData
|
||||
|
||||
enum class ProgressData(val pass: Int, val percentOfTotal: Int) {
|
||||
PREPARE_BASAL_DATA(0, 5),
|
||||
PREPARE_TEMPORARY_TARGET_DATA(1, 5),
|
||||
PREPARE_TREATMENTS_DATA(2, 5),
|
||||
IOB_COB_OREF(3, 75),
|
||||
PREPARE_IOB_AUTOSENS_DATA(4, 10);
|
||||
|
||||
fun finalPercent(progress: Int): Int {
|
||||
var total = 0
|
||||
for (i in values()) if (i.pass < pass) total += i.percentOfTotal
|
||||
total += (percentOfTotal.toDouble() * progress / 100.0).toInt()
|
||||
return total
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// Verify definition
|
||||
var sumPercent = 0
|
||||
for (pass in ProgressData.values()) sumPercent += pass.percentOfTotal
|
||||
require(sumPercent == 100)
|
||||
|
||||
disposable += rxBus
|
||||
.toObservable(EventTherapyEventChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ runOnEventTherapyEventChange() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventOfflineChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ runOnEventTherapyEventChange() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ event ->
|
||||
if (event.isChanged(rh, R.string.key_units)) {
|
||||
overviewData.reset()
|
||||
rxBus.send(EventNewHistoryData(0, false))
|
||||
}
|
||||
if (event.isChanged(rh, R.string.key_rangetodisplay)) {
|
||||
overviewData.initRange()
|
||||
runOnScaleChanged()
|
||||
rxBus.send(EventNewHistoryData(0, false))
|
||||
}
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAppInitialized::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe(
|
||||
{
|
||||
runCalculation(
|
||||
MAIN_CALCULATION,
|
||||
iobCobCalculator,
|
||||
overviewData,
|
||||
"onEventAppInitialized",
|
||||
System.currentTimeMillis(),
|
||||
bgDataReload = true,
|
||||
limitDataToOldestAvailable = true,
|
||||
cause = it,
|
||||
runLoop = true
|
||||
)
|
||||
},
|
||||
fabricPrivacy::logException
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun stopCalculation(job: String, from: String) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Stopping calculation thread: $from")
|
||||
WorkManager.getInstance(context).cancelUniqueWork(job)
|
||||
val workStatus = WorkManager.getInstance(context).getWorkInfosForUniqueWork(job).get()
|
||||
while (workStatus.size >= 1 && workStatus[0].state == WorkInfo.State.RUNNING)
|
||||
SystemClock.sleep(100)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Calculation thread stopped: $from")
|
||||
}
|
||||
|
||||
fun runCalculation(
|
||||
job: String,
|
||||
iobCobCalculator: IobCobCalculator,
|
||||
overviewData: OverviewData,
|
||||
from: String,
|
||||
end: Long,
|
||||
bgDataReload: Boolean,
|
||||
limitDataToOldestAvailable: Boolean,
|
||||
cause: Event?,
|
||||
runLoop: Boolean
|
||||
) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Starting calculation worker: $from to ${dateUtil.dateAndTimeAndSecondsString(end)}")
|
||||
|
||||
WorkManager.getInstance(context)
|
||||
.beginUniqueWork(
|
||||
job, ExistingWorkPolicy.REPLACE,
|
||||
if (bgDataReload) OneTimeWorkRequest.Builder(LoadBgDataWorker::class.java).setInputData(dataWorker.storeInputData(LoadBgDataWorker.LoadBgData(iobCobCalculator, end))).build()
|
||||
else OneTimeWorkRequest.Builder(DummyWorker::class.java).build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareBucketedDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareBucketedDataWorker.PrepareBucketedData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareBgDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareBgDataWorker.PrepareBgData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareTreatmentsDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareTreatmentsDataWorker.PrepareTreatmentsData(overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareBasalDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareBasalDataWorker.PrepareBasalData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareTemporaryTargetDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareTemporaryTargetDataWorker.PrepareTemporaryTargetData(overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
if (sensitivityOref1Plugin.isEnabled())
|
||||
OneTimeWorkRequest.Builder(IobCobOref1Worker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(IobCobOref1Worker.IobCobOref1WorkerData(injector, iobCobCalculator, from, end, limitDataToOldestAvailable, cause)))
|
||||
.build()
|
||||
else
|
||||
OneTimeWorkRequest.Builder(IobCobOrefWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(IobCobOrefWorker.IobCobOrefWorkerData(injector, iobCobCalculator, from, end, limitDataToOldestAvailable, cause)))
|
||||
.build()
|
||||
)
|
||||
.then(OneTimeWorkRequest.Builder(UpdateIobCobSensWorker::class.java).build())
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareIobAutosensGraphDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareIobAutosensGraphDataWorker.PrepareIobAutosensData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
runLoop,
|
||||
OneTimeWorkRequest.Builder(InvokeLoopWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(InvokeLoopWorker.InvokeLoopData(cause)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
runLoop,
|
||||
OneTimeWorkRequest.Builder(PreparePredictionsWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PreparePredictionsWorker.PreparePredictionsData(overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
runLoop, OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun WorkContinuation.then(shouldAdd: Boolean, work: OneTimeWorkRequest): WorkContinuation =
|
||||
if (shouldAdd) then(work) else this
|
||||
|
||||
private fun runOnEventTherapyEventChange() {
|
||||
WorkManager.getInstance(context)
|
||||
.beginUniqueWork(
|
||||
MAIN_CALCULATION, ExistingWorkPolicy.APPEND,
|
||||
OneTimeWorkRequest.Builder(PrepareTreatmentsDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareTreatmentsDataWorker.PrepareTreatmentsData(overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
|
||||
}
|
||||
|
||||
private fun runOnScaleChanged() {
|
||||
WorkManager.getInstance(context)
|
||||
.beginUniqueWork(
|
||||
MAIN_CALCULATION, ExistingWorkPolicy.APPEND,
|
||||
OneTimeWorkRequest.Builder(PrepareBucketedDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareBucketedDataWorker.PrepareBucketedData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(PrepareBgDataWorker::class.java)
|
||||
.setInputData(dataWorker.storeInputData(PrepareBgDataWorker.PrepareBgData(iobCobCalculator, overviewData)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
|
||||
class DummyWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
override fun doWork(): Result = Result.success()
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.events.Event
|
||||
import info.nightscout.androidaps.events.EventNewBG
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.Loop
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import javax.inject.Inject
|
||||
|
||||
class InvokeLoopWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var iobCobCalculator: IobCobCalculator
|
||||
@Inject lateinit var loop: Loop
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class InvokeLoopData(
|
||||
val cause: Event?
|
||||
)
|
||||
|
||||
/*
|
||||
This method is triggered once autosens calculation has completed, so the LoopPlugin
|
||||
has current data to work with. However, autosens calculation can be triggered by multiple
|
||||
sources and currently only a new BG should trigger a loop run. Hence we return early if
|
||||
the event causing the calculation is not EventNewBg.
|
||||
<p>
|
||||
*/
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as InvokeLoopData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
if (data.cause !is EventNewBG) return Result.success(workDataOf("Result" to "no calculation needed"))
|
||||
val glucoseValue = iobCobCalculator.ads.actualBg() ?: return Result.success(workDataOf("Result" to "bg outdated"))
|
||||
if (glucoseValue.timestamp <= loop.lastBgTriggeredRun) return Result.success(workDataOf("Result" to "already looped with that value"))
|
||||
loop.lastBgTriggeredRun = glucoseValue.timestamp
|
||||
loop.invoke("Calculation for $glucoseValue", true)
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoadBgDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var repository: AppRepository
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class LoadBgData(
|
||||
val iobCobCalculator: IobCobCalculator,
|
||||
val end: Long
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as LoadBgData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
data.iobCobCalculator.ads.loadBgData(data.end, repository, aapsLogger, dateUtil, rxBus)
|
||||
data.iobCobCalculator.clearCache()
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.DashPathEffect
|
||||
import android.graphics.Paint
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import java.util.ArrayList
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
class PrepareBasalDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareBasalData(
|
||||
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareBasalData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_BASAL_DATA, 0, null))
|
||||
data.overviewData.maxBasalValueFound = 0.0
|
||||
val baseBasalArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val tempBasalArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val basalLineArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val absoluteBasalLineArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
var lastLineBasal = 0.0
|
||||
var lastAbsoluteLineBasal = -1.0
|
||||
var lastBaseBasal = 0.0
|
||||
var lastTempBasal = 0.0
|
||||
var time = data.overviewData.fromTime
|
||||
while (time < data.overviewData.toTime) {
|
||||
val progress = (time - data.overviewData.fromTime).toDouble() / (data.overviewData.toTime - data.overviewData.fromTime) * 100.0
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_BASAL_DATA, progress.toInt(), null))
|
||||
val profile = profileFunction.getProfile(time)
|
||||
if (profile == null) {
|
||||
time += 60 * 1000L
|
||||
continue
|
||||
}
|
||||
val basalData = data.iobCobCalculator.getBasalData(profile, time)
|
||||
val baseBasalValue = basalData.basal
|
||||
var absoluteLineValue = baseBasalValue
|
||||
var tempBasalValue = 0.0
|
||||
var basal = 0.0
|
||||
if (basalData.isTempBasalRunning) {
|
||||
tempBasalValue = basalData.tempBasalAbsolute
|
||||
absoluteLineValue = tempBasalValue
|
||||
if (tempBasalValue != lastTempBasal) {
|
||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, data.overviewData.basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(time, tempBasalValue.also { basal = it }, data.overviewData.basalScale))
|
||||
}
|
||||
if (lastBaseBasal != 0.0) {
|
||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, data.overviewData.basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(time, 0.0, data.overviewData.basalScale))
|
||||
lastBaseBasal = 0.0
|
||||
}
|
||||
} else {
|
||||
if (baseBasalValue != lastBaseBasal) {
|
||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, data.overviewData.basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(time, baseBasalValue.also { basal = it }, data.overviewData.basalScale))
|
||||
lastBaseBasal = baseBasalValue
|
||||
}
|
||||
if (lastTempBasal != 0.0) {
|
||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, data.overviewData.basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(time, 0.0, data.overviewData.basalScale))
|
||||
}
|
||||
}
|
||||
if (baseBasalValue != lastLineBasal) {
|
||||
basalLineArray.add(ScaledDataPoint(time, lastLineBasal, data.overviewData.basalScale))
|
||||
basalLineArray.add(ScaledDataPoint(time, baseBasalValue, data.overviewData.basalScale))
|
||||
}
|
||||
if (absoluteLineValue != lastAbsoluteLineBasal) {
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(time, lastAbsoluteLineBasal, data.overviewData.basalScale))
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(time, basal, data.overviewData.basalScale))
|
||||
}
|
||||
lastAbsoluteLineBasal = absoluteLineValue
|
||||
lastLineBasal = baseBasalValue
|
||||
lastTempBasal = tempBasalValue
|
||||
data.overviewData.maxBasalValueFound = max(data.overviewData.maxBasalValueFound, max(tempBasalValue, baseBasalValue))
|
||||
time += 60 * 1000L
|
||||
}
|
||||
|
||||
// final points
|
||||
basalLineArray.add(ScaledDataPoint(data.overviewData.toTime, lastLineBasal, data.overviewData.basalScale))
|
||||
baseBasalArray.add(ScaledDataPoint(data.overviewData.toTime, lastBaseBasal, data.overviewData.basalScale))
|
||||
tempBasalArray.add(ScaledDataPoint(data.overviewData.toTime, lastTempBasal, data.overviewData.basalScale))
|
||||
absoluteBasalLineArray.add(ScaledDataPoint(data.overviewData.toTime, lastAbsoluteLineBasal, data.overviewData.basalScale))
|
||||
|
||||
// create series
|
||||
data.overviewData.baseBasalGraphSeries = LineGraphSeries(Array(baseBasalArray.size) { i -> baseBasalArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = rh.gc(R.color.basebasal)
|
||||
it.thickness = 0
|
||||
}
|
||||
data.overviewData.tempBasalGraphSeries = LineGraphSeries(Array(tempBasalArray.size) { i -> tempBasalArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = rh.gc(R.color.tempbasal)
|
||||
it.thickness = 0
|
||||
}
|
||||
data.overviewData.basalLineGraphSeries = LineGraphSeries(Array(basalLineArray.size) { i -> basalLineArray[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(2f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.basal)
|
||||
})
|
||||
}
|
||||
data.overviewData.absoluteBasalGraphSeries = LineGraphSeries(Array(absoluteBasalLineArray.size) { i -> absoluteBasalLineArray[i] }).also {
|
||||
it.setCustomPaint(Paint().also { absolutePaint ->
|
||||
absolutePaint.style = Paint.Style.STROKE
|
||||
absolutePaint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
||||
absolutePaint.color = rh.gc(R.color.basal)
|
||||
})
|
||||
}
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_BASAL_DATA, 100, null))
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import java.util.ArrayList
|
||||
import javax.inject.Inject
|
||||
|
||||
class PrepareBgDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var repository: AppRepository
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareBgData(
|
||||
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareBgData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
data.overviewData.maxBgValue = Double.MIN_VALUE
|
||||
data.overviewData.bgReadingsArray = repository.compatGetBgReadingsDataFromTime(data.overviewData.fromTime, data.overviewData.toTime, false).blockingGet()
|
||||
val bgListArray: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
for (bg in data.overviewData.bgReadingsArray) {
|
||||
if (bg.timestamp < data.overviewData.fromTime || bg.timestamp > data.overviewData.toTime) continue
|
||||
if (bg.value > data.overviewData.maxBgValue) data.overviewData.maxBgValue = bg.value
|
||||
bgListArray.add(GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh))
|
||||
}
|
||||
bgListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
||||
data.overviewData.bgReadingGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
||||
data.overviewData.maxBgValue = Profile.fromMgdlToUnits(data.overviewData.maxBgValue, profileFunction.getUnits())
|
||||
if (defaultValueHelper.determineHighLine() > data.overviewData.maxBgValue) data.overviewData.maxBgValue = defaultValueHelper.determineHighLine()
|
||||
data.overviewData.maxBgValue = addUpperChartMargin(data.overviewData.maxBgValue)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun addUpperChartMargin(maxBgValue: Double) =
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.InMemoryGlucoseValueDataPoint
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
class PrepareBucketedDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareBucketedData(
|
||||
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareBucketedData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
val bucketedData = data.iobCobCalculator.ads.getBucketedDataTableCopy() ?: return Result.success()
|
||||
if (bucketedData.isEmpty()) {
|
||||
aapsLogger.debug("No bucketed data.")
|
||||
return Result.success()
|
||||
}
|
||||
val bucketedListArray: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
for (inMemoryGlucoseValue in bucketedData) {
|
||||
if (inMemoryGlucoseValue.timestamp < data.overviewData.fromTime || inMemoryGlucoseValue.timestamp > data.overviewData.toTime) continue
|
||||
bucketedListArray.add(InMemoryGlucoseValueDataPoint(inMemoryGlucoseValue, profileFunction, rh))
|
||||
}
|
||||
bucketedListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
||||
data.overviewData.bucketedGraphSeries = PointsWithLabelGraphSeries(Array(bucketedListArray.size) { i -> bucketedListArray[i] })
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.DashPathEffect
|
||||
import android.graphics.Paint
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import com.jjoe64.graphview.series.BarGraphSeries
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.FixedLineGraphSeries
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import java.util.ArrayList
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class PrepareIobAutosensGraphDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var overviewMenus: OverviewMenus
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareIobAutosensData(
|
||||
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareIobAutosensData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_IOB_AUTOSENS_DATA, 0, null))
|
||||
val iobArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val absIobArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
data.overviewData.maxIobValueFound = Double.MIN_VALUE
|
||||
var lastIob = 0.0
|
||||
var absLastIob = 0.0
|
||||
var time = data.overviewData.fromTime
|
||||
|
||||
val minFailOverActiveList: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
val cobArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
data.overviewData.maxCobValueFound = Double.MIN_VALUE
|
||||
var lastCob = 0
|
||||
|
||||
val actArrayHist: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val actArrayPrediction: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val now = dateUtil.now().toDouble()
|
||||
data.overviewData.maxIAValue = 0.0
|
||||
|
||||
val bgiArrayHist: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val bgiArrayPrediction: MutableList<ScaledDataPoint> = ArrayList()
|
||||
data.overviewData.maxBGIValue = Double.MIN_VALUE
|
||||
|
||||
val devArray: MutableList<OverviewPlugin.DeviationDataPoint> = ArrayList()
|
||||
data.overviewData.maxDevValueFound = Double.MIN_VALUE
|
||||
|
||||
val ratioArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
data.overviewData.maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105%
|
||||
data.overviewData.minRatioValueFound = -5.0
|
||||
|
||||
val dsMaxArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
val dsMinArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
data.overviewData.maxFromMaxValueFound = Double.MIN_VALUE
|
||||
data.overviewData.maxFromMinValueFound = Double.MIN_VALUE
|
||||
|
||||
val adsData = data.iobCobCalculator.ads.clone()
|
||||
|
||||
while (time <= data.overviewData.toTime) {
|
||||
val progress = (time - data.overviewData.fromTime).toDouble() / (data.overviewData.toTime - data.overviewData.fromTime) * 100.0
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_IOB_AUTOSENS_DATA, progress.toInt(), null))
|
||||
val profile = profileFunction.getProfile(time)
|
||||
if (profile == null) {
|
||||
time += 5 * 60 * 1000L
|
||||
continue
|
||||
}
|
||||
// IOB
|
||||
val iob = data.iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
|
||||
val baseBasalIob = data.iobCobCalculator.calculateAbsoluteIobFromBaseBasals(time)
|
||||
val absIob = IobTotal.combine(iob, baseBasalIob)
|
||||
val autosensData = adsData.getAutosensDataAtTime(time)
|
||||
if (abs(lastIob - iob.iob) > 0.02) {
|
||||
if (abs(lastIob - iob.iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, data.overviewData.iobScale))
|
||||
iobArray.add(ScaledDataPoint(time, iob.iob, data.overviewData.iobScale))
|
||||
data.overviewData.maxIobValueFound = maxOf(data.overviewData.maxIobValueFound, abs(iob.iob))
|
||||
lastIob = iob.iob
|
||||
}
|
||||
if (abs(absLastIob - absIob.iob) > 0.02) {
|
||||
if (abs(absLastIob - absIob.iob) > 0.2) absIobArray.add(ScaledDataPoint(time, absLastIob, data.overviewData.iobScale))
|
||||
absIobArray.add(ScaledDataPoint(time, absIob.iob, data.overviewData.iobScale))
|
||||
data.overviewData.maxIobValueFound = maxOf(data.overviewData.maxIobValueFound, abs(absIob.iob))
|
||||
absLastIob = absIob.iob
|
||||
}
|
||||
|
||||
// COB
|
||||
if (autosensData != null) {
|
||||
val cob = autosensData.cob.toInt()
|
||||
if (cob != lastCob) {
|
||||
if (autosensData.carbsFromBolus > 0) cobArray.add(ScaledDataPoint(time, lastCob.toDouble(), data.overviewData.cobScale))
|
||||
cobArray.add(ScaledDataPoint(time, cob.toDouble(), data.overviewData.cobScale))
|
||||
data.overviewData.maxCobValueFound = max(data.overviewData.maxCobValueFound, cob.toDouble())
|
||||
lastCob = cob
|
||||
}
|
||||
if (autosensData.failOverToMinAbsorptionRate) {
|
||||
autosensData.scale = data.overviewData.cobScale
|
||||
autosensData.chartTime = time
|
||||
minFailOverActiveList.add(autosensData)
|
||||
}
|
||||
}
|
||||
|
||||
// ACTIVITY
|
||||
if (time <= now) actArrayHist.add(ScaledDataPoint(time, iob.activity, data.overviewData.actScale))
|
||||
else actArrayPrediction.add(ScaledDataPoint(time, iob.activity, data.overviewData.actScale))
|
||||
data.overviewData.maxIAValue = max(data.overviewData.maxIAValue, abs(iob.activity))
|
||||
|
||||
// BGI
|
||||
val devBgiScale = overviewMenus.isEnabledIn(OverviewMenus.CharType.DEV) == overviewMenus.isEnabledIn(OverviewMenus.CharType.BGI)
|
||||
val deviation = if (devBgiScale) autosensData?.deviation ?: 0.0 else 0.0
|
||||
val bgi: Double = iob.activity * profile.getIsfMgdl(time) * 5.0
|
||||
if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, data.overviewData.bgiScale))
|
||||
else bgiArrayPrediction.add(ScaledDataPoint(time, bgi, data.overviewData.bgiScale))
|
||||
data.overviewData.maxBGIValue = max(data.overviewData.maxBGIValue, max(abs(bgi), deviation))
|
||||
|
||||
// DEVIATIONS
|
||||
if (autosensData != null) {
|
||||
var color = rh.gc(R.color.deviationblack) // "="
|
||||
if (autosensData.type == "" || autosensData.type == "non-meal") {
|
||||
if (autosensData.pastSensitivity == "C") color = rh.gc(R.color.deviationgrey)
|
||||
if (autosensData.pastSensitivity == "+") color = rh.gc(R.color.deviationgreen)
|
||||
if (autosensData.pastSensitivity == "-") color = rh.gc(R.color.deviationred)
|
||||
} else if (autosensData.type == "uam") {
|
||||
color = rh.gc(R.color.uam)
|
||||
} else if (autosensData.type == "csf") {
|
||||
color = rh.gc(R.color.deviationgrey)
|
||||
}
|
||||
devArray.add(OverviewPlugin.DeviationDataPoint(time.toDouble(), autosensData.deviation, color, data.overviewData.devScale))
|
||||
data.overviewData.maxDevValueFound = maxOf(data.overviewData.maxDevValueFound, abs(autosensData.deviation), abs(bgi))
|
||||
}
|
||||
|
||||
// RATIO
|
||||
if (autosensData != null) {
|
||||
ratioArray.add(ScaledDataPoint(time, 100.0 * (autosensData.autosensResult.ratio - 1), data.overviewData.ratioScale))
|
||||
data.overviewData.maxRatioValueFound = max(data.overviewData.maxRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
||||
data.overviewData.minRatioValueFound = min(data.overviewData.minRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
||||
}
|
||||
|
||||
// DEV SLOPE
|
||||
if (autosensData != null) {
|
||||
dsMaxArray.add(ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, data.overviewData.dsMaxScale))
|
||||
dsMinArray.add(ScaledDataPoint(time, autosensData.slopeFromMinDeviation, data.overviewData.dsMinScale))
|
||||
data.overviewData.maxFromMaxValueFound = max(data.overviewData.maxFromMaxValueFound, abs(autosensData.slopeFromMaxDeviation))
|
||||
data.overviewData.maxFromMinValueFound = max(data.overviewData.maxFromMinValueFound, abs(autosensData.slopeFromMinDeviation))
|
||||
}
|
||||
|
||||
time += 5 * 60 * 1000L
|
||||
}
|
||||
// IOB
|
||||
data.overviewData.iobSeries = FixedLineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
||||
it.color = rh.gc(R.color.iob)
|
||||
it.thickness = 3
|
||||
}
|
||||
data.overviewData.absIobSeries = FixedLineGraphSeries(Array(absIobArray.size) { i -> absIobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
||||
it.color = rh.gc(R.color.iob)
|
||||
it.thickness = 3
|
||||
}
|
||||
|
||||
if (overviewMenus.setting[0][OverviewMenus.CharType.PRE.ordinal]) {
|
||||
val autosensData = adsData.getLastAutosensData("GraphData", aapsLogger, dateUtil)
|
||||
val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult()
|
||||
val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
|
||||
val iobPrediction: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
val iobPredictionArray = data.iobCobCalculator.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
||||
for (i in iobPredictionArray) {
|
||||
iobPrediction.add(i.setColor(rh.gc(R.color.iobPredAS)))
|
||||
data.overviewData.maxIobValueFound = max(data.overviewData.maxIobValueFound, abs(i.iob))
|
||||
}
|
||||
data.overviewData.iobPredictions1Series = PointsWithLabelGraphSeries(Array(iobPrediction.size) { i -> iobPrediction[i] })
|
||||
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + data.iobCobCalculator.iobArrayToString(iobPredictionArray))
|
||||
} else {
|
||||
data.overviewData.iobPredictions1Series = PointsWithLabelGraphSeries()
|
||||
}
|
||||
|
||||
// COB
|
||||
data.overviewData.cobSeries = FixedLineGraphSeries(Array(cobArray.size) { i -> cobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.cob) //50%
|
||||
it.color = rh.gc(R.color.cob)
|
||||
it.thickness = 3
|
||||
}
|
||||
data.overviewData.cobMinFailOverSeries = PointsWithLabelGraphSeries(Array(minFailOverActiveList.size) { i -> minFailOverActiveList[i] })
|
||||
|
||||
// ACTIVITY
|
||||
data.overviewData.activitySeries = FixedLineGraphSeries(Array(actArrayHist.size) { i -> actArrayHist[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.activity)
|
||||
it.thickness = 3
|
||||
}
|
||||
data.overviewData.activityPredictionSeries = FixedLineGraphSeries(Array(actArrayPrediction.size) { i -> actArrayPrediction[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = 3f
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.activity)
|
||||
})
|
||||
}
|
||||
|
||||
// BGI
|
||||
data.overviewData.minusBgiSeries = FixedLineGraphSeries(Array(bgiArrayHist.size) { i -> bgiArrayHist[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.bgi)
|
||||
it.thickness = 3
|
||||
}
|
||||
data.overviewData.minusBgiHistSeries = FixedLineGraphSeries(Array(bgiArrayPrediction.size) { i -> bgiArrayPrediction[i] }).also {
|
||||
it.setCustomPaint(Paint().also { paint ->
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = 3f
|
||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
||||
paint.color = rh.gc(R.color.bgi)
|
||||
})
|
||||
}
|
||||
|
||||
// DEVIATIONS
|
||||
data.overviewData.deviationsSeries = BarGraphSeries(Array(devArray.size) { i -> devArray[i] }).also {
|
||||
it.setValueDependentColor { data: OverviewPlugin.DeviationDataPoint -> data.color }
|
||||
}
|
||||
|
||||
// RATIO
|
||||
data.overviewData.ratioSeries = LineGraphSeries(Array(ratioArray.size) { i -> ratioArray[i] }).also {
|
||||
it.color = rh.gc(R.color.ratio)
|
||||
it.thickness = 3
|
||||
}
|
||||
|
||||
// DEV SLOPE
|
||||
data.overviewData.dsMaxSeries = LineGraphSeries(Array(dsMaxArray.size) { i -> dsMaxArray[i] }).also {
|
||||
it.color = rh.gc(R.color.devslopepos)
|
||||
it.thickness = 3
|
||||
}
|
||||
data.overviewData.dsMinSeries = LineGraphSeries(Array(dsMinArray.size) { i -> dsMinArray[i] }).also {
|
||||
it.color = rh.gc(R.color.devslopeneg)
|
||||
it.thickness = 3
|
||||
}
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_IOB_AUTOSENS_DATA, 100, null))
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.Loop
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class PreparePredictionsWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var overviewData: OverviewData
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var nsDeviceStatus: NSDeviceStatus
|
||||
@Inject lateinit var loop: Loop
|
||||
@Inject lateinit var overviewMenus: OverviewMenus
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PreparePredictionsData(
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PreparePredictionsData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
val apsResult = if (config.APS) loop.lastRun?.constraintsProcessed else nsDeviceStatus.getAPSResult(injector)
|
||||
val predictionsAvailable = if (config.APS) loop.lastRun?.request?.hasPredictions == true else config.NSCLIENT
|
||||
val menuChartSettings = overviewMenus.setting
|
||||
// align to hours
|
||||
val calendar = Calendar.getInstance().also {
|
||||
it.timeInMillis = System.currentTimeMillis()
|
||||
it[Calendar.MILLISECOND] = 0
|
||||
it[Calendar.SECOND] = 0
|
||||
it[Calendar.MINUTE] = 0
|
||||
it.add(Calendar.HOUR, 1)
|
||||
}
|
||||
if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) {
|
||||
var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt()
|
||||
predictionHours = min(2, predictionHours)
|
||||
predictionHours = max(0, predictionHours)
|
||||
val hoursToFetch = data.overviewData.rangeToDisplay - predictionHours
|
||||
data.overviewData.toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
||||
data.overviewData.fromTime = data.overviewData.toTime - T.hours(hoursToFetch.toLong()).msecs()
|
||||
data.overviewData.endTime = data.overviewData.toTime + T.hours(predictionHours.toLong()).msecs()
|
||||
} else {
|
||||
data.overviewData.toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
||||
data.overviewData.fromTime = data.overviewData.toTime - T.hours(data.overviewData.rangeToDisplay.toLong()).msecs()
|
||||
data.overviewData.endTime = data.overviewData.toTime
|
||||
}
|
||||
|
||||
val bgListArray: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
val predictions: MutableList<GlucoseValueDataPoint>? = apsResult?.predictions
|
||||
?.map { bg -> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh) }
|
||||
?.toMutableList()
|
||||
if (predictions != null) {
|
||||
predictions.sortWith { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }
|
||||
for (prediction in predictions) if (prediction.data.value >= 40) bgListArray.add(prediction)
|
||||
}
|
||||
data.overviewData.predictionsGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import com.jjoe64.graphview.series.DataPoint
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.extensions.target
|
||||
import info.nightscout.androidaps.interfaces.Loop
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
class PrepareTemporaryTargetDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var loop: Loop
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareTemporaryTargetData(
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareTemporaryTargetData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TEMPORARY_TARGET_DATA, 0, null))
|
||||
val profile = profileFunction.getProfile() ?: return Result.failure(workDataOf("Error" to "missing profile"))
|
||||
val units = profileFunction.getUnits()
|
||||
var toTime = data.overviewData.toTime
|
||||
val targetsSeriesArray: MutableList<DataPoint> = ArrayList()
|
||||
var lastTarget = -1.0
|
||||
loop.lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) }
|
||||
var time = data.overviewData.fromTime
|
||||
while (time < toTime) {
|
||||
val progress = (time - data.overviewData.fromTime).toDouble() / (data.overviewData.toTime - data.overviewData.fromTime) * 100.0
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TEMPORARY_TARGET_DATA, progress.toInt(), null))
|
||||
val tt = repository.getTemporaryTargetActiveAt(time).blockingGet()
|
||||
val value: Double = if (tt is ValueWrapper.Existing) {
|
||||
Profile.fromMgdlToUnits(tt.value.target(), units)
|
||||
} else {
|
||||
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
|
||||
}
|
||||
if (lastTarget != value) {
|
||||
if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget))
|
||||
targetsSeriesArray.add(DataPoint(time.toDouble(), value))
|
||||
}
|
||||
lastTarget = value
|
||||
time += 5 * 60 * 1000L
|
||||
}
|
||||
// final point
|
||||
targetsSeriesArray.add(DataPoint(toTime.toDouble(), lastTarget))
|
||||
// create series
|
||||
data.overviewData.temporaryTargetSeries = LineGraphSeries(Array(targetsSeriesArray.size) { i -> targetsSeriesArray[i] }).also {
|
||||
it.isDrawBackground = false
|
||||
it.color = rh.gc(R.color.tempTargetBackground)
|
||||
it.thickness = 2
|
||||
}
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TEMPORARY_TARGET_DATA, 100, null))
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.receivers.DataWorker
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.Translator
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class PrepareTreatmentsDataWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var dataWorker: DataWorker
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var translator: Translator
|
||||
@Inject lateinit var activePlugin: ActivePlugin
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
class PrepareTreatmentsData(
|
||||
val overviewData: OverviewData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as PrepareTreatmentsData?
|
||||
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TREATMENTS_DATA, 0, null))
|
||||
data.overviewData.maxTreatmentsValue = 0.0
|
||||
val filteredTreatments: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
repository.getBolusesDataFromTimeToTime(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
|
||||
.map { BolusDataPoint(it, rh, activePlugin, defaultValueHelper) }
|
||||
.filter { it.data.type == Bolus.Type.NORMAL || it.data.type == Bolus.Type.SMB }
|
||||
.forEach {
|
||||
it.y = getNearestBg(data.overviewData, it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
repository.getCarbsDataFromTimeToTimeExpanded(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
|
||||
.map { CarbsDataPoint(it, rh) }
|
||||
.forEach {
|
||||
it.y = getNearestBg(data.overviewData, it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
|
||||
// ProfileSwitch
|
||||
repository.getEffectiveProfileSwitchDataFromTimeToTime(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
|
||||
.map { EffectiveProfileSwitchDataPoint(it, rh) }
|
||||
.forEach(filteredTreatments::add)
|
||||
|
||||
// OfflineEvent
|
||||
repository.getOfflineEventDataFromTimeToTime(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
|
||||
.map {
|
||||
TherapyEventDataPoint(
|
||||
TherapyEvent(timestamp = it.timestamp, duration = it.duration, type = TherapyEvent.Type.APS_OFFLINE, glucoseUnit = TherapyEvent.GlucoseUnit.MMOL),
|
||||
rh,
|
||||
profileFunction,
|
||||
translator
|
||||
)
|
||||
}
|
||||
.forEach(filteredTreatments::add)
|
||||
|
||||
// Extended bolus
|
||||
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
||||
repository.getExtendedBolusDataFromTimeToTime(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
|
||||
.map { ExtendedBolusDataPoint(it, rh) }
|
||||
.filter { it.duration != 0L }
|
||||
.forEach {
|
||||
it.y = getNearestBg(data.overviewData, it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Careportal
|
||||
repository.compatGetTherapyEventDataFromToTime(data.overviewData.fromTime - T.hours(6).msecs(), data.overviewData.endTime).blockingGet()
|
||||
.map { TherapyEventDataPoint(it, rh, profileFunction, translator) }
|
||||
.filterTimeframe(data.overviewData.fromTime, data.overviewData.endTime)
|
||||
.forEach {
|
||||
if (it.y == 0.0) it.y = getNearestBg(data.overviewData, it.x.toLong())
|
||||
filteredTreatments.add(it)
|
||||
}
|
||||
|
||||
// increase maxY if a treatment forces it's own height that's higher than a BG value
|
||||
filteredTreatments.map { it.y }
|
||||
.maxOrNull()
|
||||
?.let(::addUpperChartMargin)
|
||||
?.let { data.overviewData.maxTreatmentsValue = maxOf(data.overviewData.maxTreatmentsValue, it) }
|
||||
|
||||
data.overviewData.treatmentsSeries = PointsWithLabelGraphSeries(filteredTreatments.toTypedArray())
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TREATMENTS_DATA, 100, null))
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun addUpperChartMargin(maxBgValue: Double) =
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4
|
||||
|
||||
private fun getNearestBg(overviewData: OverviewData, date: Long): Double {
|
||||
overviewData.bgReadingsArray.let { bgReadingsArray ->
|
||||
for (reading in bgReadingsArray) {
|
||||
if (reading.timestamp > date) continue
|
||||
return Profile.fromMgdlToUnits(reading.value, profileFunction.getUnits())
|
||||
}
|
||||
return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].value, profileFunction.getUnits())
|
||||
else Profile.fromMgdlToUnits(100.0, profileFunction.getUnits())
|
||||
}
|
||||
}
|
||||
|
||||
private fun <E : DataPointWithLabelInterface> List<E>.filterTimeframe(fromTime: Long, endTime: Long): List<E> =
|
||||
filter { it.x + it.duration >= fromTime && it.x <= endTime }
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewGraph
|
||||
import javax.inject.Inject
|
||||
|
||||
class UpdateGraphWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var overviewPlugin: OverviewPlugin
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
override fun doWork(): Result {
|
||||
if (inputData.getString(CalculationWorkflow.JOB) == CalculationWorkflow.MAIN_CALCULATION)
|
||||
overviewPlugin.overviewBus.send(EventUpdateOverviewGraph("UpdateGraphWorker"))
|
||||
else
|
||||
rxBus.send(EventUpdateOverviewGraph("UpdateGraphWorker"))
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewIobCob
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewSensitivity
|
||||
import javax.inject.Inject
|
||||
|
||||
class UpdateIobCobSensWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var overviewPlugin: OverviewPlugin
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
override fun doWork(): Result {
|
||||
overviewPlugin.overviewBus.send(EventUpdateOverviewIobCob("UpdateIobCobSensWorker"))
|
||||
overviewPlugin.overviewBus.send(EventUpdateOverviewSensitivity("UpdateIobCobSensWorker"))
|
||||
return Result.success()
|
||||
}
|
||||
}
|
|
@ -63,6 +63,17 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:progress="100" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -88,13 +99,6 @@
|
|||
android:paddingTop="5dp"
|
||||
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_iobcalculationprogess"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:textSize="15sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -30,6 +30,8 @@ class AbstractSensitivityPluginTest : TestBase() {
|
|||
override val id: Sensitivity.SensitivityType
|
||||
get() = Sensitivity.SensitivityType.UNKNOWN
|
||||
|
||||
override fun maxAbsorptionHours(): Double = 8.0
|
||||
|
||||
override fun configuration(): JSONObject = JSONObject()
|
||||
|
||||
override fun applyConfiguration(configuration: JSONObject) {}
|
||||
|
|
|
@ -7,7 +7,11 @@ import android.os.SystemClock
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.annotations.OpenForTesting
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.events.EventBTChange
|
||||
import info.nightscout.androidaps.events.EventChargingState
|
||||
import info.nightscout.androidaps.events.EventLocationChange
|
||||
import info.nightscout.androidaps.events.EventNetworkChange
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
|
@ -33,7 +37,6 @@ import org.json.JSONObject
|
|||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@OpenForTesting
|
||||
@Singleton
|
||||
|
@ -127,10 +130,6 @@ class AutomationPlugin @Inject constructor(
|
|||
.toObservable(EventNetworkChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ processActions() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ processActions() }, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventBTChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
|
@ -150,7 +149,7 @@ class AutomationPlugin @Inject constructor(
|
|||
|
||||
private fun storeToSP() {
|
||||
val array = JSONArray()
|
||||
val iterator = ArrayList<AutomationEvent>(automationEvents).iterator()
|
||||
val iterator = ArrayList(automationEvents).iterator()
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
val event = iterator.next()
|
||||
|
|
|
@ -38,6 +38,7 @@ ActionsTestBase : TestBaseWithProfile() {
|
|||
override var enabled: Boolean
|
||||
get() = true
|
||||
set(_) {}
|
||||
override var lastBgTriggeredRun: Long = 0
|
||||
|
||||
override fun invoke(initiator: String, allowNotification: Boolean, tempBasalFallback: Boolean) {}
|
||||
override fun acceptChangeRequest() {}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
import info.nightscout.androidaps.events.EventLoop
|
||||
|
||||
class EventAutosensCalculationFinished(val cause: Event?) : EventLoop()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventDanaRSyncStatus(var message: String) : Event()
|
|
@ -5,6 +5,7 @@ import android.os.Looper
|
|||
import android.view.View
|
||||
|
||||
fun Boolean.toVisibility() = if (this) View.VISIBLE else View.GONE
|
||||
fun Boolean.toVisibilityKeepSpace() = if (this) View.VISIBLE else View.INVISIBLE
|
||||
|
||||
fun runOnUiThread(theRunnable: Runnable?) = theRunnable?.let {
|
||||
Handler(Looper.getMainLooper()).post(it)
|
||||
|
|
|
@ -52,6 +52,12 @@ interface ActivePlugin {
|
|||
*/
|
||||
val activeSafety: Safety
|
||||
|
||||
/**
|
||||
* Currently selected Safety plugin
|
||||
* Always IobCobCalculatorPlugin
|
||||
*/
|
||||
val activeIobCobCalculator: IobCobCalculator
|
||||
|
||||
/**
|
||||
* List of all registered plugins
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,8 @@ interface Loop {
|
|||
val isDisconnected: Boolean
|
||||
var enabled: Boolean
|
||||
|
||||
var lastBgTriggeredRun: Long
|
||||
|
||||
fun invoke(initiator: String, allowNotification: Boolean, tempBasalFallback: Boolean = false)
|
||||
|
||||
fun acceptChangeRequest()
|
||||
|
|
|
@ -4,6 +4,5 @@ import info.nightscout.androidaps.plugins.bus.RxBus
|
|||
|
||||
interface Overview : ConfigExportImport {
|
||||
|
||||
fun refreshLoop(from: String)
|
||||
val overviewBus: RxBus
|
||||
}
|
|
@ -20,6 +20,7 @@ interface Sensitivity : ConfigExportImport {
|
|||
|
||||
val id: SensitivityType
|
||||
fun detectSensitivity(ads: AutosensDataStore, fromTime: Long, toTime: Long): AutosensResult
|
||||
fun maxAbsorptionHours(): Double
|
||||
|
||||
companion object {
|
||||
|
||||
|
|
|
@ -234,6 +234,9 @@
|
|||
<color name="mdtp_button_selected">#33969696</color>
|
||||
<color name="plastic">#EBEBEA</color>
|
||||
|
||||
<color name="textAppearancemediumLight">#000000</color>
|
||||
<color name="textAppearancemediumDark">#B3FFFFFF</color>
|
||||
|
||||
<!-- dash and eros colors -->
|
||||
<color name="omni_yellow">#FFFF00</color>
|
||||
<color name="omni_cyan">#00FFFF</color>
|
||||
|
|
|
@ -225,6 +225,7 @@
|
|||
<item name="activityColor">@color/activity</item>
|
||||
<!-- CardView specific colors -->
|
||||
<item name="strokeColor">@color/plastic_grey</item>
|
||||
<item name="textAppearancemediumColor">@color/textAppearancemediumDark</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.MaterialComponents.DayNight.DarkActionBar" parent="Theme.MaterialComponents.DayNight.Bridge"/>
|
||||
|
|
|
@ -205,4 +205,5 @@
|
|||
<attr name="activityColor" format="reference|color" />
|
||||
<!-- CardView specific colors -->
|
||||
<attr name="strokeColor" format="reference|color" />
|
||||
<attr name="textAppearancemediumColor" format="reference|color" />
|
||||
</resources>
|
|
@ -238,6 +238,9 @@
|
|||
<color name="mdtp_button_selected">#33969696</color>
|
||||
<color name="plastic">#EBEBEA</color>
|
||||
|
||||
<color name="textAppearancemediumLight">#000000</color>
|
||||
<color name="textAppearancemediumDark">#B3FFFFFF</color>
|
||||
|
||||
<!-- dash and eros colors -->
|
||||
<color name="omni_yellow">#FFFF00</color>
|
||||
<color name="omni_cyan">#00FFFF</color>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<!-- BG source temp button -->
|
||||
<item name="setTempButton">@color/colorSetTempButton</item>
|
||||
<!-- Card Item-->
|
||||
<item name="cardItemBackgroundColor">@color/cardColorBackground</item>
|
||||
<item name="cardItemBackgroundColor">?attr/colorSurface</item>
|
||||
<!-- Exercise -->
|
||||
<item name="exerciseColor">@color/exercise</item>
|
||||
<!-- BG low -->
|
||||
|
@ -233,6 +233,7 @@
|
|||
<item name="activityColor">@color/activity</item>
|
||||
<!-- CardView specific colors -->
|
||||
<item name="strokeColor">@color/plastic_grey</item>
|
||||
<item name="textAppearancemediumColor">@color/textAppearancemediumLight</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.MaterialComponents.DayNight.DarkActionBar" parent="Theme.MaterialComponents.DayNight.Bridge"/>
|
||||
|
|
|
@ -27,7 +27,7 @@ android {
|
|||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['libs']
|
||||
jniLibs.srcDirs = ['src/main/jniLibs']
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ dependencies {
|
|||
implementation(files('libs/wearpreferenceactivity-0.5.0.aar'))
|
||||
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.1'
|
||||
implementation "androidx.core:core-ktx:$core_version"
|
||||
implementation "androidx.wear.tiles:tiles:1.0.1"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
|
Loading…
Reference in a new issue