AndroidAPS/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt

388 lines
18 KiB
Kotlin
Raw Normal View History

2020-12-25 16:47:42 +01:00
package info.nightscout.androidaps.dialogs
2021-01-01 11:37:24 +01:00
import android.content.Context
2020-12-26 17:40:16 +01:00
import android.content.Intent
2020-12-25 16:47:42 +01:00
import android.os.Bundle
2021-01-01 16:44:25 +01:00
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
2020-12-25 16:47:42 +01:00
import androidx.fragment.app.FragmentManager
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.activities.ErrorHelperActivity
2020-12-27 16:20:32 +01:00
import info.nightscout.androidaps.databinding.DialogLoopBinding
2021-01-01 16:44:25 +01:00
import info.nightscout.androidaps.events.*
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.interfaces.*
2020-12-25 16:47:42 +01:00
import info.nightscout.androidaps.logging.AAPSLogger
2021-02-09 17:57:28 +01:00
import info.nightscout.androidaps.logging.UserEntryLogger
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
2020-12-25 16:47:42 +01:00
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils
2020-12-26 17:40:16 +01:00
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
2020-12-28 12:21:31 +01:00
import info.nightscout.androidaps.utils.extensions.toVisibility
2020-12-25 16:47:42 +01:00
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class LoopDialog : DaggerDialogFragment() {
@Inject lateinit var aapsLogger: AAPSLogger
2021-01-01 11:37:24 +01:00
@Inject lateinit var ctx: Context
2020-12-25 16:47:42 +01:00
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
2020-12-26 17:40:16 +01:00
@Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var objectivesPlugin: ObjectivesPlugin
2020-12-25 16:47:42 +01:00
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var constraintChecker: ConstraintChecker
2020-12-26 17:40:16 +01:00
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
2021-02-09 17:57:28 +01:00
@Inject lateinit var uel: UserEntryLogger
2020-12-25 16:47:42 +01:00
2020-12-26 17:40:16 +01:00
private var showOkCancel: Boolean = true
2020-12-27 16:20:32 +01:00
private var _binding: DialogLoopBinding? = null
2021-01-01 16:44:25 +01:00
private var loopHandler = Handler()
private var refreshDialog: Runnable? = null
2020-12-27 16:20:32 +01:00
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
2020-12-26 17:40:16 +01:00
2020-12-25 16:47:42 +01:00
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
2020-12-26 17:40:16 +01:00
savedInstanceState.putInt("showOkCancel", if (showOkCancel) 1 else 0)
2020-12-25 16:47:42 +01:00
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
2020-12-28 12:21:31 +01:00
savedInstanceState: Bundle?): View {
2020-12-26 17:40:16 +01:00
// load data from bundle
(savedInstanceState ?: arguments)?.let { bundle ->
showOkCancel = bundle.getInt("showOkCancel", 1) == 1
}
2020-12-25 16:47:42 +01:00
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
2020-12-27 16:20:32 +01:00
_binding = DialogLoopBinding.inflate(inflater, container, false)
return binding.root
2020-12-25 16:47:42 +01:00
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
2020-12-26 17:40:16 +01:00
updateGUI("LoopDialogOnViewCreated")
2020-12-28 12:21:31 +01:00
binding.overviewCloseloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewLgsloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewOpenloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisable.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewEnable.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewResume.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewReconnect.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewSuspend1h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewSuspend2h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewSuspend3h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewSuspend10h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisconnect15m.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisconnect30m.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisconnect1h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisconnect2h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
binding.overviewDisconnect3h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() }
2020-12-25 16:47:42 +01:00
// cancel button
2020-12-27 16:20:32 +01:00
binding.cancel.setOnClickListener { dismiss() }
2020-12-25 16:47:42 +01:00
2021-01-01 16:44:25 +01:00
refreshDialog = Runnable {
scheduleUpdateGUI("refreshDialog")
loopHandler.postDelayed(refreshDialog, 15 * 1000L)
}
loopHandler.postDelayed(refreshDialog, 15 * 1000L)
2020-12-25 16:47:42 +01:00
}
2020-12-28 12:21:31 +01:00
@Synchronized
2020-12-25 16:47:42 +01:00
override fun onDestroyView() {
super.onDestroyView()
2020-12-28 12:21:31 +01:00
_binding = null
2021-01-01 16:44:25 +01:00
loopHandler.removeCallbacksAndMessages(null)
}
var task: Runnable? = null
private fun scheduleUpdateGUI(from: String) {
class UpdateRunnable : Runnable {
override fun run() {
updateGUI(from)
task = null
}
}
view?.removeCallbacks(task)
task = UpdateRunnable()
view?.postDelayed(task, 500)
2020-12-25 16:47:42 +01:00
}
2020-12-28 12:21:31 +01:00
@Synchronized
2020-12-26 17:40:16 +01:00
fun updateGUI(from: String) {
2020-12-28 12:21:31 +01:00
if (_binding == null) return
2020-12-26 17:40:16 +01:00
aapsLogger.debug("UpdateGUI from $from")
val pumpDescription: PumpDescription = activePlugin.activePump.pumpDescription
val closedLoopAllowed = objectivesPlugin.isClosedLoopAllowed(Constraint(true))
val lgsEnabled = objectivesPlugin.isLgsAllowed(Constraint(true))
2020-12-28 12:21:31 +01:00
val apsMode = sp.getString(R.string.key_aps_mode, "open")
2020-12-26 17:40:16 +01:00
if (profileFunction.isProfileValid("LoopDialogUpdateGUI")) {
if (loopPlugin.isEnabled(PluginType.LOOP)) {
2020-12-28 12:21:31 +01:00
when {
closedLoopAllowed.value() -> {
binding.overviewCloseloop.visibility = (apsMode != "closed").toVisibility()
binding.overviewLgsloop.visibility = (apsMode != "lgs").toVisibility()
binding.overviewOpenloop.visibility = (apsMode != "open").toVisibility()
}
lgsEnabled.value() -> {
binding.overviewCloseloop.visibility = View.GONE
binding.overviewLgsloop.visibility = (apsMode != "lgs").toVisibility()
binding.overviewOpenloop.visibility = (apsMode != "open").toVisibility()
}
else -> {
binding.overviewCloseloop.visibility = View.GONE
binding.overviewLgsloop.visibility = View.GONE
binding.overviewOpenloop.visibility = View.GONE
}
}
2020-12-28 12:21:31 +01:00
binding.overviewEnable.visibility = View.GONE
2020-12-27 16:20:32 +01:00
binding.overviewDisable.visibility = View.VISIBLE
2020-12-28 12:21:31 +01:00
if (!loopPlugin.isSuspended) {
binding.overviewSuspendHeader.text = resourceHelper.gs(R.string.suspendloop)
2020-12-27 16:20:32 +01:00
binding.overviewResume.visibility = View.GONE
2020-12-28 12:21:31 +01:00
binding.overviewSuspendButtons.visibility = View.VISIBLE
binding.overviewSuspend.visibility = View.VISIBLE
2020-12-26 17:40:16 +01:00
} else {
if (!loopPlugin.isDisconnected) {
2020-12-27 16:20:32 +01:00
binding.overviewSuspendHeader.text = resourceHelper.gs(R.string.resumeloop)
binding.overviewResume.visibility = View.VISIBLE
2020-12-28 12:21:31 +01:00
binding.overviewSuspendButtons.visibility = View.GONE
binding.overviewSuspend.visibility = View.VISIBLE
2020-12-26 17:40:16 +01:00
} else
2020-12-27 16:20:32 +01:00
binding.overviewSuspend.visibility = View.GONE
2020-12-26 17:40:16 +01:00
}
} else {
2020-12-27 16:20:32 +01:00
binding.overviewEnable.visibility = View.VISIBLE
binding.overviewDisable.visibility = View.GONE
binding.overviewSuspend.visibility = View.GONE
2020-12-26 17:40:16 +01:00
}
if (!loopPlugin.isDisconnected) {
2020-12-27 16:20:32 +01:00
binding.overviewPumpHeader.text = resourceHelper.gs(R.string.disconnectpump)
2020-12-28 12:21:31 +01:00
binding.overviewDisconnect15m.visibility = pumpDescription.tempDurationStep15mAllowed.toVisibility()
binding.overviewDisconnect30m.visibility = pumpDescription.tempDurationStep30mAllowed.toVisibility()
2020-12-27 16:20:32 +01:00
binding.overviewDisconnectButtons.visibility = View.VISIBLE
binding.overviewReconnect.visibility = View.GONE
2020-12-26 17:40:16 +01:00
} else {
2020-12-27 16:20:32 +01:00
binding.overviewPumpHeader.text = resourceHelper.gs(R.string.reconnect)
binding.overviewDisconnectButtons.visibility = View.GONE
binding.overviewReconnect.visibility = View.VISIBLE
2020-12-26 17:40:16 +01:00
}
2020-12-25 16:47:42 +01:00
}
val profile = profileFunction.getProfile()
val profileStore = activePlugin.activeProfileInterface.profile
if (profile == null || profileStore == null) {
2021-01-01 11:37:24 +01:00
ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile))
2020-12-25 16:47:42 +01:00
dismiss()
return
}
}
2021-01-01 11:37:24 +01:00
private fun onClickOkCancelEnabled(v: View): Boolean {
2020-12-26 17:40:16 +01:00
var description = ""
2020-12-28 12:21:31 +01:00
when (v.id) {
R.id.overview_closeloop -> description = resourceHelper.gs(R.string.closedloop)
R.id.overview_lgsloop -> description = resourceHelper.gs(R.string.lowglucosesuspend)
R.id.overview_openloop -> description = resourceHelper.gs(R.string.openloop)
R.id.overview_disable -> description = resourceHelper.gs(R.string.disableloop)
R.id.overview_enable -> description = resourceHelper.gs(R.string.enableloop)
R.id.overview_resume -> description = resourceHelper.gs(R.string.resume)
R.id.overview_reconnect -> description = resourceHelper.gs(R.string.reconnect)
R.id.overview_suspend_1h -> description = resourceHelper.gs(R.string.suspendloopfor1h)
R.id.overview_suspend_2h -> description = resourceHelper.gs(R.string.suspendloopfor2h)
R.id.overview_suspend_3h -> description = resourceHelper.gs(R.string.suspendloopfor3h)
R.id.overview_suspend_10h -> description = resourceHelper.gs(R.string.suspendloopfor10h)
R.id.overview_disconnect_15m -> description = resourceHelper.gs(R.string.disconnectpumpfor15m)
R.id.overview_disconnect_30m -> description = resourceHelper.gs(R.string.disconnectpumpfor30m)
R.id.overview_disconnect_1h -> description = resourceHelper.gs(R.string.disconnectpumpfor1h)
R.id.overview_disconnect_2h -> description = resourceHelper.gs(R.string.disconnectpumpfor2h)
R.id.overview_disconnect_3h -> description = resourceHelper.gs(R.string.disconnectpumpfor3h)
2020-12-26 17:40:16 +01:00
}
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.confirm), description, Runnable {
onClick(v)
})
2020-12-25 16:47:42 +01:00
}
2020-12-26 17:40:16 +01:00
return true
}
2020-12-25 16:47:42 +01:00
2020-12-26 17:40:16 +01:00
fun onClick(v: View): Boolean {
val profile = profileFunction.getProfile() ?: return true
when (v.id) {
R.id.overview_closeloop -> {
2021-02-09 17:57:28 +01:00
uel.log("CLOSED LOOP MODE")
sp.putString(R.string.key_aps_mode, "closed")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop)))
2020-12-28 12:21:31 +01:00
return true
}
2020-12-28 12:21:31 +01:00
R.id.overview_lgsloop -> {
2021-02-09 17:57:28 +01:00
uel.log("LGS LOOP MODE")
sp.putString(R.string.key_aps_mode, "lgs")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
2020-12-28 12:21:31 +01:00
return true
}
2020-12-28 12:21:31 +01:00
R.id.overview_openloop -> {
2021-02-09 17:57:28 +01:00
uel.log("OPEN LOOP MODE")
sp.putString(R.string.key_aps_mode, "open")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
2020-12-28 12:21:31 +01:00
return true
}
2020-12-28 12:21:31 +01:00
R.id.overview_disable -> {
2021-02-09 17:57:28 +01:00
uel.log("LOOP DISABLED")
2020-12-26 17:40:16 +01:00
loopPlugin.setPluginEnabled(PluginType.LOOP, false)
loopPlugin.setFragmentVisible(PluginType.LOOP, false)
configBuilderPlugin.storeSettings("DisablingLoop")
rxBus.send(EventRefreshOverview("suspendmenu"))
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (!result.success) {
2021-01-01 11:37:24 +01:00
ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.tempbasaldeliveryerror))
2020-12-26 17:40:16 +01:00
}
}
})
loopPlugin.createOfflineEvent(24 * 60) // upload 24h, we don't know real duration
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_enable -> {
2021-02-09 17:57:28 +01:00
uel.log("LOOP ENABLED")
2020-12-26 17:40:16 +01:00
loopPlugin.setPluginEnabled(PluginType.LOOP, true)
loopPlugin.setFragmentVisible(PluginType.LOOP, true)
configBuilderPlugin.storeSettings("EnablingLoop")
rxBus.send(EventRefreshOverview("suspendmenu"))
loopPlugin.createOfflineEvent(0)
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_resume, R.id.overview_reconnect -> {
2021-02-09 17:57:28 +01:00
uel.log("RESUME")
2020-12-26 17:40:16 +01:00
loopPlugin.suspendTo(0L)
rxBus.send(EventRefreshOverview("suspendmenu"))
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (!result.success) {
2021-01-01 11:37:24 +01:00
val i = Intent(ctx, ErrorHelperActivity::class.java)
2020-12-26 17:40:16 +01:00
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
2021-01-01 11:37:24 +01:00
ctx.startActivity(i)
2020-12-26 17:40:16 +01:00
}
}
})
sp.putBoolean(R.string.key_objectiveusereconnect, true)
loopPlugin.createOfflineEvent(0)
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_suspend_1h -> {
2021-02-09 17:57:28 +01:00
uel.log("SUSPEND 1h")
2020-12-26 17:40:16 +01:00
loopPlugin.suspendLoop(60)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_suspend_2h -> {
2021-02-09 17:57:28 +01:00
uel.log("SUSPEND 2h")
2020-12-26 17:40:16 +01:00
loopPlugin.suspendLoop(120)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_suspend_3h -> {
2021-02-09 17:57:28 +01:00
uel.log("SUSPEND 3h")
2020-12-26 17:40:16 +01:00
loopPlugin.suspendLoop(180)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_suspend_10h -> {
2021-02-09 17:57:28 +01:00
uel.log("SUSPEND 10h")
2020-12-26 17:40:16 +01:00
loopPlugin.suspendLoop(600)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_disconnect_15m -> {
2021-02-09 17:57:28 +01:00
uel.log("DISCONNECT 15m")
2020-12-26 17:40:16 +01:00
loopPlugin.disconnectPump(15, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_disconnect_30m -> {
2021-02-09 17:57:28 +01:00
uel.log("DISCONNECT 30m")
2020-12-26 17:40:16 +01:00
loopPlugin.disconnectPump(30, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
2020-12-25 16:47:42 +01:00
R.id.overview_disconnect_1h -> {
2021-02-09 17:57:28 +01:00
uel.log("DISCONNECT 1h")
2020-12-26 17:40:16 +01:00
loopPlugin.disconnectPump(60, profile)
sp.putBoolean(R.string.key_objectiveusedisconnect, true)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
2020-12-25 16:47:42 +01:00
}
R.id.overview_disconnect_2h -> {
2021-02-09 17:57:28 +01:00
uel.log("DISCONNECT 2h")
2020-12-26 17:40:16 +01:00
loopPlugin.disconnectPump(120, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
2020-12-25 16:47:42 +01:00
}
R.id.overview_disconnect_3h -> {
2021-02-09 17:57:28 +01:00
uel.log("DISCONNECT 3h")
2020-12-26 17:40:16 +01:00
loopPlugin.disconnectPump(180, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
2020-12-25 16:47:42 +01:00
}
}
2020-12-26 17:40:16 +01:00
return false
2020-12-25 16:47:42 +01:00
}
override fun show(manager: FragmentManager, tag: String?) {
try {
manager.beginTransaction().let {
it.add(this, tag)
it.commitAllowingStateLoss()
}
} catch (e: IllegalStateException) {
aapsLogger.debug(e.localizedMessage)
}
}
}