optimize screen refreshing

This commit is contained in:
Milos Kozak 2021-11-09 23:06:24 +01:00
parent 95f6cc7a7d
commit 5ae83c47c0
29 changed files with 690 additions and 513 deletions

View file

@ -179,7 +179,7 @@ class WizardDialog : DaggerDialogFragment() {
// profile spinner
binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileselected))
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileset))
binding.ok.visibility = View.GONE
}

View file

@ -242,8 +242,8 @@ class LoopPlugin @Inject constructor(
if (!isEnabled(PluginType.LOOP)) return
val profile = profileFunction.getProfile()
if (profile == null || !profileFunction.isProfileValid("Loop")) {
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileselected))
rxBus.send(EventLoopSetLastRunGui(rh.gs(R.string.noprofileselected)))
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileset))
rxBus.send(EventLoopSetLastRunGui(rh.gs(R.string.noprofileset)))
return
}

View file

@ -86,8 +86,8 @@ class OpenAPSAMAPlugin @Inject constructor(
val profile = profileFunction.getProfile()
val pump = activePlugin.activePump
if (profile == null) {
rxBus.send(EventOpenAPSUpdateResultGui(rh.gs(R.string.noprofileselected)))
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileselected))
rxBus.send(EventOpenAPSUpdateResultGui(rh.gs(R.string.noprofileset)))
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileset))
return
}
if (!isEnabled(PluginType.APS)) {

View file

@ -93,8 +93,8 @@ class OpenAPSSMBPlugin @Inject constructor(
val profile = profileFunction.getProfile()
val pump = activePlugin.activePump
if (profile == null) {
rxBus.send(EventOpenAPSUpdateResultGui(rh.gs(R.string.noprofileselected)))
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileselected))
rxBus.send(EventOpenAPSUpdateResultGui(rh.gs(R.string.noprofileset)))
aapsLogger.debug(LTag.APS, rh.gs(R.string.noprofileset))
return
}
if (!isEnabled(PluginType.APS)) {

View file

@ -78,7 +78,7 @@ class ProfileFunctionImplementation @Inject constructor(
getProfileName(System.currentTimeMillis(), customized = true, showRemainingTime = true)
fun getProfileName(time: Long, customized: Boolean, showRemainingTime: Boolean): String {
var profileName = rh.gs(R.string.noprofileselected)
var profileName = rh.gs(R.string.noprofileset)
val profileSwitch = repository.getEffectiveProfileSwitchActiveAt(time).blockingGet()
if (profileSwitch is ValueWrapper.Existing) {

View file

@ -12,7 +12,8 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.insight.database.InsightDatabase
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ImportExportPrefs
@ -23,7 +24,8 @@ import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
import info.nightscout.androidaps.plugins.general.overview.OverviewData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase
import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -43,6 +45,9 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
@Inject lateinit var danaHistoryDatabase: DanaHistoryDatabase
@Inject lateinit var insightDatabase: InsightDatabase
@Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase
@Inject lateinit var erosDatabase: ErosHistoryDatabase
@Inject lateinit var dashDatabase: DashHistoryDatabase
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var pumpSync: PumpSync
@ -79,6 +84,9 @@ class MaintenanceFragment : DaggerFragment() {
repository.clearDatabases()
danaHistoryDatabase.clearAllTables()
insightDatabase.clearAllTables()
diaconnDatabase.clearAllTables()
erosDatabase.clearAllTables()
dashDatabase.clearAllTables()
dataSyncSelector.resetToNextFullSync()
pumpSync.connectNewPump()
overviewData.reset()
@ -86,12 +94,10 @@ class MaintenanceFragment : DaggerFragment() {
iobCobCalculator.clearCache()
}
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error clearing databases", it) },
onComplete = {
rxBus.send(EventNewBG(null))
rxBus.send(EventNewHistoryData(0, true))
rxBus.send(EventPreferenceChange(rh, R.string.key_units))
}
)
)

View file

@ -1,28 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks;
import org.json.JSONObject;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.plugins.bus.RxBus;
import io.socket.client.Ack;
public class NSAuthAck extends Event implements Ack {
private final RxBus rxBus;
public boolean read = false;
public boolean write = false;
public boolean write_treatment = false;
public NSAuthAck(RxBus rxBus) {
this.rxBus = rxBus;
}
public void call(Object... args) {
JSONObject response = (JSONObject) args[0];
read = response.optBoolean("read");
write = response.optBoolean("write");
write_treatment = response.optBoolean("write_treatment");
rxBus.send(this);
}
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.plugins.bus.RxBus
import io.socket.client.Ack
import org.json.JSONObject
class NSAuthAck(private val rxBus: RxBus) : Event(), Ack {
var read = false
var write = false
var writeTreatment = false
override fun call(vararg args: Any) {
val response = args[0] as JSONObject
read = response.optBoolean("read")
write = response.optBoolean("write")
writeTreatment = response.optBoolean("write_treatment")
rxBus.send(this)
}
}

View file

@ -199,16 +199,16 @@ class NSClientService : DaggerService() {
var connectionStatus = "Authenticated ("
if (ack.read) connectionStatus += "R"
if (ack.write) connectionStatus += "W"
if (ack.write_treatment) connectionStatus += "T"
if (ack.writeTreatment) connectionStatus += "T"
connectionStatus += ')'
isConnected = true
hasWriteAuth = ack.write && ack.write_treatment
hasWriteAuth = ack.write && ack.writeTreatment
rxBus.send(EventNSClientStatus(connectionStatus))
rxBus.send(EventNSClientNewLog("AUTH", connectionStatus))
if (!ack.write) {
rxBus.send(EventNSClientNewLog("ERROR", "Write permission not granted "))
}
if (!ack.write_treatment) {
if (!ack.writeTreatment) {
rxBus.send(EventNSClientNewLog("ERROR", "Write treatment permission not granted "))
}
if (!hasWriteAuth) {

View file

@ -53,20 +53,6 @@ class OverviewData @Inject constructor(
private val translator: Translator
) {
enum class Property {
TIME,
CALC_PROGRESS,
PROFILE,
TEMPORARY_BASAL,
EXTENDED_BOLUS,
TEMPORARY_TARGET,
BG,
IOB_COB,
SENSITIVITY,
GRAPH,
PUMPSTATUS
}
var rangeToDisplay = 6 // for graph
var toTime: Long = 0
var fromTime: Long = 0

View file

@ -45,6 +45,7 @@ import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnitsString
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
@ -54,7 +55,7 @@ import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCh
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverview
import info.nightscout.androidaps.plugins.general.overview.events.*
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
@ -189,7 +190,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
overviewData.initRange()
overviewData.prepareBucketedData("EventBucketedDataCreated")
overviewData.prepareBgData("EventBucketedDataCreated")
updateGUI("rangeChange", OverviewData.Property.GRAPH)
updateGraph("rangeChange")
rxBus.send(EventPreferenceChange(rh, R.string.key_rangetodisplay))
sp.putBoolean(R.string.key_objectiveusescale, true)
false
@ -226,41 +227,93 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
override fun onResume() {
super.onResume()
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverview::class.java)
.toObservable(EventUpdateOverviewTime::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGUI(it.from, it.what) }, fabricPrivacy::logException)
disposable.add(rxBus
.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)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewIobCob::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.subscribe({ updateIobCob(it.from) }, fabricPrivacy::logException)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewSensitivity::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.subscribe({ updateSensitivity(it.from) }, fabricPrivacy::logException)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewGraph::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGraph(it.from) }, fabricPrivacy::logException)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewPumpStatus::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updatePumpStatus(it.from) }, fabricPrivacy::logException)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewNotification::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateNotification(it.from) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventRefreshOverview::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
if (it.now) overviewPlugin.refreshLoop(it.from)
else scheduleUpdateGUI(it.from)
}, fabricPrivacy::logException))
disposable.add(rxBus
if (it.now) overviewPlugin.refreshLoop(it.from)
else scheduleUpdateGUI(it.from)
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAcceptOpenLoopChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ scheduleUpdateGUI("EventAcceptOpenLoopChange") }, fabricPrivacy::logException))
disposable.add(rxBus
.subscribe({ scheduleUpdateGUI("EventAcceptOpenLoopChange") }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventInitializationChanged::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGUI("EventInitializationChanged", OverviewData.Property.TIME) }, fabricPrivacy::logException))
disposable.add(rxBus
.subscribe({ updateTime("EventInitializationChanged") }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ scheduleUpdateGUI("EventPreferenceChange") }, fabricPrivacy::logException))
disposable.add(rxBus
.subscribe({ scheduleUpdateGUI("EventPreferenceChange") }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNewOpenLoopNotification::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ scheduleUpdateGUI("EventNewOpenLoopNotification") }, fabricPrivacy::logException))
.subscribe({ scheduleUpdateGUI("EventNewOpenLoopNotification") }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPumpStatusChanged::class.java)
.observeOn(aapsSchedulers.main)
.delay (30, TimeUnit.MILLISECONDS, aapsSchedulers.main)
.delay(30, TimeUnit.MILLISECONDS, aapsSchedulers.main)
.subscribe({
overviewData.pumpStatus = it.getStatus(rh)
updateGUI("EventPumpStatusChanged", OverviewData.Property.PUMPSTATUS)
}, fabricPrivacy::logException)
overviewData.pumpStatus = it.getStatus(rh)
updatePumpStatus("EventPumpStatusChanged")
}, fabricPrivacy::logException)
refreshLoop = Runnable {
overviewPlugin.refreshLoop("refreshLoop")
@ -268,7 +321,17 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
handler.postDelayed(refreshLoop, 60 * 1000L)
for (p in OverviewData.Property.values()) updateGUI("onResume", p)
updateTime("onResume")
updateCalcProgress("onResume")
updateProfile("onResume")
updateTemporaryBasal("onResume")
updateExtendedBolus("onResume")
updateTemporaryTarget("onResume")
updateBg("onResume")
updateIobCob("onResume")
updateSensitivity("onResume")
updateGraph("onResume")
updatePumpStatus("onResume")
}
@Synchronized
@ -283,12 +346,27 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (childFragmentManager.isStateSaved) return
activity?.let { activity ->
when (v.id) {
R.id.treatment_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") })
R.id.wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") })
R.id.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") })
R.id.treatment_button -> protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") })
R.id.wizard_button -> protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") })
R.id.insulin_button -> protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") })
R.id.quick_wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) onClickQuickWizard() })
R.id.carbs_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") })
R.id.temp_target -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") })
R.id.carbs_button -> protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") })
R.id.temp_target -> protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") })
R.id.active_profile -> {
ProfileViewerDialog().also { pvd ->
@ -335,12 +413,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), {
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
Thread { loopPlugin.acceptChangeRequest() }.run()
})
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
Thread { loopPlugin.acceptChangeRequest() }.run()
})
})
}
}
@ -390,7 +468,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
R.id.temp_target -> v.performClick()
R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") }) }
R.id.active_profile -> activity?.let { activity ->
protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") })
}
}
return false
@ -453,7 +536,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
// **** Various treatment buttons ****
binding.buttonsLayout.carbsButton.visibility = ((!activePlugin.activePump.pumpDescription.storesCarbInfo || pump.isInitialized() && !pump.isSuspended()) && profile != null && sp.getBoolean(R.string.key_show_carbs_button, true)).toVisibility()
binding.buttonsLayout.carbsButton.visibility =
((!activePlugin.activePump.pumpDescription.storesCarbInfo || pump.isInitialized() && !pump.isSuspended()) && profile != null && sp.getBoolean(
R.string.key_show_carbs_button,
true
)).toVisibility()
binding.buttonsLayout.treatmentButton.visibility = (pump.isInitialized() && !pump.isSuspended() && profile != null && sp.getBoolean(R.string.key_show_treatment_button, false)).toVisibility()
binding.buttonsLayout.wizardButton.visibility = (pump.isInitialized() && !pump.isSuspended() && profile != null && sp.getBoolean(R.string.key_show_wizard_button, true)).toVisibility()
binding.buttonsLayout.insulinButton.visibility = (pump.isInitialized() && !pump.isSuspended() && profile != null && sp.getBoolean(R.string.key_show_insulin_button, true)).toVisibility()
@ -520,13 +607,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
pump.isSuspended() -> {
binding.infoLayout.apsMode.setImageResource(if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab
R.drawable.ic_loop_disconnected
} else {
R.drawable.ic_loop_paused
})
binding.infoLayout.apsMode.setImageResource(
if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab
R.drawable.ic_loop_disconnected
} else {
R.drawable.ic_loop_paused
}
)
binding.infoLayout.apsModeText.visibility = View.GONE
}
@ -582,7 +671,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val graph = GraphView(context)
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(skinProvider.activeSkin().secondaryGraphHeight)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
graph.layoutParams =
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(skinProvider.activeSkin().secondaryGraphHeight)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
graph.gridLabelRenderer?.gridColor = rh.gc(R.color.graphgrid)
graph.gridLabelRenderer?.reloadStyles()
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
@ -620,269 +710,283 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
task?.let { handler.postDelayed(it, 500) }
}
@Suppress("UNUSED_PARAMETER")
@SuppressLint("SetTextI18n")
fun updateGUI(from: String, what: OverviewData.Property) {
// if (what != OverviewData.Property.CALC_PROGRESS)
// aapsLogger.debug(LTag.UI, "UpdateGui $from $what")
if (profileFunction.getProfile() == null) {
binding.activeProfile.setText(R.string.noprofileset)
binding.activeProfile.setBackgroundColor(rh.gc(R.color.errorAlertBackground))
return
}
binding.notifications.let { notificationStore.updateNotifications(it) }
@Suppress("UNUSED_PARAMETER")
fun updateBg(from: String) {
val units = profileFunction.getUnits()
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
?: rh.gs(R.string.notavailable)
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor)
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.deltaLarge.setTextColor(overviewData.lastBgColor)
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
} else {
binding.infoLayout.deltaLarge.text = ""
binding.infoLayout.delta.text = "Δ " + rh.gs(R.string.notavailable)
binding.infoLayout.avgDelta.text = ""
binding.infoLayout.longAvgDelta.text = ""
}
// strike through if BG is old
binding.infoLayout.bg.paintFlags =
if (!overviewData.isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else binding.infoLayout.bg.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon)
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
}
} else {
binding.infoLayout.bgQuality.visibility = View.GONE
}
}
@Suppress("UNUSED_PARAMETER")
fun updateProfile(from: String) {
val profileBackgroundColor =
profileFunction.getProfile()?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
rh.gc(R.color.ribbonWarning)
else rh.gc(R.color.ribbonDefault)
} else if (it is ProfileSealed.PS) {
rh.gc(R.color.ribbonDefault)
} else {
rh.gc(R.color.ribbonDefault)
}
} ?: rh.gc(R.color.ribbonCritical)
val profileTextColor =
profileFunction.getProfile()?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
rh.gc(R.color.ribbonTextWarning)
else rh.gc(R.color.ribbonTextDefault)
} else if (it is ProfileSealed.PS) {
rh.gc(R.color.ribbonTextDefault)
} else {
rh.gc(R.color.ribbonTextDefault)
}
} ?: rh.gc(R.color.ribbonTextDefault)
binding.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
binding.activeProfile.setBackgroundColor(profileBackgroundColor)
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)
binding.infoLayout.basalLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText) }
}
}
@Suppress("UNUSED_PARAMETER")
fun updateExtendedBolus(from: String) {
val pump = activePlugin.activePump
when (what) {
OverviewData.Property.BG -> {
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
?: rh.gs(R.string.notavailable)
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor)
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText
binding.infoLayout.extendedLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText) }
}
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
}
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.deltaLarge.setTextColor(overviewData.lastBgColor)
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
} else {
binding.infoLayout.deltaLarge.text = ""
binding.infoLayout.delta.text = "Δ " + rh.gs(R.string.notavailable)
binding.infoLayout.avgDelta.text = ""
binding.infoLayout.longAvgDelta.text = ""
@Suppress("UNUSED_PARAMETER")
fun updateTime(from: String) {
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
// Status lights
binding.statusLightsLayout.statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
statusLightHandler.updateStatusLights(
binding.statusLightsLayout.cannulaAge,
binding.statusLightsLayout.insulinAge,
binding.statusLightsLayout.reservoirLevel,
binding.statusLightsLayout.sensorAge,
null,
binding.statusLightsLayout.pbAge,
binding.statusLightsLayout.batteryLevel
)
processButtonsVisibility()
processAps()
}
@Suppress("UNUSED_PARAMETER")
fun updateIobCob(from: String) {
binding.infoLayout.iob.text = overviewData.iobText
binding.infoLayout.iobLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText) }
}
// cob
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
val constraintsProcessed = loopPlugin.lastRun?.constraintsProcessed
val lastRun = loopPlugin.lastRun
if (config.APS && constraintsProcessed != null && lastRun != null) {
if (constraintsProcessed.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently
if (overviewData.lastCarbsTime < lastRun.lastAPSRun) {
cobText += " | " + constraintsProcessed.carbsReq + " " + rh.gs(R.string.required)
}
// strike through if BG is old
binding.infoLayout.bg.paintFlags =
if (!overviewData.isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else binding.infoLayout.bg.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon)
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
}
} else {
binding.infoLayout.bgQuality.visibility = View.GONE
}
if (carbAnimation?.isRunning == false)
carbAnimation?.start()
} else {
carbAnimation?.stop()
carbAnimation?.selectDrawable(0)
}
}
binding.infoLayout.cob.text = cobText
}
OverviewData.Property.PROFILE -> {
val profileBackgroundColor =
profileFunction.getProfile()?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
rh.gc(R.color.ribbonWarning)
else rh.gc(R.color.ribbonDefault)
} else if (it is ProfileSealed.PS) {
rh.gc(R.color.ribbonDefault)
} else {
rh.gc(R.color.ribbonDefault)
}
} ?: rh.gc(R.color.ribbonCritical)
@SuppressLint("SetTextI18n")
@Suppress("UNUSED_PARAMETER")
fun updateTemporaryTarget(from: String) {
val units = profileFunction.getUnits()
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
val tempTarget = overviewData.temporaryTarget
if (tempTarget != null) {
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextWarning))
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonWarning))
binding.tempTarget.text = Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
} else {
// If the target is not the same as set in the profile then oref has overridden it
profileFunction.getProfile()?.let { profile ->
val targetUsed = loopPlugin.lastRun?.constraintsProcessed?.targetBG ?: 0.0
val profileTextColor =
profileFunction.getProfile()?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
rh.gc(R.color.ribbonTextWarning)
else rh.gc(R.color.ribbonTextDefault)
}else if (it is ProfileSealed.PS) {
rh.gc(R.color.ribbonTextDefault)
} else {
rh.gc(R.color.ribbonTextDefault)
}
} ?: rh.gc(R.color.ribbonTextDefault)
binding.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
binding.activeProfile.setBackgroundColor(profileBackgroundColor)
binding.activeProfile.setTextColor(profileTextColor)
}
OverviewData.Property.TEMPORARY_BASAL -> {
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor)
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon)
binding.infoLayout.basalLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText) }
}
}
OverviewData.Property.EXTENDED_BOLUS -> {
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText
binding.infoLayout.extendedLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText) }
}
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
}
OverviewData.Property.TIME -> {
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
// Status lights
binding.statusLightsLayout.statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
statusLightHandler.updateStatusLights(binding.statusLightsLayout.cannulaAge, binding.statusLightsLayout.insulinAge, binding.statusLightsLayout.reservoirLevel, binding.statusLightsLayout.sensorAge, null, binding.statusLightsLayout.pbAge, binding.statusLightsLayout.batteryLevel)
processButtonsVisibility()
processAps()
}
OverviewData.Property.IOB_COB -> {
binding.infoLayout.iob.text = overviewData.iobText
binding.infoLayout.iobLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText) }
}
// cob
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
val constraintsProcessed = loopPlugin.lastRun?.constraintsProcessed
val lastRun = loopPlugin.lastRun
if (config.APS && constraintsProcessed != null && lastRun != null) {
if (constraintsProcessed.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently
if (overviewData.lastCarbsTime < lastRun.lastAPSRun) {
cobText += " | " + constraintsProcessed.carbsReq + " " + rh.gs(R.string.required)
}
if (carbAnimation?.isRunning == false)
carbAnimation?.start()
} else {
carbAnimation?.stop()
carbAnimation?.selectDrawable(0)
}
}
binding.infoLayout.cob.text = cobText
}
OverviewData.Property.TEMPORARY_TARGET -> {
// temp target
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
val tempTarget = overviewData.temporaryTarget
if (tempTarget != null) {
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
binding.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextWarning))
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonWarning))
binding.tempTarget.text = Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
binding.tempTarget.setBackgroundColor(rh.gc(R.color.tempTargetBackground))
} else {
// If the target is not the same as set in the profile then oref has overridden it
profileFunction.getProfile()?.let { profile ->
val targetUsed = loopPlugin.lastRun?.constraintsProcessed?.targetBG ?: 0.0
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
binding.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextWarning))
binding.tempTarget.setBackgroundColor(rh.gc(R.color.tempTargetBackground))
} else {
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextDefault))
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonDefault))
binding.tempTarget.text = Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
}
}
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextDefault))
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonDefault))
binding.tempTarget.text = Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
}
}
OverviewData.Property.GRAPH -> {
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
val menuChartSettings = overviewMenus.setting
graphData.addInRangeArea(overviewData.fromTime, overviewData.endTime, defaultValueHelper.determineLowLine(), defaultValueHelper.determineHighLine())
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
if (buildHelper.isDev()) graphData.addBucketedData()
graphData.addTreatments()
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
graphData.addActivity(0.8)
if ((pump.pumpDescription.isTempBasalCapable || config.NSCLIENT) && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
graphData.addBasals()
graphData.addTargetLine()
graphData.addNowLine(dateUtil.now())
// set manual x bounds to have nice steps
graphData.setNumVerticalLabels()
graphData.formatAxis(overviewData.fromTime, overviewData.endTime)
graphData.performUpdate()
// 2nd graphs
prepareGraphsIfNeeded(menuChartSettings.size)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
val now = System.currentTimeMillis()
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
val secondGraphData = GraphData(injector, secondaryGraphs[g], overviewData)
var useABSForScale = false
var useIobForScale = false
var useCobForScale = false
var useDevForScale = false
var useRatioForScale = false
var useDSForScale = false
var useBGIForScale = false
when {
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
}
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(useABSForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(useIobForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(useCobForScale, if (useCobForScale) 1.0 else 0.5)
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(useDevForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8)
if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(useRatioForScale, if (useRatioForScale) 1.0 else 0.8)
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(useDSForScale, if(useDSForScale) 1.0 else 0.8, useRatioForScale)
// set manual x bounds to have nice steps
secondGraphData.formatAxis(overviewData.fromTime, overviewData.endTime)
secondGraphData.addNowLine(now)
secondaryGraphsData.add(secondGraphData)
}
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
secondaryGraphs[g].visibility = (
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
).toVisibility()
secondaryGraphsData[g].performUpdate()
}
}
OverviewData.Property.CALC_PROGRESS -> {
binding.graphsLayout.iobCalculationProgress.text = overviewData.calcProgress
}
OverviewData.Property.SENSITIVITY -> {
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 {
binding.infoLayout.sensitivityIcon.setImageResource(R.drawable.ic_x_swap_vert)
}
binding.infoLayout.sensitivity.text =
overviewData.lastAutosensData?.let { autosensData ->
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
} ?: ""
}
OverviewData.Property.PUMPSTATUS -> {
val status = overviewData.pumpStatus
binding.pumpStatus.text = status
binding.pumpStatusLayout.visibility = (status != "").toVisibility()
}
}
}
@Suppress("UNUSED_PARAMETER")
fun updateGraph(from: String) {
val pump = activePlugin.activePump
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
val menuChartSettings = overviewMenus.setting
graphData.addInRangeArea(overviewData.fromTime, overviewData.endTime, defaultValueHelper.determineLowLine(), defaultValueHelper.determineHighLine())
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
if (buildHelper.isDev()) graphData.addBucketedData()
graphData.addTreatments()
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
graphData.addActivity(0.8)
if ((pump.pumpDescription.isTempBasalCapable || config.NSCLIENT) && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
graphData.addBasals()
graphData.addTargetLine()
graphData.addNowLine(dateUtil.now())
// set manual x bounds to have nice steps
graphData.setNumVerticalLabels()
graphData.formatAxis(overviewData.fromTime, overviewData.endTime)
graphData.performUpdate()
// 2nd graphs
prepareGraphsIfNeeded(menuChartSettings.size)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
val now = System.currentTimeMillis()
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
val secondGraphData = GraphData(injector, secondaryGraphs[g], overviewData)
var useABSForScale = false
var useIobForScale = false
var useCobForScale = false
var useDevForScale = false
var useRatioForScale = false
var useDSForScale = false
var useBGIForScale = false
when {
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
}
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(useABSForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(useIobForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(useCobForScale, if (useCobForScale) 1.0 else 0.5)
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(useDevForScale, 1.0)
if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8)
if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(useRatioForScale, if (useRatioForScale) 1.0 else 0.8)
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(
useDSForScale,
if (useDSForScale) 1.0 else 0.8,
useRatioForScale
)
// set manual x bounds to have nice steps
secondGraphData.formatAxis(overviewData.fromTime, overviewData.endTime)
secondGraphData.addNowLine(now)
secondaryGraphsData.add(secondGraphData)
}
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
secondaryGraphs[g].visibility = (
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
).toVisibility()
secondaryGraphsData[g].performUpdate()
}
}
@Suppress("UNUSED_PARAMETER")
fun updateCalcProgress(from: String) {
binding.graphsLayout.iobCalculationProgress.text = overviewData.calcProgress
}
@Suppress("UNUSED_PARAMETER")
fun updateSensitivity(from: String) {
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 {
binding.infoLayout.sensitivityIcon.setImageResource(R.drawable.ic_x_swap_vert)
}
binding.infoLayout.sensitivity.text =
overviewData.lastAutosensData?.let { autosensData ->
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
} ?: ""
}
@Suppress("UNUSED_PARAMETER")
fun updatePumpStatus(from: String) {
val status = overviewData.pumpStatus
binding.pumpStatus.text = status
binding.pumpStatusLayout.visibility = (status != "").toVisibility()
}
@Suppress("UNUSED_PARAMETER")
fun updateNotification(from: String) {
binding.notifications.let { notificationStore.updateNotifications(it) }
}
}

View file

@ -13,9 +13,7 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
import info.nightscout.androidaps.plugins.bus.RxBus
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.EventUpdateOverview
import info.nightscout.androidaps.plugins.general.overview.events.*
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
@ -48,7 +46,8 @@ class OverviewPlugin @Inject constructor(
private val repository: AppRepository,
private val overviewData: OverviewData,
private val overviewMenus: OverviewMenus
) : PluginBase(PluginDescription()
) : PluginBase(
PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(OverviewFragment::class.qualifiedName)
.alwaysVisible(true)
@ -58,7 +57,7 @@ class OverviewPlugin @Inject constructor(
.shortName(R.string.overview_shortname)
.preferencesId(R.xml.pref_overview)
.description(R.string.description_overview),
aapsLogger, rh, injector
aapsLogger, rh, injector
), Overview {
private var disposable: CompositeDisposable = CompositeDisposable()
@ -74,97 +73,97 @@ class OverviewPlugin @Inject constructor(
notificationStore.createNotificationChannel()
disposable += rxBus
.toObservable(EventNewNotification::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ n ->
if (notificationStore.add(n.notification))
rxBus.send(EventRefreshOverview("EventNewNotification"))
}, fabricPrivacy::logException)
.toObservable(EventNewNotification::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ n ->
if (notificationStore.add(n.notification))
rxBus.send(EventUpdateOverviewNotification("EventNewNotification"))
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventDismissNotification::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ n ->
if (notificationStore.remove(n.id))
rxBus.send(EventRefreshOverview("EventDismissNotification"))
}, fabricPrivacy::logException)
.toObservable(EventDismissNotification::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ n ->
if (notificationStore.remove(n.id))
rxBus.send(EventUpdateOverviewNotification("EventDismissNotification"))
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventIobCalculationProgress::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ overviewData.calcProgress = it.progress; overviewBus.send(EventUpdateOverview("EventIobCalculationProgress", OverviewData.Property.CALC_PROGRESS)) }, fabricPrivacy::logException)
.toObservable(EventIobCalculationProgress::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ overviewData.calcProgress = it.progress; overviewBus.send(EventUpdateOverviewCalcProgress("EventIobCalculationProgress")) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTempBasalChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ overviewBus.send(EventUpdateOverview("EventTempBasalChange", OverviewData.Property.TEMPORARY_BASAL)) }, fabricPrivacy::logException)
.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(EventUpdateOverview("EventExtendedBolusChange", OverviewData.Property.EXTENDED_BOLUS)) }, fabricPrivacy::logException)
.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)
.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)
.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(EventUpdateOverview("EventTreatmentChange", OverviewData.Property.GRAPH))
}, fabricPrivacy::logException)
.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(EventUpdateOverview("EventTherapyEventChange", OverviewData.Property.GRAPH))
}, fabricPrivacy::logException)
.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(EventUpdateOverview("EventBucketedDataCreated", OverviewData.Property.GRAPH))
}, fabricPrivacy::logException)
.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)
.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)
.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")
}, fabricPrivacy::logException)
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
if (it.cause !is EventCustomCalculationFinished) refreshLoop("EventAutosensCalculationFinished")
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPumpStatusChanged::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
overviewData.pumpStatus = it.getStatus(rh)
}, fabricPrivacy::logException)
.toObservable(EventPumpStatusChanged::class.java)
.observeOn(aapsSchedulers.io)
.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(EventUpdateOverview("EventBucketedDataCreated", OverviewData.Property.GRAPH))
loadAll("EventPreferenceChange")
}
}, fabricPrivacy::logException)
.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()
}
@ -189,58 +188,58 @@ class OverviewPlugin @Inject constructor(
}
override fun configuration(): JSONObject =
JSONObject()
.putString(R.string.key_units, sp, rh)
.putString(R.string.key_quickwizard, sp, rh)
.putInt(R.string.key_eatingsoon_duration, sp, rh)
.putDouble(R.string.key_eatingsoon_target, sp, rh)
.putInt(R.string.key_activity_duration, sp, rh)
.putDouble(R.string.key_activity_target, sp, rh)
.putInt(R.string.key_hypo_duration, sp, rh)
.putDouble(R.string.key_hypo_target, sp, rh)
.putDouble(R.string.key_low_mark, sp, rh)
.putDouble(R.string.key_high_mark, sp, rh)
.putDouble(R.string.key_statuslights_cage_warning, sp, rh)
.putDouble(R.string.key_statuslights_cage_critical, sp, rh)
.putDouble(R.string.key_statuslights_iage_warning, sp, rh)
.putDouble(R.string.key_statuslights_iage_critical, sp, rh)
.putDouble(R.string.key_statuslights_sage_warning, sp, rh)
.putDouble(R.string.key_statuslights_sage_critical, sp, rh)
.putDouble(R.string.key_statuslights_sbat_warning, sp, rh)
.putDouble(R.string.key_statuslights_sbat_critical, sp, rh)
.putDouble(R.string.key_statuslights_bage_warning, sp, rh)
.putDouble(R.string.key_statuslights_bage_critical, sp, rh)
.putDouble(R.string.key_statuslights_res_warning, sp, rh)
.putDouble(R.string.key_statuslights_res_critical, sp, rh)
.putDouble(R.string.key_statuslights_bat_warning, sp, rh)
.putDouble(R.string.key_statuslights_bat_critical, sp, rh)
JSONObject()
.putString(R.string.key_units, sp, rh)
.putString(R.string.key_quickwizard, sp, rh)
.putInt(R.string.key_eatingsoon_duration, sp, rh)
.putDouble(R.string.key_eatingsoon_target, sp, rh)
.putInt(R.string.key_activity_duration, sp, rh)
.putDouble(R.string.key_activity_target, sp, rh)
.putInt(R.string.key_hypo_duration, sp, rh)
.putDouble(R.string.key_hypo_target, sp, rh)
.putDouble(R.string.key_low_mark, sp, rh)
.putDouble(R.string.key_high_mark, sp, rh)
.putDouble(R.string.key_statuslights_cage_warning, sp, rh)
.putDouble(R.string.key_statuslights_cage_critical, sp, rh)
.putDouble(R.string.key_statuslights_iage_warning, sp, rh)
.putDouble(R.string.key_statuslights_iage_critical, sp, rh)
.putDouble(R.string.key_statuslights_sage_warning, sp, rh)
.putDouble(R.string.key_statuslights_sage_critical, sp, rh)
.putDouble(R.string.key_statuslights_sbat_warning, sp, rh)
.putDouble(R.string.key_statuslights_sbat_critical, sp, rh)
.putDouble(R.string.key_statuslights_bage_warning, sp, rh)
.putDouble(R.string.key_statuslights_bage_critical, sp, rh)
.putDouble(R.string.key_statuslights_res_warning, sp, rh)
.putDouble(R.string.key_statuslights_res_critical, sp, rh)
.putDouble(R.string.key_statuslights_bat_warning, sp, rh)
.putDouble(R.string.key_statuslights_bat_critical, sp, rh)
override fun applyConfiguration(configuration: JSONObject) {
configuration
.storeString(R.string.key_units, sp, rh)
.storeString(R.string.key_quickwizard, sp, rh)
.storeInt(R.string.key_eatingsoon_duration, sp, rh)
.storeDouble(R.string.key_eatingsoon_target, sp, rh)
.storeInt(R.string.key_activity_duration, sp, rh)
.storeDouble(R.string.key_activity_target, sp, rh)
.storeInt(R.string.key_hypo_duration, sp, rh)
.storeDouble(R.string.key_hypo_target, sp, rh)
.storeDouble(R.string.key_low_mark, sp, rh)
.storeDouble(R.string.key_high_mark, sp, rh)
.storeDouble(R.string.key_statuslights_cage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_cage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_iage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_iage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_sage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_sage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_sbat_warning, sp, rh)
.storeDouble(R.string.key_statuslights_sbat_critical, sp, rh)
.storeDouble(R.string.key_statuslights_bage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_bage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_res_warning, sp, rh)
.storeDouble(R.string.key_statuslights_res_critical, sp, rh)
.storeDouble(R.string.key_statuslights_bat_warning, sp, rh)
.storeDouble(R.string.key_statuslights_bat_critical, sp, rh)
.storeString(R.string.key_units, sp, rh)
.storeString(R.string.key_quickwizard, sp, rh)
.storeInt(R.string.key_eatingsoon_duration, sp, rh)
.storeDouble(R.string.key_eatingsoon_target, sp, rh)
.storeInt(R.string.key_activity_duration, sp, rh)
.storeDouble(R.string.key_activity_target, sp, rh)
.storeInt(R.string.key_hypo_duration, sp, rh)
.storeDouble(R.string.key_hypo_target, sp, rh)
.storeDouble(R.string.key_low_mark, sp, rh)
.storeDouble(R.string.key_high_mark, sp, rh)
.storeDouble(R.string.key_statuslights_cage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_cage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_iage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_iage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_sage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_sage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_sbat_warning, sp, rh)
.storeDouble(R.string.key_statuslights_sbat_critical, sp, rh)
.storeDouble(R.string.key_statuslights_bage_warning, sp, rh)
.storeDouble(R.string.key_statuslights_bage_critical, sp, rh)
.storeDouble(R.string.key_statuslights_res_warning, sp, rh)
.storeDouble(R.string.key_statuslights_res_critical, sp, rh)
.storeDouble(R.string.key_statuslights_bat_warning, sp, rh)
.storeDouble(R.string.key_statuslights_bat_critical, sp, rh)
}
@Volatile
@ -248,22 +247,23 @@ class OverviewPlugin @Inject constructor(
override fun refreshLoop(from: String) {
if (runningRefresh) return
runningRefresh = true
overviewBus.send(EventUpdateOverviewNotification(from))
loadIobCobResults(from)
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.PROFILE))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.BG))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.TIME))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.TEMPORARY_BASAL))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.EXTENDED_BOLUS))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.TEMPORARY_TARGET))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.SENSITIVITY))
overviewBus.send(EventUpdateOverviewProfile(from))
overviewBus.send(EventUpdateOverviewBg(from))
overviewBus.send(EventUpdateOverviewTime(from))
overviewBus.send(EventUpdateOverviewTemporaryBasal(from))
overviewBus.send(EventUpdateOverviewExtendedBolus(from))
overviewBus.send(EventUpdateOverviewTemporaryTarget(from))
overviewBus.send(EventUpdateOverviewSensitivity(from))
loadAsData(from)
overviewData.preparePredictions(from)
overviewData.prepareBasalData(from)
overviewData.prepareTemporaryTargetData(from)
overviewData.prepareTreatmentsData(from)
overviewData.prepareIobAutosensData(from)
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.GRAPH))
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.IOB_COB))
overviewBus.send(EventUpdateOverviewGraph(from))
overviewBus.send(EventUpdateOverviewIobCob(from))
aapsLogger.debug(LTag.UI, "refreshLoop finished")
runningRefresh = false
}
@ -280,31 +280,31 @@ class OverviewPlugin @Inject constructor(
overviewData.prepareTreatmentsData(from)
// prepareIobAutosensData(from)
// preparePredictions(from)
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.GRAPH))
overviewBus.send(EventUpdateOverviewGraph(from))
aapsLogger.debug(LTag.UI, "loadAll finished")
}
private fun loadProfile(from: String) {
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.PROFILE))
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(EventUpdateOverview(from, OverviewData.Property.TEMPORARY_TARGET))
overviewBus.send(EventUpdateOverviewTemporaryTarget(from))
}
private fun loadAsData(from: String) {
overviewData.lastAutosensData = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.SENSITIVITY))
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(EventUpdateOverview(from, OverviewData.Property.BG))
overviewBus.send(EventUpdateOverviewBg(from))
}
private fun loadIobCobResults(from: String) {
@ -314,7 +314,7 @@ class OverviewPlugin @Inject constructor(
val lastCarbs = repository.getLastCarbsRecordWrapped().blockingGet()
overviewData.lastCarbsTime = if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
overviewBus.send(EventUpdateOverview(from, OverviewData.Property.IOB_COB))
overviewBus.send(EventUpdateOverviewIobCob(from))
}
}

View file

@ -1,6 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.plugins.general.overview.OverviewData
class EventUpdateOverview(val from: String, val what: OverviewData.Property) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewBg(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewCalcProgress(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewExtendedBolus(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewGraph(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewIobCob(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewNotification(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewProfile(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewPumpStatus(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewSensitivity(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewTemporaryBasal(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewTemporaryTarget(val from: String) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview.events
import info.nightscout.androidaps.events.Event
class EventUpdateOverviewTime(val from: String) : Event()

View file

@ -37,6 +37,9 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONArray
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.floor
@ -126,12 +129,7 @@ class IobCobCalculatorPlugin @Inject constructor(
disposable += rxBus
.toObservable(EventNewHistoryData::class.java)
.observeOn(aapsSchedulers.io)
.subscribe(
{ event ->
newHistoryData(event.oldDataTimestamp, event.reloadBgData, if (event.newestGlucoseValue != null) EventNewBG(event.newestGlucoseValue) else event)
},
fabricPrivacy::logException
)
.subscribe({ event -> scheduleHistoryDataChange(event) }, fabricPrivacy::logException)
}
override fun onStop() {
@ -389,6 +387,44 @@ class IobCobCalculatorPlugin @Inject constructor(
}
}
// Limit rate of EventNewHistoryData
private val historyWorker = Executors.newSingleThreadScheduledExecutor()
private var scheduledHistoryPost: ScheduledFuture<*>? = null
private var scheduledEvent: EventNewHistoryData? = null
@Synchronized
private fun scheduleHistoryDataChange(event: EventNewHistoryData) {
// if there is nothing scheduled or asking reload deeper to the past
if (scheduledEvent == null || event.oldDataTimestamp < (scheduledEvent?.oldDataTimestamp) ?: 0L) {
// cancel waiting task to prevent sending multiple posts
scheduledHistoryPost?.cancel(false)
// prepare task for execution in 1 sec
scheduledEvent = event
scheduledHistoryPost = historyWorker.schedule({
synchronized(this) {
aapsLogger.debug(LTag.DATABASE, "Running newHistoryData")
newHistoryData(
event.oldDataTimestamp,
event.reloadBgData,
if (event.newestGlucoseValue != null) EventNewBG(event.newestGlucoseValue) else event
)
scheduledEvent = null
scheduledHistoryPost = null
}
}, 1L, TimeUnit.SECONDS)
} else {
// asked reload is newer -> adjust params only
scheduledEvent?.let {
// set reload bg data if was not set
if (!it.reloadBgData) it.reloadBgData = event.reloadBgData
// set Glucose value if newer
event.newestGlucoseValue?.let { gv ->
if (gv.timestamp > (it.newestGlucoseValue?.timestamp ?: 0L)) it.newestGlucoseValue = gv
}
}
}
}
// 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");

View file

@ -6,7 +6,7 @@ import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import java.text.DateFormat
class EventNewHistoryData(val oldDataTimestamp: Long, val reloadBgData: Boolean, val newestGlucoseValue : GlucoseValue? = null) : Event() {
class EventNewHistoryData(val oldDataTimestamp: Long, var reloadBgData: Boolean, var newestGlucoseValue : GlucoseValue? = null) : Event() {
override fun toString(): String {
return super.toString() +

View file

@ -52,7 +52,7 @@
android:gravity="center_vertical|center_horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:text="TempTarget"
android:text="@string/notavailable"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"
tools:ignore="HardcodedText" />

View file

@ -224,7 +224,6 @@
<string name="profile_carbs_per_unit">g/U</string>
<!-- ProfileFunction-->
<string name="noprofileselected">No profile selected</string>
<string name="startprofile">Start profile %1$d%% for %2$d min</string>
<!-- PumpType-->