Merge branch 'dev' into rxjava3

This commit is contained in:
Milos Kozak 2022-02-17 21:45:20 +01:00
commit e27bb2d04c
209 changed files with 5717 additions and 1549 deletions

View file

@ -4,11 +4,16 @@
[![Support Server](https://img.shields.io/discord/629952586895851530.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge)](https://discord.gg/4fQUWHZ4Mw)
[![Build status](https://travis-ci.org/nightscout/AndroidAPS.svg?branch=master)](https://travis-ci.org/nightscout/AndroidAPS)
[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/master.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/master)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/androidaps/localized.svg)](https://translations.androidaps.org/project/androidaps)
[![Documentation Status](https://readthedocs.org/projects/androidaps/badge/?version=latest)](https://androidaps.readthedocs.io/en/latest/?badge=latest)
[![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
dev: [![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
DEV:
[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev)
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
![BTC](https://bitit.io/assets/coins/icon-btc-1e5a37bc0eb730ac83130d7aa859052bd4b53ac3f86f99966627801f7b0410be.svg) 3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2
<img src="https://cdn.iconscout.com/icon/free/png-256/bitcoin-384-920569.png" srcset="https://cdn.iconscout.com/icon/free/png-512/bitcoin-384-920569.png 2x" alt="Bitcoin Icon" width="100">
3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2

File diff suppressed because it is too large Load diff

View file

@ -239,6 +239,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
}
binding.age.editText?.id?.let { binding.ageLabel.labelFor = it }
binding.tdd.editText?.id?.let { binding.tddLabel.labelFor = it }
binding.weight.editText?.id?.let { binding.weightLabel.labelFor = it }
binding.basalpctfromtdd.editText?.id?.let { binding.basalpctfromtddLabel.labelFor = it }
switchTab(0, typeSelected[0], false)
}

View file

@ -271,6 +271,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
_binding = null
}
private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.let { it.timestamp } ?: ml.bolus?.let { it.timestamp } ?: ml.carbs?.let { it.timestamp } ?: 0L
inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder =
@ -280,16 +282,20 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
val profile = profileFunction.getProfile() ?: return
val ml = mealLinks[position]
val sameDayPrevious = position > 0 && dateUtil.isSameDay(timestamp(ml), timestamp(mealLinks[position - 1]))
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(timestamp(ml))
// Metadata
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.bolusCalculatorResult?.let { bolusCalculatorResult ->
holder.binding.date.text = dateUtil.dateAndTimeString(bolusCalculatorResult.timestamp)
holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp)
}
// Bolus
holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.bolus?.let { bolus ->
holder.binding.bolusDate.text = dateUtil.timeString(bolus.timestamp)
holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp)
holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount)
holder.binding.bolusNs.visibility = (bolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility()
@ -317,7 +323,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
// Carbs
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.carbs?.let { carbs ->
holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp)
holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp)
holder.binding.carbs.text = rh.gs(R.string.format_carbs, carbs.amount.toInt())
holder.binding.carbsDuration.text = if (carbs.duration > 0) rh.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) else ""
holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility()
@ -330,6 +336,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
holder.binding.bolusRemove.tag = ml
holder.binding.carbsRemove.tag = ml
holder.binding.calculation.tag = ml
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {

View file

@ -152,7 +152,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
_binding = null
}
inner class RecyclerViewAdapter internal constructor(private var list: List<TherapyEvent>) : RecyclerView.Adapter<TherapyEventsViewHolder>() {
inner class RecyclerViewAdapter internal constructor(private var therapyList: List<TherapyEvent>) : RecyclerView.Adapter<TherapyEventsViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TherapyEventsViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_careportal_item, viewGroup, false)
@ -160,18 +160,23 @@ class TreatmentsCareportalFragment : DaggerFragment() {
}
override fun onBindViewHolder(holder: TherapyEventsViewHolder, position: Int) {
val therapyEvent = list[position]
val therapyEvent = therapyList[position]
holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(therapyEvent.timestamp)
val sameDayPrevious = position > 0 && dateUtil.isSameDay(therapyEvent.timestamp, therapyList[position - 1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(therapyEvent.timestamp)
holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp)
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
holder.binding.note.text = therapyEvent.note
holder.binding.type.text = translator.translate(therapyEvent.type)
holder.binding.remove.tag = therapyEvent
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {
return list.size
return therapyList.size
}
inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) {

View file

@ -125,13 +125,16 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position-1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp)
@SuppressLint("SetTextI18n")
if (extendedBolus.isInProgress(dateUtil)) {
holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp)
holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp)
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
} else {
holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) + " - " + dateUtil.timeString(extendedBolus.end)
holder.binding.date.setTextColor(holder.binding.insulin.currentTextColor)
holder.binding.time.text = dateUtil.timeRangeString(extendedBolus.timestamp, extendedBolus.end)
holder.binding.time.setTextColor(holder.binding.insulin.currentTextColor)
}
val profile = profileFunction.getProfile(extendedBolus.timestamp) ?: return
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(extendedBolus.duration).mins())
@ -141,6 +144,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
holder.binding.remove.tag = extendedBolus
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int = extendedBolusList.size

View file

@ -181,7 +181,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
val profileSwitch = profileSwitchList[position]
holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(profileSwitch.timestamp)
val sameDayPrevious = position > 0 && dateUtil.isSameDay(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp)
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
@ -196,6 +199,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.root.setBackgroundColor(rh.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter))
val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {

View file

@ -164,18 +164,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
holder.binding.remove.visibility = tempTarget.isValid.toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.timestamp) + " - " + dateUtil.timeString(tempTarget.end)
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position-1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp)
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
holder.binding.high.text = tempTarget.highValueToUnitsToString(units)
holder.binding.reason.text = translator.translate(tempTarget.reason)
holder.binding.date.setTextColor(
holder.binding.time.setTextColor(
when {
tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive)
tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
else -> holder.binding.reasonColon.currentTextColor
})
holder.binding.remove.tag = tempTarget
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int = tempTargetList.size

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
@ -165,12 +164,15 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility()
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position-1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp)
if (tempBasal.isInProgress) {
holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.timestamp)
holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp)
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
} else {
holder.binding.date.text = dateUtil.dateAndTimeRangeString(tempBasal.timestamp, tempBasal.end)
holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.time.text = dateUtil.timeRangeString(tempBasal.timestamp, tempBasal.end)
holder.binding.time.setTextColor(holder.binding.duration.currentTextColor)
}
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempBasal.duration).mins())
if (tempBasal.isAbsolute) holder.binding.rate.text = rh.gs(R.string.pump_basebasalrate, tempBasal.rate)
@ -186,6 +188,9 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.remove.tag = tempBasal
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int = tempBasalList.size

View file

@ -20,6 +20,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
@ -131,14 +132,19 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
val current = entries[position]
holder.binding.date.text = dateUtil.dateAndTimeAndSecondsString(current.timestamp)
val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position-1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(current.timestamp)
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action)
holder.binding.s.text = current.note
holder.binding.s.visibility = if (current.note != "") View.VISIBLE else View.GONE
holder.binding.notes.text = current.note
holder.binding.notes.visibility = if (current.note != "") View.VISIBLE else View.GONE
holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source))
holder.binding.iconSource.visibility = View.VISIBLE
holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values)
holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE
val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(current.timestamp, nextTimestamp).toVisibility()
}
inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalAdapterAM
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.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
@ -19,6 +20,7 @@ abstract class APSModule {
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
}

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
@ -212,6 +213,12 @@ abstract class PluginsModule {
@IntKey(220)
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(222)
abstract fun bindOpenAPSSMBAutoISFPlugin(plugin: OpenAPSSMBDynamicISFPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap

View file

@ -64,6 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
binding.units.text = if (units == GlucoseUnit.MMOL) rh.gs(R.string.mmol) else rh.gs(R.string.mgdl)
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -137,32 +137,39 @@ class CarbsDialog : DialogFragmentWithDate() {
savedInstanceState?.getDouble("carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
)
binding.plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
val plus1text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
binding.plus1.text = plus1text
binding.plus1.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus1text
binding.plus1.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
binding.plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
val plus2text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
binding.plus2.text = plus2text
binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus2text
binding.plus2.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
binding.plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
val plus3text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
binding.plus3.text = plus3text
binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus3text
binding.plus3.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
setOnValueChangedListener { eventTime: Long ->
@ -188,6 +195,9 @@ class CarbsDialog : DialogFragmentWithDate() {
binding.hypoTt.isChecked = false
binding.activityTt.isChecked = false
}
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -165,6 +165,8 @@ class CareDialog : DialogFragmentWithDate() {
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -70,6 +70,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
binding.duration.setParams(savedInstanceState?.getDouble("duration")
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -96,7 +96,7 @@ class FillDialog : DialogFragmentWithDate() {
} else {
binding.fillPresetButton3.visibility = View.GONE
}
binding.fillInsulinamount.editText?.id?.let { binding.fillLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -116,29 +116,40 @@ class InsulinDialog : DialogFragmentWithDate() {
binding.amount.setParams(savedInstanceState?.getDouble("amount")
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.plus05.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
val plus05Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus05.text = plus05Text
binding.plus05.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus05Text
binding.plus05.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.plus10.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
val plus10Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus10.text = plus10Text
binding.plus10.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus10Text
binding.plus10.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.plus20.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
val plus20Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus20.text = plus20Text
binding.plus20.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus20Text
binding.plus20.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.timeLayout.visibility = View.GONE
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
binding.timeLayout.visibility = isChecked.toVisibility()
}
binding.amount.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -148,6 +148,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
}
}
binding.ttLayout.visibility = View.GONE
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.percentage.editText?.id?.let { binding.percentageLabel.labelFor = it }
binding.timeshift.editText?.id?.let { binding.timeshiftLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -86,6 +86,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
binding.percentLayout.visibility = View.GONE
binding.absoluteLayout.visibility = View.VISIBLE
}
binding.basalPercentInput.editText?.id?.let { binding.basalPercentLabel.labelFor = it }
binding.basalAbsoluteInput.editText?.id?.let { binding.basalAbsoluteLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -120,6 +120,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
longClick(it)
return@setOnLongClickListener true
}
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.temptarget.editText?.id?.let { binding.temptargetLabel.labelFor = it }
}
}

View file

@ -106,6 +106,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.recordOnlyLayout.visibility = View.GONE
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -4,11 +4,7 @@ import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.view.*
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter
@ -136,33 +132,36 @@ class WizardDialog : DaggerDialogFragment() {
val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
bolusStep = activePlugin.activePump.pumpDescription.bolusStep
if (profileFunction.getUnits() == GlucoseUnit.MGDL)
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input")
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher)
else
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input")
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.ok, textWatcher)
if (profileFunction.getUnits() == GlucoseUnit.MGDL) {
binding.bgInput.setParams(
savedInstanceState?.getDouble("bg_input")
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher)
} else {
binding.bgInput.setParams(
savedInstanceState?.getDouble("bg_input")
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, textWatcher)
}
binding.carbsInput.setParams(savedInstanceState?.getDouble("carbs_input")
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.ok, textWatcher)
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
if (correctionPercent) {
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.ok, textWatcher)
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.value = calculatedPercentage
binding.correctionUnit.text = "%"
} else {
binding.correctionInput.setParams(
savedInstanceState?.getDouble("correction_input")
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher)
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.correctionUnit.text = rh.gs(R.string.insulin_unit_shortname)
}
binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input")
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher)
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher)
initDialog()
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
// ok button
binding.ok.setOnClickListener {
binding.okcancel.ok.setOnClickListener {
if (okClicked) {
aapsLogger.debug(LTag.UI, "guarding: ok already clicked")
} else {
@ -175,12 +174,12 @@ class WizardDialog : DaggerDialogFragment() {
}
dismiss()
}
binding.bgEnabledIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked }
binding.trendEnabledIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked }
binding.cobEnabledIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); }
binding.iobEnabledIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked }
binding.bgCheckboxIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked }
binding.trendCheckboxIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked }
binding.cobCheckboxIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); }
binding.iobCheckboxIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked }
// cancel button
binding.cancel.setOnClickListener {
binding.okcancel.cancel.setOnClickListener {
aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}")
dismiss()
}
@ -212,11 +211,17 @@ class WizardDialog : DaggerDialogFragment() {
sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked)
binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname)
correctionPercent = binding.correctionPercent.isChecked
if (correctionPercent)
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.ok, textWatcher)
else
binding.correctionInput.setParams(savedInstanceState?.getDouble("correction_input")
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher)
if (correctionPercent) {
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_percentage)
} else {
binding.correctionInput.setParams(
savedInstanceState?.getDouble("correction_input")
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher
)
binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_units)
}
binding.correctionInput.updateA11yDescription()
binding.correctionInput.value = if (correctionPercent) calculatedPercentage else Round.roundTo(calculatedCorrection, bolusStep)
}
}
@ -224,12 +229,12 @@ class WizardDialog : DaggerDialogFragment() {
binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileset))
binding.ok.visibility = View.GONE
binding.okcancel.ok.visibility = View.GONE
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
calculateInsulin()
binding.ok.visibility = View.VISIBLE
binding.okcancel.ok.visibility = View.VISIBLE
}
}
// bus
@ -241,6 +246,14 @@ class WizardDialog : DaggerDialogFragment() {
}, fabricPrivacy::logException)
)
setA11yLabels()
}
private fun setA11yLabels() {
binding.bgInput.editText?.id?.let { binding.bgInputLabel.labelFor = it }
binding.carbsInput.editText?.id?.let { binding.carbsInputLabel.labelFor = it }
binding.correctionInput.editText?.id?.let { binding.correctionInputLabel.labelFor = it }
binding.carbTimeInput.editText?.id?.let { binding.carbTimeInputLabel.labelFor = it }
}
override fun onDestroyView() {
@ -261,21 +274,29 @@ class WizardDialog : DaggerDialogFragment() {
private fun processCobCheckBox() {
if (binding.cobCheckbox.isChecked) {
binding.iobCheckbox.isEnabled = false
binding.iobCheckboxIcon.isEnabled = false
binding.iobCheckbox.isChecked = true
} else {
binding.iobCheckbox.isEnabled = true
binding.iobCheckboxIcon.isEnabled = true
}
}
private fun processEnabledIcons() {
binding.bgEnabledIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f
binding.trendEnabledIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f
binding.iobEnabledIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f
binding.cobEnabledIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f
binding.bgEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.trendEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.iobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.cobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.bgCheckboxIcon.isChecked = binding.bgCheckbox.isChecked
binding.trendCheckboxIcon.isChecked = binding.bgTrendCheckbox.isChecked
binding.iobCheckboxIcon.isChecked = binding.iobCheckbox.isChecked
binding.cobCheckboxIcon.isChecked = binding.cobCheckbox.isChecked
binding.bgCheckboxIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f
binding.trendCheckboxIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f
binding.iobCheckboxIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f
binding.cobCheckboxIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f
binding.bgCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
}
private fun saveCheckedStates() {
@ -442,10 +463,10 @@ class WizardDialog : DaggerDialogFragment() {
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin).formatColor(rh, R.color.bolus) else ""
val carbsText = if (carbsAfterConstraint > 0.0) rh.gs(R.string.format_carbs, carbsAfterConstraint).formatColor(rh, R.color.carbs) else ""
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.result_insulin_carbs, insulinText, carbsText))
binding.ok.visibility = View.VISIBLE
binding.okcancel.ok.visibility = View.VISIBLE
} else {
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()).formatColor(rh, R.color.carbs))
binding.ok.visibility = View.INVISIBLE
binding.okcancel.ok.visibility = View.INVISIBLE
}
binding.percentUsed.text = rh.gs(R.string.format_percent, wizard.percentageCorrection)
calculatedPercentage = wizard.calculatedPercentage

View file

@ -69,13 +69,15 @@ class WizardInfoDialog : DaggerDialogFragment() {
binding.close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits()
val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
val isf = Profile.toUnits(data.isf, data.isf * Constants.MGDL_TO_MMOLL, units)
val trend = Profile.toUnitsString(data.glucoseTrend * 3, data.glucoseTrend * 3 * Constants.MGDL_TO_MMOLL, units)
// BG
binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, data.isf)
binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, isf)
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)
binding.bgCheckbox.isChecked = data.wasGlucoseUsed
binding.ttCheckbox.isChecked = data.wasTempTargetUsed
// Trend
binding.bgTrend.text = DecimalFormatter.to1Decimal(data.glucoseTrend)
binding.bgTrend.text = trend
binding.bgTrendInsulin.text = rh.gs(R.string.formatinsulinunits, data.trendInsulin)
binding.bgTrendCheckbox.isChecked = data.wasTrendUsed
// COB

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
@ -14,6 +15,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -30,7 +32,7 @@ import java.nio.charset.StandardCharsets
import javax.inject.Inject
import kotlin.math.min
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) {
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
private val injector: HasAndroidInjector
@ -48,21 +50,15 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
private var currentTemp = JSONObject()
private var autosensData = JSONObject()
var currentTempParam: String? = null
private set
var iobDataParam: String? = null
private set
var glucoseStatusParam: String? = null
private set
var profileParam: String? = null
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultAMA? {
override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -143,18 +139,25 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
}
@Suppress("SpellCheckingInspection")
@Throws(JSONException::class) fun setData(profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean) {
@Throws(JSONException::class)
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
this.profile = JSONObject()
this.profile.put("max_iob", maxIob)
this.profile.put("dia", min(profile.dia, 3.0))

View file

@ -96,7 +96,7 @@ class OpenAPSAMAFragment : DaggerFragment() {
binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned()
}
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
openAPSAMAPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterAMAJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
try {

View file

@ -60,8 +60,8 @@ class OpenAPSAMAPlugin @Inject constructor(
// last values
override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultAMA? = null
var lastDetermineBasalAdapterAMAJS: DetermineBasalAdapterAMAJS? = null
var lastAutosensResult: AutosensResult = AutosensResult()
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
override var lastAutosensResult: AutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean {
return try {
@ -158,7 +158,7 @@ class OpenAPSAMAPlugin @Inject constructor(
// Fix bug determine basal
if (determineBasalResultAMA == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterAMAJS = null
lastDetermineBasalAdapter = null
lastAPSResult = null
lastAPSRun = 0
} else {
@ -167,8 +167,8 @@ class OpenAPSAMAPlugin @Inject constructor(
val now = System.currentTimeMillis()
determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultAMA.inputConstraints = inputConstraints
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA
lastDetermineBasalAdapter = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA as DetermineBasalResultAMA
lastAPSRun = now
}
rxBus.send(EventOpenAPSUpdateGui())

View file

@ -7,14 +7,11 @@ import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin
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.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
@ -31,7 +28,7 @@ import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) {
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@ -51,21 +48,16 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
private var smbAlwaysAllowed = false
private var currentTime: Long = 0
private var saveCgmSource = false
var currentTempParam: String? = null
private set
var iobDataParam: String? = null
private set
var glucoseStatusParam: String? = null
private set
var profileParam: String? = null
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultSMB? {
override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -155,22 +147,24 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
return determineBasalResultSMB
}
@Suppress("SpellCheckingInspection") fun setData(profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
@Suppress("SpellCheckingInspection")
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep

View file

@ -10,6 +10,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
private var eventualBG = 0.0
private var snoozeBG = 0.0
var variableSens: Double? = null
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
date = dateUtil.now()
@ -50,6 +51,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
}
}
if (result.has("variable_sens")) variableSens = result.getDouble("variable_sens");
} catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
}

View file

@ -9,8 +9,7 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.bus.RxBus
@ -19,6 +18,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
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 org.json.JSONArray
@ -34,7 +35,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Inject lateinit var rxBus: RxBus
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var jsonFormatter: JSONFormatter
@ -44,8 +45,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
return binding.root
}
@ -54,7 +54,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState)
binding.run.setOnClickListener {
openAPSSMBPlugin.invoke("OpenAPSSMB button", false)
activePlugin.activeAPS.invoke("OpenAPSSMB button", false)
}
}
@ -92,11 +92,12 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Synchronized
fun updateGUI() {
if (_binding == null) return
val openAPSSMBPlugin = activePlugin.activeAPS
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned()
}
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
openAPSSMBPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterSMBJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
try {

View file

@ -10,8 +10,6 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.extensions.target
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.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
@ -24,6 +22,8 @@ import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@ -37,7 +37,7 @@ class OpenAPSSMBPlugin @Inject constructor(
private val constraintChecker: ConstraintChecker,
rh: ResourceHelper,
private val profileFunction: ProfileFunction,
private val context: Context,
val context: Context,
private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator,
private val hardLimits: HardLimits,
@ -46,23 +46,24 @@ class OpenAPSSMBPlugin @Inject constructor(
private val dateUtil: DateUtil,
private val repository: AppRepository,
private val glucoseStatusProvider: GlucoseStatusProvider
) : PluginBase(PluginDescription()
.mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name)
.pluginIcon(R.drawable.ic_generic_icon)
.pluginName(R.string.openapssmb)
.shortName(R.string.smb_shortname)
.preferencesId(R.xml.pref_openapssmb)
.description(R.string.description_smb)
.setDefault(),
) : PluginBase(
PluginDescription()
.mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name)
.pluginIcon(R.drawable.ic_generic_icon)
.pluginName(R.string.openapssmb)
.shortName(R.string.smb_shortname)
.preferencesId(R.xml.pref_openapssmb)
.description(R.string.description_smb)
.setDefault(),
aapsLogger, rh, injector
), APS, Constraints {
// last values
override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultSMB? = null
var lastDetermineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS? = null
var lastAutosensResult = AutosensResult()
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
override var lastAutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean {
return try {
@ -120,15 +121,34 @@ class OpenAPSSMBPlugin @Inject constructor(
}.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1])
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1])
var maxBg =
hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1])
var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1])
var isTempTarget = false
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
maxBg = hardLimits.verifyHardLimits(tempTarget.value.highTarget, R.string.temp_target_high_target, HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
targetBg = hardLimits.verifyHardLimits(tempTarget.value.target(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
minBg =
hardLimits.verifyHardLimits(
tempTarget.value.lowTarget,
R.string.temp_target_low_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()
)
maxBg =
hardLimits.verifyHardLimits(
tempTarget.value.highTarget,
R.string.temp_target_high_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()
)
targetBg =
hardLimits.verifyHardLimits(
tempTarget.value.target(),
R.string.temp_target_value,
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()
)
}
if (!hardLimits.checkHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
@ -165,8 +185,9 @@ class OpenAPSSMBPlugin @Inject constructor(
profiler.log(LTag.APS, "SMB data gathering", start)
start = System.currentTimeMillis()
DetermineBasalAdapterSMBJS(ScriptReader(context), injector).also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg,
provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(
profile, maxIob, maxBasal, minBg, maxBg, targetBg,
activePlugin.activePump.baseBasalRate,
iobArray,
glucoseStatus,
@ -176,24 +197,26 @@ class OpenAPSSMBPlugin @Inject constructor(
smbAllowed.value(),
uam.value(),
advancedFiltering.value(),
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin")
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin"
)
val now = System.currentTimeMillis()
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
profiler.log(LTag.APS, "SMB calculation", start)
if (determineBasalResultSMB == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterSMBJS = null
lastDetermineBasalAdapter = null
lastAPSResult = null
lastAPSRun = 0
} else {
// TODO still needed with oref1?
// Fix bug determine basal
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested = false
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested =
false
determineBasalResultSMB.iob = iobArray[0]
determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultSMB.inputConstraints = inputConstraints
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB
lastDetermineBasalAdapter = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB as DetermineBasalResultSMB
lastAPSRun = now
}
}
@ -204,4 +227,6 @@ class OpenAPSSMBPlugin @Inject constructor(
value.set(aapsLogger, false)
return value
}
fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBJS(ScriptReader(context), injector)
}

View file

@ -0,0 +1,296 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin
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.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var sp: SP
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var tddCalculator: TddCalculator
private var profile = JSONObject()
private var mGlucoseStatus = JSONObject()
private var iobData: JSONArray? = null
private var mealData = JSONObject()
private var currentTemp = JSONObject()
private var autosensData = JSONObject()
private var microBolusAllowed = false
private var smbAlwaysAllowed = false
private var currentTime: Long = 0
private var saveCgmSource = false
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
override operator fun invoke(): DetermineBasalResultSMB? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it })
aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it })
aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it })
aapsLogger.debug(LTag.APS, "Autosens data: $autosensData")
aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined")
aapsLogger.debug(LTag.APS, "MicroBolusAllowed: $microBolusAllowed")
aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: $smbAlwaysAllowed")
aapsLogger.debug(LTag.APS, "CurrentTime: $currentTime")
aapsLogger.debug(LTag.APS, "isSaveCgmSource: $saveCgmSource")
var determineBasalResultSMB: DetermineBasalResultSMB? = null
val rhino = Context.enter()
val scope: Scriptable = rhino.initStandardObjects()
// Turn off optimization to make Rhino Android compatible
rhino.optimizationLevel = -1
try {
//register logger callback for console.log and console.error
ScriptableObject.defineClass(scope, LoggerCallback::class.java)
val myLogger = rhino.newObject(scope, "LoggerCallback", null)
scope.put("console2", scope, myLogger)
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null)
//set module parent
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null)
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null)
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null)
//generate functions "determine_basal" and "setTempBasal"
rhino.evaluateString(scope, readFile("OpenAPSSMBDynamicISF/determine-basal.js"), "JavaScript", 0, null)
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null)
val determineBasalObj = scope["determine_basal", scope]
val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope]
//call determine-basal
if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) {
//prepare parameters
val params = arrayOf(
makeParam(mGlucoseStatus, rhino, scope),
makeParam(currentTemp, rhino, scope),
makeParamArray(iobData, rhino, scope),
makeParam(profile, rhino, scope),
makeParam(autosensData, rhino, scope),
makeParam(mealData, rhino, scope),
setTempBasalFunctionsObj,
java.lang.Boolean.valueOf(microBolusAllowed),
makeParam(null, rhino, scope), // reservoir data as undefined
java.lang.Long.valueOf(currentTime),
java.lang.Boolean.valueOf(saveCgmSource)
)
val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject
scriptDebug = LoggerCallback.scriptDebug
// Parse the jsResult object to a JSON-String
val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString()
aapsLogger.debug(LTag.APS, "Result: $result")
try {
val resultJson = JSONObject(result)
determineBasalResultSMB = DetermineBasalResultSMB(injector, resultJson)
} catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Unhandled exception", e)
}
} else {
aapsLogger.error(LTag.APS, "Problem loading JS Functions")
}
} catch (e: IOException) {
aapsLogger.error(LTag.APS, "IOException")
} catch (e: RhinoException) {
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString())
} catch (e: IllegalAccessException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InstantiationException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InvocationTargetException) {
aapsLogger.error(LTag.APS, e.toString())
} finally {
Context.exit()
}
glucoseStatusParam = mGlucoseStatus.toString()
iobDataParam = iobData.toString()
currentTempParam = currentTemp.toString()
profileParam = profile.toString()
mealDataParam = mealData.toString()
return determineBasalResultSMB
}
@Suppress("SpellCheckingInspection")
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep
this.profile.put("max_iob", maxIob)
//mProfile.put("dia", profile.getDia());
this.profile.put("type", "current")
this.profile.put("max_daily_basal", profile.getMaxDailyBasal())
this.profile.put("max_basal", maxBasal)
this.profile.put("min_bg", minBg)
this.profile.put("max_bg", maxBg)
this.profile.put("target_bg", targetBg)
this.profile.put("carb_ratio", profile.getIc())
this.profile.put("sens", profile.getIsfMgdl())
this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3))
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
this.profile.put("high_temptarget_raises_sensitivity", false)
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
this.profile.put("low_temptarget_lowers_sensitivity", false)
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
this.profile.put("exercise_mode", SMBDefaults.exercise_mode)
this.profile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target)
this.profile.put("maxCOB", SMBDefaults.maxCOB)
this.profile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour())
// min_5m_carbimpact is not used within SMB determinebasal
//if (mealData.usedMinCarbsImpact > 0) {
// mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
//} else {
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
//}
this.profile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap)
this.profile.put("enableUAM", uamAllowed)
this.profile.put("A52_risk_enable", SMBDefaults.A52_risk_enable)
val smbEnabled = sp.getBoolean(R.string.key_use_smb, false)
this.profile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval))
this.profile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false))
this.profile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false))
this.profile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false))
this.profile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering)
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
//set the min SMB amount to be the amount set by the pump.
this.profile.put("bolus_increment", pumpBolusStep)
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
this.profile.put("current_basal", basalRate)
this.profile.put("temptargetSet", tempTargetSet)
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
this.profile.put("out_units", "mmol/L")
}
val now = System.currentTimeMillis()
val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
currentTemp.put("temp", "absolute")
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0)
// as we have non default temps longer than 30 mintues
if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now))
iobData = iobCobCalculator.convertToJSONArray(iobArray)
mGlucoseStatus.put("glucose", glucoseStatus.glucose)
mGlucoseStatus.put("noise", glucoseStatus.noise)
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
mGlucoseStatus.put("delta", glucoseStatus.shortAvgDelta)
} else {
mGlucoseStatus.put("delta", glucoseStatus.delta)
}
mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta)
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date)
this.mealData.put("carbs", mealData.carbs)
this.mealData.put("mealCOB", mealData.mealCOB)
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount)
this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount)
if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio)
} else {
autosensData.put("ratio", 1.0)
}
this.microBolusAllowed = microBolusAllowed
smbAlwaysAllowed = advancedFiltering
currentTime = now
saveCgmSource = isSaveCgmSource
}
private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any {
return if (jsonObject == null) Undefined.instance
else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any {
return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
@Throws(IOException::class) private fun readFile(filename: String): String {
val bytes = scriptReader.readFile(filename)
var string = String(bytes, StandardCharsets.UTF_8)
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20)
}
return string
}
init {
injector.androidInjector().inject(this)
}
}

View file

@ -0,0 +1,74 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF
import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@OpenForTesting
@Singleton
class OpenAPSSMBDynamicISFPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
rxBus: RxBus,
constraintChecker: ConstraintChecker,
rh: ResourceHelper,
profileFunction: ProfileFunction,
context: Context,
activePlugin: ActivePlugin,
iobCobCalculator: IobCobCalculator,
hardLimits: HardLimits,
profiler: Profiler,
sp: SP,
dateUtil: DateUtil,
repository: AppRepository,
glucoseStatusProvider: GlucoseStatusProvider,
private val buildHelper: BuildHelper
) : OpenAPSSMBPlugin(
injector,
aapsLogger,
rxBus,
constraintChecker,
rh,
profileFunction,
context,
activePlugin,
iobCobCalculator,
hardLimits,
profiler,
sp,
dateUtil,
repository,
glucoseStatusProvider
) {
init {
pluginDescription
.pluginName(R.string.openaps_smb_dynamic_isf)
.description(R.string.description_smb_dynamic_isf)
.setDefault(false)
}
override fun specialEnableCondition(): Boolean = buildHelper.isEngineeringMode() && buildHelper.isDev()
override fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector)
}

View file

@ -102,4 +102,11 @@ class BgQualityCheckPlugin @Inject constructor(
State.RECALCULATED -> R.drawable.ic_baseline_warning_24_yellow
State.DOUBLED -> R.drawable.ic_baseline_warning_24_red
}
fun stateDescription(): String =
when (state) {
State.RECALCULATED -> rh.gs(R.string.a11y_bg_quality_recalculated)
State.DOUBLED -> rh.gs(R.string.a11y_bg_quality_doubles)
else -> ""
}
}

View file

@ -107,6 +107,7 @@ class ActionsFragment : DaggerFragment() {
private var sensorLevelLabel: TextView? = null
private var insulinLevelLabel: TextView? = null
private var pbLevelLabel: TextView? = null
private var cannulaOrPatch: TextView? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -153,6 +154,7 @@ class ActionsFragment : DaggerFragment() {
sensorLevelLabel = view.findViewById(R.id.sensor_level_label)
insulinLevelLabel = view.findViewById(R.id.insulin_level_label)
pbLevelLabel = view.findViewById(R.id.pb_level_label)
cannulaOrPatch = view.findViewById(R.id.cannula_or_patch)
profileSwitch?.setOnClickListener {
ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")
@ -319,6 +321,10 @@ class ActionsFragment : DaggerFragment() {
tempTarget?.visibility = (profile != null && !loop.isDisconnected).toVisibility()
tddStats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
cannulaOrPatch?.text = if (pump.pumpDescription.isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula)
val imageResource = if (pump.pumpDescription.isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula
cannulaOrPatch?.setCompoundDrawablesWithIntrinsicBounds(imageResource, 0, 0, 0)
if (!config.NSCLIENT) {
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel)
sensorLevelLabel?.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label)

View file

@ -128,14 +128,29 @@ class OverviewData @Inject constructor(
var lastBg: GlucoseValue? = null
val lastBgColor: Int
val isLow: Boolean
get() = lastBg?.let { lastBg ->
when {
lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() -> rh.gc(R.color.low)
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() -> rh.gc(R.color.high)
else -> rh.gc(R.color.inrange)
}
} ?: rh.gc(R.color.inrange)
lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine()
} ?: false
val isHigh: Boolean
get() = lastBg?.let { lastBg ->
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
} ?: false
val lastBgColor: Int
get() = when {
isLow -> rh.gc(R.color.low)
isHigh -> rh.gc(R.color.high)
else -> rh.gc(R.color.inrange)
}
val lastBgDescription: String
get() = when {
isLow -> rh.gs(R.string.a11y_low)
isHigh -> rh.gs(R.string.a11y_high)
else -> rh.gs(R.string.a11y_inrange)
}
val isActualBg: Boolean
get() =

View file

@ -8,6 +8,7 @@ import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.AnimationDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
@ -47,6 +48,7 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
@ -416,7 +418,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), {
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
Thread { loop.acceptChangeRequest() }.run()
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
@ -597,24 +599,36 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// aps mode
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
fun apsModeSetA11yLabel(stringRes: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
binding.infoLayout.apsMode.stateDescription = rh.gs(stringRes)
} else {
binding.infoLayout.apsMode.contentDescription = rh.gs(R.string.apsmode_title) + " " + rh.gs(stringRes)
}
}
if (config.APS && pump.pumpDescription.isTempBasalCapable) {
binding.infoLayout.apsMode.visibility = View.VISIBLE
binding.infoLayout.timeLayout.visibility = View.GONE
when {
(loop as PluginBase).isEnabled() && loop.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus)
apsModeSetA11yLabel(R.string.superbolus)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
loop.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected)
apsModeSetA11yLabel(R.string.disconnected)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
(loop as PluginBase).isEnabled() && loop.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused)
apsModeSetA11yLabel(R.string.suspendloop_label)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
@ -624,8 +638,10 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
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
apsModeSetA11yLabel(R.string.disconnected)
R.drawable.ic_loop_disconnected
} else {
apsModeSetA11yLabel(R.string.pump_paused)
R.drawable.ic_loop_paused
}
)
@ -634,24 +650,43 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs)
apsModeSetA11yLabel(R.string.uel_lgs_loop_mode)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed)
apsModeSetA11yLabel(R.string.closedloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open)
apsModeSetA11yLabel(R.string.openloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
else -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled)
apsModeSetA11yLabel(R.string.disabledloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
}
// Show variable sensitivity
val request = loop.lastRun?.request
if (request is DetermineBasalResultSMB) {
val isfMgdl = profileFunction.getProfile()?.getIsfMgdl()
val variableSens = request.variableSens
if (variableSens != isfMgdl && variableSens != null && isfMgdl != null) {
binding.infoLayout.variableSensitivity.text =
String.format(
Locale.getDefault(), "%1$.1f→%2$.1f",
Profile.toUnits(isfMgdl, isfMgdl * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()),
Profile.toUnits(variableSens, variableSens * Constants.MGDL_TO_MMOLL, profileFunction.getUnits())
)
binding.infoLayout.variableSensitivity.visibility = View.VISIBLE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else {
//nsclient
binding.infoLayout.apsMode.visibility = View.GONE
@ -732,6 +767,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor)
binding.infoLayout.arrow.contentDescription = overviewData.lastBgDescription + " " + rh.gs(R.string.and) + " " + trendCalculator.getTrendDescription(overviewData.lastBg)
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
@ -751,13 +787,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
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()
val outDate = (if (!overviewData.isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
binding.infoLayout.bg.contentDescription =
rh.gs(R.string.a11y_blood_glucose) + " " + binding.infoLayout.bg.text.toString() + " " + overviewData.lastBgDescription + " " + outDate
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(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.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription()
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
}
@ -823,7 +866,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
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()
val isPatchPump = activePlugin.activePump.pumpDescription.isPatchPump
binding.statusLightsLayout.apply {
cannulaOrPatch.setImageResource(if (isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula)
cannulaOrPatch.contentDescription = rh.gs(if (isPatchPump) R.string.statuslights_patch_pump_age else R.string.statuslights_cannula_age)
cannulaOrPatch.scaleX = if (isPatchPump) 1.4f else 2f
cannulaOrPatch.scaleY = cannulaOrPatch.scaleX
insulinAge.visibility = isPatchPump.not().toVisibility()
statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
}
statusLightHandler.updateStatusLights(
binding.statusLightsLayout.cannulaAge,
binding.statusLightsLayout.insulinAge,

View file

@ -40,12 +40,7 @@ class StatusLightHandler @Inject constructor(
val pump = activePlugin.activePump
val bgSource = activePlugin.activeBgSource
handleAge(careportal_cannula_age, TherapyEvent.Type.CANNULA_CHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0)
if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
careportal_insulin_age?.visibility = View.GONE
} else {
careportal_insulin_age?.visibility = View.VISIBLE
handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0)
}
handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0)
handleAge(careportal_sensor_age, TherapyEvent.Type.SENSOR_CHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0)
if (pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)) {
handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0)

View file

@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.general.overview.activities
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.R
@ -17,10 +23,12 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWiza
import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class QuickWizardListActivity : NoSplashAppCompatActivity() {
@ -30,20 +38,95 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var sp: SP
private var disposable: CompositeDisposable = CompositeDisposable()
private lateinit var binding: OverviewQuickwizardlistActivityBinding
private val itemTouchHelper by lazy {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(UP or DOWN or START or END, 0) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val adapter = recyclerView.adapter as RecyclerViewAdapter
val from = viewHolder.layoutPosition
val to = target.layoutPosition
adapter.moveItem(from, to)
adapter.notifyItemMoved(from, to)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = 1.0f
val adapter = recyclerView.adapter as RecyclerViewAdapter
adapter.onDrop()
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
fun startDragging(viewHolder: RecyclerView.ViewHolder) {
itemTouchHelper.startDrag(viewHolder)
}
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>() {
@SuppressLint("ClickableViewAccessibility")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
return QuickWizardEntryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false), fragmentManager)
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false)
val viewHolder = QuickWizardEntryViewHolder(itemView, fragmentManager)
viewHolder.handleView.setOnTouchListener { _, event ->
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
startDragging(viewHolder)
}
return@setOnTouchListener true
}
return viewHolder
}
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate())
val wearControl = sp.getBoolean(R.string.key_wear_control, false)
if (wearControl) {
holder.handleView.visibility = View.VISIBLE
} else {
holder.handleView.visibility = View.GONE
}
if (quickWizard[position].device() == QuickWizardEntry.DEVICE_ALL) {
holder.device.visibility = View.GONE
} else {
holder.device.visibility = View.VISIBLE
holder.device.setImageResource(
when (quickWizard[position].device()) {
QuickWizardEntry.DEVICE_WATCH -> R.drawable.ic_watch
else -> R.drawable.ic_smartphone
}
)
}
holder.buttonText.text = quickWizard[position].buttonText()
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs())
}
@ -55,6 +138,8 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
val buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
val handleView: ImageView = itemView.findViewById(R.id.handleView)
val device: ImageView = itemView.findViewById(R.id.overview_quickwizard_item_device)
val to: TextView = itemView.findViewById(R.id.overview_quickwizard_item_to)
private val editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_button)
@ -74,6 +159,16 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
}
}
}
fun moveItem(from: Int, to: Int) {
Log.i("QuickWizard", "moveItem")
quickWizard.move(from, to)
}
fun onDrop() {
Log.i("QuickWizard", "onDrop")
rxBus.send(EventQuickWizardChange())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -84,6 +179,7 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
binding.addButton.setOnClickListener {
val manager = supportFragmentManager
@ -98,13 +194,13 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
.toObservable(EventQuickWizardChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({
val adapter = RecyclerViewAdapter(supportFragmentManager)
binding.recyclerview.swapAdapter(adapter, false)
}, fabricPrivacy::logException)
val adapter = RecyclerViewAdapter(supportFragmentManager)
binding.recyclerview.swapAdapter(adapter, false)
}, fabricPrivacy::logException)
}
override fun onPause() {
disposable.clear()
super.onPause()
}
}
}

View file

@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBus
@ -21,6 +22,7 @@ import info.nightscout.androidaps.utils.extensions.setEnableForChildren
import info.nightscout.androidaps.utils.extensions.setSelection
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
import javax.inject.Inject
@ -30,9 +32,9 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var sp: SP
var position = -1
var fromSeconds: Int = 0
var toSeconds: Int = 0
@ -42,8 +44,10 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
@ -57,6 +61,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
position = bundle.getInt("position", -1)
}
val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position]
if (sp.getBoolean(R.string.key_wear_control, false)) {
binding.deviceLabel.visibility = View.VISIBLE
binding.device.visibility = View.VISIBLE
} else {
binding.deviceLabel.visibility = View.GONE
binding.device.visibility = View.GONE
}
binding.okcancel.ok.setOnClickListener {
try {
entry.storage.put("buttonText", binding.buttonEdit.text.toString())
@ -66,10 +78,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
entry.storage.put("useBG", binding.useBg.selectedItemPosition)
entry.storage.put("useCOB", binding.useCob.selectedItemPosition)
entry.storage.put("useBolusIOB", binding.useBolusIob.selectedItemPosition)
entry.storage.put("device", binding.device.selectedItemPosition)
entry.storage.put("useBasalIOB", binding.useBasalIob.selectedItemPosition)
entry.storage.put("useTrend", binding.useTrend.selectedItemPosition)
entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition)
entry.storage.put("useTempTarget", binding.useTempTarget.selectedItemPosition)
entry.storage.put("usePercentage", binding.usePercentage.selectedItemPosition)
val percentage = SafeParse.stringToInt(binding.percentage.text.toString())
entry.storage.put("percentage", percentage)
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
@ -88,7 +104,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.from.setOnClickListener {
context?.let {
TimePickerDialog(it, fromTimeSetListener,
TimePickerDialog(
it, fromTimeSetListener,
T.secs(fromSeconds.toLong()).hours().toInt(),
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)
@ -105,13 +122,29 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.to.setOnClickListener {
context?.let {
TimePickerDialog(it, toTimeSetListener,
TimePickerDialog(
it, toTimeSetListener,
T.secs(toSeconds.toLong()).hours().toInt(),
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)
).show()
}
}
fun usePercentage(custom: Boolean) {
if (custom) {
binding.percentageLabel.visibility = View.VISIBLE
binding.percentage.visibility = View.VISIBLE
} else {
binding.percentageLabel.visibility = View.GONE
binding.percentage.visibility = View.GONE
}
}
binding.usePercentage.setOnCheckedChangeListener { _, checkedId ->
usePercentage(checkedId == R.id.use_percentage_custom)
}
toSeconds = entry.validTo()
binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
@ -122,10 +155,13 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.useCob.setSelection(entry.useCOB())
binding.useBolusIob.setSelection(entry.useBolusIOB())
binding.useBasalIob.setSelection(entry.useBasalIOB())
binding.device.setSelection(entry.device())
binding.useTrend.setSelection(entry.useTrend())
binding.useSuperBolus.setSelection(entry.useSuperBolus())
binding.useTempTarget.setSelection(entry.useTempTarget())
binding.usePercentage.setSelection(entry.usePercentage())
usePercentage(entry.usePercentage() == QuickWizardEntry.CUSTOM)
binding.percentage.setText(entry.percentage().toString())
binding.useCobYes.setOnClickListener(this)
binding.useCobNo.setOnClickListener(this)
processCob()

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.wear
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
@ -39,11 +40,11 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.wizard.BolusWizard
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.shared.SafeParse
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DateFormat
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
@ -71,6 +72,7 @@ class ActionStringHandler @Inject constructor(
private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator,
private val localInsightPlugin: LocalInsightPlugin,
private val quickWizard: QuickWizard,
private val danaRPlugin: DanaRPlugin,
private val danaRKoreanPlugin: DanaRKoreanPlugin,
private val danaRv2Plugin: DanaRv2Plugin,
@ -79,7 +81,8 @@ class ActionStringHandler @Inject constructor(
private val dateUtil: DateUtil,
private val config: Config,
private val repository: AppRepository,
private val uel: UserEntryLogger
private val uel: UserEntryLogger,
private val defaultValueHelper: DefaultValueHelper
) {
private val timeout = 65 * 1000
@ -107,9 +110,11 @@ class ActionStringHandler @Inject constructor(
@Synchronized
private fun handleInitiate(actionString: String) {
//TODO: i18n
Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString)
if (!sp.getBoolean(R.string.key_wear_control, false)) return
lastBolusWizard = null
var rTitle = "CONFIRM" //TODO: i18n
var rTitle = rh.gs(R.string.confirm).uppercase()
var rMessage = ""
var rAction = ""
// do the parsing and check constraints
@ -136,6 +141,11 @@ class ActionStringHandler @Inject constructor(
val carbs = SafeParse.stringToInt(act[2])
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
val pump = activePlugin.activePump
if (insulinAfterConstraints > 0 && (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected)) {
sendError(rh.gs(R.string.wizard_pump_not_available))
return
}
rMessage += rh.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
@ -143,32 +153,72 @@ class ActionStringHandler @Inject constructor(
}
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
val isMGDL = java.lang.Boolean.parseBoolean(act[1])
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
sendError("Different units used on watch and phone!")
return
}
val duration = SafeParse.stringToInt(act[2])
if (duration == 0) {
rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"
aapsLogger.info(LTag.WEAR, "temptarget received: $act")
if ("cancel" == act[1]) {
rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
rAction = "temptarget true 0 0 0"
} else if ("preset" == act[1]) {
val presetIsMGDL = profileFunction.getUnits() == GlucoseUnit.MGDL
val preset = act[2]
when (preset) {
"activity" -> {
val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
val activityTT = defaultValueHelper.determineActivityTT()
val reason = rh.gs(R.string.activity)
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, activityTT, activityTTDuration)
rAction = "temptarget $presetIsMGDL $activityTTDuration $activityTT $activityTT"
}
"hypo" -> {
val hypoTTDuration = defaultValueHelper.determineHypoTTDuration()
val hypoTT = defaultValueHelper.determineHypoTT()
val reason = rh.gs(R.string.hypo)
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, hypoTT, hypoTTDuration)
rAction = "temptarget $presetIsMGDL $hypoTTDuration $hypoTT $hypoTT"
}
"eating" -> {
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
val reason = rh.gs(R.string.eatingsoon)
rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, eatingSoonTT, eatingSoonTTDuration)
rAction = "temptarget $presetIsMGDL $eatingSoonTTDuration $eatingSoonTT $eatingSoonTT"
}
else -> {
sendError(rh.gs(R.string.wear_action_tempt_preset_error, preset))
return
}
}
} else {
var low = SafeParse.stringToDouble(act[3])
var high = SafeParse.stringToDouble(act[4])
if (!isMGDL) {
low *= Constants.MMOLL_TO_MGDL
high *= Constants.MMOLL_TO_MGDL
}
if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
sendError("Min-BG out of range!")
val isMGDL = java.lang.Boolean.parseBoolean(act[1])
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
sendError(rh.gs(R.string.wear_action_tempt_unit_error))
return
}
if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
sendError("Max-BG out of range!")
return
val duration = SafeParse.stringToInt(act[2])
if (duration == 0) {
rMessage += rh.gs(R.string.wear_action_tempt_zero_message)
rAction = "temptarget true 0 0 0"
} else {
var low = SafeParse.stringToDouble(act[3])
var high = SafeParse.stringToDouble(act[4])
if (!isMGDL) {
low *= Constants.MMOLL_TO_MGDL
high *= Constants.MMOLL_TO_MGDL
}
if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
sendError(rh.gs(R.string.wear_action_tempt_min_bg_error))
return
}
if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
sendError(rh.gs(R.string.wear_action_tempt_max_bg_error))
return
}
rMessage += if (act[3] === act[4]) rh.gs(R.string.wear_action_tempt_manual_message, act[3], act[2])
else rh.gs(R.string.wear_action_tempt_manual_range_message, act[3], act[4], act[2])
rAction = actionString
}
rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2]
rAction = actionString
}
} else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS
rTitle = "STATUS"
@ -186,10 +236,15 @@ class ActionStringHandler @Inject constructor(
sendError("Update APP on Watch!")
return
} else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD
val pump = activePlugin.activePump
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
sendError(rh.gs(R.string.wizard_pump_not_available))
return
}
val carbsBeforeConstraints = SafeParse.stringToInt(act[1])
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
sendError("Carb constraint violation!")
sendError(rh.gs(R.string.wizard_carbs_constraint))
return
}
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
@ -202,52 +257,94 @@ class ActionStringHandler @Inject constructor(
val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName()
if (profile == null) {
sendError("No profile found!")
sendError(rh.gs(R.string.wizard_no_active_profile))
return
}
val bgReading = iobCobCalculator.ads.actualBg()
if (bgReading == null) {
sendError("No recent BG to base calculation on!")
sendError(rh.gs(R.string.wizard_no_actual_bg))
return
}
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
if (cobInfo.displayCob == null) {
sendError("Unknown COB! BG reading missing or recent app restart?")
sendError(rh.gs(R.string.wizard_no_cob))
return
}
val format = DecimalFormat("0.00")
val formatInt = DecimalFormat("0")
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget,
carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()),
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) {
sendError("Insulin constraint violation!" +
"\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!")
val bolusWizard = BolusWizard(injector).doCalc(
profile, profileName, tempTarget,
carbsAfterConstraints, cobInfo.displayCob!!, bgReading.valueToUnits(profileFunction.getUnits()),
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false
)
val insulinAfterConstraints = bolusWizard.insulinAfterConstraints
val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
if (abs(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= minStep) {
sendError(rh.gs(R.string.wizard_constraint_bolus_size, bolusWizard.calculatedTotalInsulin))
return
}
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
rAction = "info"
rTitle = "INFO"
rTitle = rh.gs(R.string.info)
} else {
rAction = actionString
}
rMessage += "Carbs: " + bolusWizard.carbs + "g"
rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"
rMessage += rh.gs(R.string.wizard_result, bolusWizard.calculatedTotalInsulin, bolusWizard.carbs)
rMessage += "\n_____________"
rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "
rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U"
if (useCOB) rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.insulinFromCOB) + "U"
if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"
if (useBolusIOB) rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulinFromBolusIOB) + "U"
if (useBasalIOB) rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulinFromBasalIOB) + "U"
if (useTrend) rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.insulinFromTrend) + "U"
if (percentage != 100) {
rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"
}
rMessage += "\n" + bolusWizard.explainShort()
lastBolusWizard = bolusWizard
} else if ("quick_wizard" == act[0]) {
val guid = act[1]
val actualBg = iobCobCalculator.ads.actualBg()
val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName()
val quickWizardEntry = quickWizard.get(guid)
Log.i("QuickWizard", "handleInitiate: quick_wizard " + quickWizardEntry?.buttonText() + " c " + quickWizardEntry?.carbs())
if (quickWizardEntry == null) {
sendError(rh.gs(R.string.quick_wizard_not_available))
return
}
if (actualBg == null) {
sendError(rh.gs(R.string.wizard_no_actual_bg))
return
}
if (profile == null) {
sendError(rh.gs(R.string.wizard_no_active_profile))
return
}
val cobInfo = iobCobCalculator.getCobInfo(false, "QuickWizard wear")
if (cobInfo.displayCob == null) {
sendError(rh.gs(R.string.wizard_no_cob))
return
}
val pump = activePlugin.activePump
if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
sendError(rh.gs(R.string.wizard_pump_not_available))
return
}
val wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true)
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(quickWizardEntry.carbs())).value()
if (carbsAfterConstraints != quickWizardEntry.carbs()) {
sendError(rh.gs(R.string.wizard_carbs_constraint))
return
}
val insulinAfterConstraints = wizard.insulinAfterConstraints
val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
if (abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= minStep) {
sendError(rh.gs(R.string.wizard_constraint_bolus_size, wizard.calculatedTotalInsulin))
return
}
rMessage = rh.gs(R.string.quick_wizard_message, quickWizardEntry.buttonText(), wizard.calculatedTotalInsulin, quickWizardEntry.carbs())
rAction = "bolus $insulinAfterConstraints $carbsAfterConstraints"
Log.i("QuickWizard", "handleInitiate: quick_wizard action=$rAction")
rMessage += "\n_____________"
rMessage += "\n" + wizard.explainShort()
} else if ("opencpp" == act[0]) {
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
@ -331,7 +428,10 @@ class ActionStringHandler @Inject constructor(
rAction = "cancelChangeRequest"
wearPlugin.requestNotificationCancel(rAction)
return
} else return
} else {
sendError(rh.gs(R.string.wear_unknown_action_string) + act[0])
return
}
// send result
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
lastSentTimestamp = System.currentTimeMillis()
@ -560,39 +660,45 @@ class ActionStringHandler @Inject constructor(
}
//send profile to pump
uel.log(Action.PROFILE_SWITCH, Sources.Wear,
ValueWithUnit.Percent(percentage),
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
ValueWithUnit.Percent(percentage),
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
profileFunction.createProfileSwitch(0, percentage, timeshift)
}
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
if (duration != 0) {
disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
reason = TemporaryTarget.Reason.WEAR,
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
)).subscribe({ result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
})
uel.log(Action.TT, Sources.Wear,
disposable += repository.runTransactionForResult(
InsertAndCancelCurrentTemporaryTargetTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
reason = TemporaryTarget.Reason.WEAR,
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
)
).subscribe({ result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
})
uel.log(
Action.TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
ValueWithUnit.Minute(duration))
ValueWithUnit.Minute(duration)
)
} else {
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
.subscribe({ result ->
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
})
uel.log(Action.CANCEL_TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR))
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
})
uel.log(
Action.CANCEL_TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)
)
}
}
@ -601,13 +707,15 @@ class ActionStringHandler @Inject constructor(
detailedBolusInfo.insulin = amount
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
uel.log(Action.PRIME_BOLUS, Sources.Wear,
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 })
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
sendError(rh.gs(R.string.treatmentdeliveryerror) +
"\n" +
result.comment)
sendError(
rh.gs(R.string.treatmentdeliveryerror) +
"\n" +
result.comment
)
}
}
})
@ -615,9 +723,9 @@ class ActionStringHandler @Inject constructor(
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
ValueWithUnit.Timestamp(time),
ValueWithUnit.Gram(carbs),
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
ValueWithUnit.Timestamp(time),
ValueWithUnit.Gram(carbs),
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
doBolus(0.0, carbs, time, duration)
}
@ -636,15 +744,17 @@ class ActionStringHandler @Inject constructor(
else -> Action.TREATMENT
}
uel.log(action, Sources.Wear,
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
sendError(rh.gs(R.string.treatmentdeliveryerror) +
"\n" +
result.comment)
sendError(
rh.gs(R.string.treatmentdeliveryerror) +
"\n" +
result.comment
)
}
}
})
@ -665,4 +775,4 @@ class ActionStringHandler @Inject constructor(
lastConfirmActionString = null
lastBolusWizard = null
}
}
}

View file

@ -46,6 +46,7 @@ import info.nightscout.androidaps.interfaces.Loop;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Profile;
import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
@ -62,6 +63,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.DefaultValueHelper;
import info.nightscout.androidaps.utils.TrendCalculator;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.wizard.QuickWizard;
import info.nightscout.shared.sharedPreferences.SP;
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
@ -81,6 +83,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
@Inject ReceiverStatusStore receiverStatusStore;
@Inject Config config;
@Inject public TrendCalculator trendCalculator;
@Inject public QuickWizard quickWizard;
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
@ -101,12 +104,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
private static final String QUICK_WIZARD_PATH = "/send_quick_wizard";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
String TAG = "WatchUpdateService";
private static boolean lastLoopStatus;
@ -156,7 +161,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent != null ? intent.getAction() : null;
// Log.d(TAG, logPrefix + "onStartCommand: " + action);
// Log.d(TAG, "onStartCommand: " + action);
if (wearIntegration()) {
handler.post(() -> {
@ -235,7 +240,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
super.onPeerConnected(peer);
String id = peer.getId();
String name = peer.getDisplayName();
// Log.d(TAG, logPrefix + "onPeerConnected peer name & ID: " + name + "|" + id);
Log.d(TAG, "onPeerConnected peer name & ID: " + name + "|" + id);
}
@ -244,14 +249,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
super.onPeerDisconnected(peer);
String id = peer.getId();
String name = peer.getDisplayName();
// Log.d(TAG, logPrefix + "onPeerDisconnected peer name & ID: " + name + "|" + id);
Log.d(TAG, "onPeerDisconnected peer name & ID: " + name + "|" + id);
}
@Override
public void onMessageReceived(MessageEvent event) {
// Log.d(TAG, logPrefix + "onMessageRecieved: " + event);
// Log.d(TAG, "onMessageRecieved: " + event);
if (wearIntegration()) {
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
@ -283,7 +288,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendData() {
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
// Log.d(TAG, logPrefix + "LastBg=" + lastBG);
// Log.d(TAG, "LastBg=" + lastBG);
if (lastBG != null) {
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
@ -364,6 +369,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
googleApiConnect();
}
sendPreferences();
sendQuickWizard();
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
@ -382,7 +391,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
entries.putDataMapArrayList("entries", dataMaps);
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
}
sendPreferences();
sendBasals();
sendStatus();
}
@ -720,19 +728,62 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendPreferences() {
if (googleApiClient != null && googleApiClient.isConnected()) {
GlucoseUnit units = profileFunction.getUnits();
boolean wearcontrol = sp.getBoolean(R.string.key_wear_control, false);
boolean mgdl = units.equals(GlucoseUnit.MGDL);
int percentage = sp.getInt(R.string.key_boluswizard_percentage, 100);
int maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0);
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
//unique content
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_wear_control), wearcontrol);
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_units_mgdl), mgdl);
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_boluswizard_percentage), percentage);
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), maxCarbs);
dataMapRequest.getDataMap().putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus),maxBolus);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("SendStatus", "No connection to wearable available!");
Log.e("SendPreferences", "No connection to wearable available!");
}
}
private void sendQuickWizard() {
if (googleApiClient != null && googleApiClient.isConnected()) {
int size = quickWizard.size();
ArrayList<DataMap> entities = new ArrayList<>();
for(int i=0; i < size; i++) {
QuickWizardEntry q = quickWizard.get(i);
if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) {
entities.add(quickMap(q));
}
}
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(QUICK_WIZARD_PATH);
DataMap dm = dataMapRequest.getDataMap();
dm.putLong("timestamp", System.currentTimeMillis());
dm.putDataMapArrayList("quick_wizard", entities);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Log.i(TAG, "sendQuickWizard: " + putDataRequest);
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("sendQuickWizard", "No connection to wearable available!");
}
}
private DataMap quickMap(QuickWizardEntry q) {
DataMap dm = new DataMap();
dm.putString("guid", q.guid());
dm.putString("button_text", q.buttonText());
dm.putInt("carbs", q.carbs());
dm.putInt("from", q.validFrom());
dm.putInt("to", q.validTo());
return dm;
}
@NonNull
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {

View file

@ -18,10 +18,11 @@ class ActivityGraph : GraphView {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
fun show(insulin: Insulin) {
fun show(insulin: Insulin, diaSample: Double? = null) {
removeAllSeries()
val dia = diaSample ?: insulin.dia
mSecondScale = null
val hours = floor(insulin.dia + 1).toLong()
val hours = floor(dia + 1).toLong()
val bolus = Bolus(
timestamp = 0,
amount = 1.0,
@ -31,7 +32,7 @@ class ActivityGraph : GraphView {
val iobArray: MutableList<DataPoint> = ArrayList()
var time: Long = 0
while (time <= T.hours(hours).msecs()) {
val iob = insulin.iobCalcForTreatment(bolus, time, insulin.dia)
val iob = insulin.iobCalcForTreatment(bolus, time, dia)
activityArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.activityContrib))
iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib))
time += T.mins(5).msecs()

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.profile.local
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -20,7 +21,6 @@ import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
@ -31,8 +31,10 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.SpinnerHelper
import info.nightscout.androidaps.utils.ui.TimeListEdit
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.math.RoundingMode
import java.text.DecimalFormat
import javax.inject.Inject
@ -61,6 +63,8 @@ class LocalProfileFragment : DaggerFragment() {
binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.show(ProfileSealed.Pure(it))
binding.targetGraph.show(ProfileSealed.Pure(it))
binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text))
}
}
@ -117,6 +121,7 @@ class LocalProfileFragment : DaggerFragment() {
processVisibilityOnClick(it)
binding.target.visibility = View.VISIBLE
}
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
}
fun build() {
@ -130,14 +135,22 @@ class LocalProfileFragment : DaggerFragment() {
binding.name.addTextChangedListener(textWatch)
binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch)
binding.dia.tag = "LP_DIA"
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_label), currentProfile.ic, null, hardLimits.minIC(), hardLimits.maxIC(), 0.1, DecimalFormat("0.0"), save)
basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_long_label), currentProfile.ic, null, doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), null, 0.1, DecimalFormat ("0.0"), save)
basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_long_label) + ": " + sumLabel(), currentProfile.basal, null, doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), null, 0.01, DecimalFormat("0.00"), save)
if (units == Constants.MGDL) {
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], 1.0, DecimalFormat("0"), save)
val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange , null, 1.0, DecimalFormat("0"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_MIN_BG, HardLimits.VERY_HARD_LIMIT_TARGET_BG, 1.0, DecimalFormat("0"), save)
} else {
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save)
val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL)))
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null,isfRange , null, 0.1, DecimalFormat("0.0"), save)
val range1 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL)))
val range2 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL)))
Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1])
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, range1 , range2, 0.1, DecimalFormat("0.0"), save)
}
// Spinner
@ -175,6 +188,8 @@ class LocalProfileFragment : DaggerFragment() {
binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.show(ProfileSealed.Pure(it))
binding.targetGraph.show(ProfileSealed.Pure(it))
binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text))
}
binding.profileAdd.setOnClickListener {
@ -265,6 +280,14 @@ class LocalProfileFragment : DaggerFragment() {
updateGUI()
}
private fun roundUp(number: Double): Double {
return number.toBigDecimal().setScale(1, RoundingMode.UP).toDouble()
}
private fun roundDown(number: Double): Double {
return number.toBigDecimal().setScale(1, RoundingMode.DOWN).toDouble()
}
private fun updateGUI() {
if (_binding == null) return
val isValid = localProfilePlugin.isValidEditState(activity)

View file

@ -7,8 +7,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.ListenableWorker
import androidx.work.workDataOf
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
@ -118,7 +116,10 @@ class BGSourceFragment : DaggerFragment() {
val glucoseValue = glucoseValues[position]
holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(glucoseValue.timestamp)
val sameDayPrevious = position > 0 && dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position-1].timestamp)
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
holder.binding.date.text = dateUtil.dateString(glucoseValue.timestamp)
holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp)
holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
holder.binding.remove.tag = glucoseValue

View file

@ -1,20 +1,37 @@
package info.nightscout.androidaps.utils
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.GlucoseValue.TrendArrow.*
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TrendCalculator @Inject constructor(
private val repository: AppRepository
private val repository: AppRepository,
private val rh: ResourceHelper
) {
fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow =
when {
glucoseValue?.trendArrow == null -> GlucoseValue.TrendArrow.NONE
glucoseValue.trendArrow != GlucoseValue.TrendArrow.NONE -> glucoseValue.trendArrow
else -> calculateDirection(glucoseValue)
glucoseValue?.trendArrow == null -> NONE
glucoseValue.trendArrow != NONE -> glucoseValue.trendArrow
else -> calculateDirection(glucoseValue)
}
fun getTrendDescription(glucoseValue: GlucoseValue?): String =
when (getTrendArrow(glucoseValue)) {
DOUBLE_DOWN -> rh.gs(R.string.a11y_arrow_double_down)
SINGLE_DOWN -> rh.gs(R.string.a11y_arrow_single_down)
FORTY_FIVE_DOWN -> rh.gs(R.string.a11y_arrow_forty_five_down)
FLAT -> rh.gs(R.string.a11y_arrow_flat)
FORTY_FIVE_UP -> rh.gs(R.string.a11y_arrow_forty_five_up)
SINGLE_UP -> rh.gs(R.string.a11y_arrow_single_up)
DOUBLE_UP -> rh.gs(R.string.a11y_arrow_double_up)
NONE -> rh.gs(R.string.a11y_arrow_none)
else -> rh.gs(R.string.a11y_arrow_unknown)
}
private fun calculateDirection(glucoseValue: GlucoseValue): GlucoseValue.TrendArrow {
@ -23,7 +40,7 @@ class TrendCalculator @Inject constructor(
val readings = repository.compatGetBgReadingsDataFromTime(toTime - T.mins(10).msecs(), toTime, false).blockingGet()
if (readings.size < 2)
return GlucoseValue.TrendArrow.NONE
return NONE
val current = readings[0]
val previous = readings[1]
@ -35,14 +52,14 @@ class TrendCalculator @Inject constructor(
val slopeByMinute = slope * 60000
return when {
slopeByMinute <= -3.5 -> GlucoseValue.TrendArrow.DOUBLE_DOWN
slopeByMinute <= -2 -> GlucoseValue.TrendArrow.SINGLE_DOWN
slopeByMinute <= -1 -> GlucoseValue.TrendArrow.FORTY_FIVE_DOWN
slopeByMinute <= 1 -> GlucoseValue.TrendArrow.FLAT
slopeByMinute <= 2 -> GlucoseValue.TrendArrow.FORTY_FIVE_UP
slopeByMinute <= 3.5 -> GlucoseValue.TrendArrow.SINGLE_UP
slopeByMinute <= 40 -> GlucoseValue.TrendArrow.DOUBLE_UP
else -> GlucoseValue.TrendArrow.NONE
slopeByMinute <= -3.5 -> DOUBLE_DOWN
slopeByMinute <= -2 -> SINGLE_DOWN
slopeByMinute <= -1 -> FORTY_FIVE_DOWN
slopeByMinute <= 1 -> FLAT
slopeByMinute <= 2 -> FORTY_FIVE_UP
slopeByMinute <= 3.5 -> SINGLE_UP
slopeByMinute <= 40 -> DOUBLE_UP
else -> NONE
}
}
}
}

View file

@ -58,13 +58,13 @@ class TddCalculator @Inject constructor(
val tbr = tempBasals[t]
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / 60.0 * 5.0
tdd.basalAmount += absoluteRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0
tdd.bolusAmount += absoluteEbRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
}
result.put(midnight, tdd)
}
@ -76,7 +76,54 @@ class TddCalculator @Inject constructor(
return result
}
private fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
fun calculateDaily():TotalDailyDose {
val startTime = MidnightTime.calc(dateUtil.now() )
val endTime = dateUtil.now()
val tdd = TotalDailyDose(timestamp = startTime)
//val result = TotalDailyDose()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
//result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble()
}
//result.put(midnight, tdd)
}
//for (i in 0 until tdd.size()) {
//val tdd = result.valueAt(i)
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i)

View file

@ -57,6 +57,8 @@ public class TimeListEdit {
private final double step;
private final double min;
private final double max;
private final double min2;
private final double max2;
private final NumberFormat formatter;
private final Runnable save;
private LinearLayout layout;
@ -68,7 +70,7 @@ public class TimeListEdit {
Context context,
AAPSLogger aapsLogger,
DateUtil dateUtil,
View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double min, double max, double step, NumberFormat formatter, Runnable save) {
View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double[] range1, double[] range2, double step, NumberFormat formatter, Runnable save) {
this.context = context;
this.aapsLogger = aapsLogger;
this.dateUtil = dateUtil;
@ -79,8 +81,10 @@ public class TimeListEdit {
this.data1 = data1;
this.data2 = data2;
this.step = step;
this.min = min;
this.max = max;
this.min = range1[0];
this.max = range1[1];
this.min2 = range2 != null ? range2[0] : 0;
this.max2 = range2 != null ? range2[1] : 0;
this.formatter = formatter;
this.save = save;
buildView();
@ -108,6 +112,7 @@ public class TimeListEdit {
float factor = layout.getContext().getResources().getDisplayMetrics().density;
finalAdd = new ImageView(context);
finalAdd.setImageResource(R.drawable.ic_add);
finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.a11y_add_new_to_list));
LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor));
illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
illp.gravity = Gravity.CENTER;
@ -177,7 +182,13 @@ public class TimeListEdit {
numberPickers1[position].setTextWatcher(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
editItem(position, secondFromMidnight(position), SafeParse.stringToDouble(numberPickers1[position].getText()), value2(position));
Double value1 = SafeParse.stringToDouble(numberPickers1[position].getText());
Double value2 = value2(position);
if (data2 != null && value1 > value2) {
value2 = value1;
numberPickers2[position].setValue(value2);
}
editItem(position, secondFromMidnight(position), value1, value2);
callSave();
log();
}
@ -197,7 +208,13 @@ public class TimeListEdit {
numberPickers2[position].setTextWatcher(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
editItem(position, secondFromMidnight(position), value1(position), SafeParse.stringToDouble(numberPickers2[position].getText()));
Double value1 = value1(position);
Double value2 = SafeParse.stringToDouble(numberPickers2[position].getText());
if (data2 != null && value2 < value1) {
value1 = value2;
numberPickers1[position].setValue(value1);
}
editItem(position, secondFromMidnight(position), value1, value2);
callSave();
log();
}
@ -246,7 +263,7 @@ public class TimeListEdit {
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
editText1.setParams(value1(i), min, max, step, formatter, false, null);
editText2.setParams(value2(i), min, max, step, formatter, false, null);
editText2.setParams(value2(i), min2, max2, step, formatter, false, null);
if (data2 == null) {
editText2.setVisibility(View.GONE);

View file

@ -18,6 +18,8 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.extensions.highValueToUnitsToString
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
@ -135,27 +137,28 @@ class BolusWizard @Inject constructor(
private var quickWizard: Boolean = true
var usePercentage: Boolean = false
fun doCalc(profile: Profile,
profileName: String,
tempTarget: TemporaryTarget?,
carbs: Int,
cob: Double,
bg: Double,
correction: Double,
percentageCorrection: Int = 100,
useBg: Boolean,
useCob: Boolean,
includeBolusIOB: Boolean,
includeBasalIOB: Boolean,
useSuperBolus: Boolean,
useTT: Boolean,
useTrend: Boolean,
useAlarm: Boolean,
notes: String = "",
carbTime: Int = 0,
usePercentage: Boolean = false,
totalPercentage: Double = 100.0,
quickWizard: Boolean = false
fun doCalc(
profile: Profile,
profileName: String,
tempTarget: TemporaryTarget?,
carbs: Int,
cob: Double,
bg: Double,
correction: Double,
percentageCorrection: Int = 100,
useBg: Boolean,
useCob: Boolean,
includeBolusIOB: Boolean,
includeBasalIOB: Boolean,
useSuperBolus: Boolean,
useTT: Boolean,
useTrend: Boolean,
useAlarm: Boolean,
notes: String = "",
carbTime: Int = 0,
usePercentage: Boolean = false,
totalPercentage: Double = 100.0,
quickWizard: Boolean = false
): BolusWizard {
this.profile = profile
@ -261,22 +264,23 @@ class BolusWizard @Inject constructor(
return this
}
private fun createBolusCalculatorResult(): BolusCalculatorResult =
BolusCalculatorResult(
private fun createBolusCalculatorResult(): BolusCalculatorResult {
val unit = profileFunction.getUnits()
return BolusCalculatorResult(
timestamp = dateUtil.now(),
targetBGLow = targetBGLow,
targetBGHigh = targetBGHigh,
isf = sens,
targetBGLow = Profile.toMgdl(targetBGLow, unit),
targetBGHigh = Profile.toMgdl(targetBGHigh, unit),
isf = Profile.toMgdl(sens, unit),
ic = ic,
bolusIOB = insulinFromBolusIOB,
wasBolusIOBUsed = includeBolusIOB,
basalIOB = insulinFromBasalIOB,
wasBasalIOBUsed = includeBasalIOB,
glucoseValue = bg,
glucoseValue = Profile.toMgdl(bg, unit),
wasGlucoseUsed = useBg && bg > 0,
glucoseDifference = bgDiff,
glucoseInsulin = insulinFromBG,
glucoseTrend = trend,
glucoseTrend = Profile.fromMgdlToUnits(trend, unit),
wasTrendUsed = useTrend,
trendInsulin = insulinFromTrend,
cob = cob,
@ -294,6 +298,7 @@ class BolusWizard @Inject constructor(
profileName = profileName,
note = notes
)
}
private fun confirmMessageAfterConstraints(advisor: Boolean): Spanned {
@ -312,7 +317,9 @@ class BolusWizard @Inject constructor(
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs).formatColor(rh, R.color.carbs) + timeShift)
}
if (insulinFromCOB > 0) {
actions.add(rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert))
actions.add(
rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert)
)
val absorptionRate = iobCobCalculator.ads.slowAbsorptionPercentage(60)
if (absorptionRate > .25)
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt()))
@ -342,11 +349,13 @@ class BolusWizard @Inject constructor(
carbTimer.removeEatReminder()
if (sp.getBoolean(R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0)
OKDialog.showYesNoCancel(ctx, rh.gs(R.string.bolusadvisor), rh.gs(R.string.bolusadvisormessage),
{ bolusAdvisorProcessing(ctx) },
{ commonProcessing(ctx) }
{ bolusAdvisorProcessing(ctx) },
{ commonProcessing(ctx) }
)
else
commonProcessing(ctx)
} else {
OKDialog.show(ctx, rh.gs(R.string.boluswizard), rh.gs(R.string.no_action_selected))
}
}
@ -363,10 +372,13 @@ class BolusWizard @Inject constructor(
carbTime = 0
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
uel.log(Action.BOLUS_ADVISOR, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
uel.log(
Action.BOLUS_ADVISOR,
if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints))
ValueWithUnit.Insulin(insulinAfterConstraints)
)
if (insulin > 0) {
commandQueue.bolus(this, object : Callback() {
override fun run() {
@ -381,6 +393,26 @@ class BolusWizard @Inject constructor(
})
}
fun explainShort(): String {
var message = rh.gs(R.string.wizard_explain_calc, ic, sens)
message += "\n" + rh.gs(R.string.wizard_explain_carbs, insulinFromCarbs)
if (useTT && tempTarget != null) {
val tt = if (tempTarget?.lowTarget == tempTarget?.highTarget) tempTarget?.lowValueToUnitsToString(profile.units)
else rh.gs(R.string.wizard_explain_tt_to, tempTarget?.lowValueToUnitsToString(profile.units), tempTarget?.highValueToUnitsToString(profile.units))
message += "\n" + rh.gs(R.string.wizard_explain_tt, tt)
}
if (useCob) message += "\n" + rh.gs(R.string.wizard_explain_cob, cob, insulinFromCOB)
if (useBg) message += "\n" + rh.gs(R.string.wizard_explain_bg, insulinFromBG)
if (includeBolusIOB) message += "\n" + rh.gs(R.string.wizard_explain_bolus_iob, insulinFromBolusIOB)
if (includeBasalIOB) message += "\n" + rh.gs(R.string.wizard_explain_basal_iob, insulinFromBasalIOB)
if (useTrend) message += "\n" + rh.gs(R.string.wizard_explain_trend, insulinFromTrend)
if (useSuperBolus) message += "\n" + rh.gs(R.string.wizard_explain_superbolus, insulinFromSuperBolus)
if (percentageCorrection != 100) {
message += "\n" + rh.gs(R.string.wizard_explain_percent, totalBeforePercentageAdjustment, percentageCorrection, calculatedTotalInsulin)
}
return message
}
private fun commonProcessing(ctx: Context) {
val profile = profileFunction.getProfile() ?: return
val pump = activePlugin.activePump
@ -429,17 +461,17 @@ class BolusWizard @Inject constructor(
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
if (insulin > 0 || carbs > 0) {
val action = when {
val action = when {
insulinAfterConstraints.equals(0.0) -> Action.CARBS
carbs.equals(0.0) -> Action.BOLUS
else -> Action.TREATMENT
}
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
commandQueue.bolus(this, object : Callback() {
override fun run() {
if (!result.success) {
@ -465,9 +497,9 @@ class BolusWizard @Inject constructor(
private fun calcPercentageWithConstraints() {
calculatedPercentage = 100.0
if (totalBeforePercentageAdjustment != insulinFromCorrection)
calculatedPercentage = calculatedTotalInsulin/(totalBeforePercentageAdjustment-insulinFromCorrection) * 100
calculatedPercentage = calculatedTotalInsulin / (totalBeforePercentageAdjustment - insulinFromCorrection) * 100
calculatedPercentage = max(calculatedPercentage, 10.0)
calculatedPercentage = min(calculatedPercentage,250.0)
calculatedPercentage = min(calculatedPercentage, 250.0)
}
private fun calcCorrectionWithConstraints() {
@ -477,4 +509,4 @@ class BolusWizard @Inject constructor(
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
}
}
}

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.utils.wizard
import android.util.Log
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -18,6 +20,18 @@ class QuickWizard @Inject constructor(
init {
setData(JSONArray(sp.getString(R.string.key_quickwizard, "[]")))
setGuidsForOldEntries()
}
private fun setGuidsForOldEntries() {
// for migration purposes; guid is a new required property
for (i in 0 until storage.length()) {
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
if (entry.guid() == "") {
val guid = UUID.randomUUID().toString()
entry.storage.put("guid", guid)
}
}
}
fun getActive(): QuickWizardEntry? {
@ -41,6 +55,38 @@ class QuickWizard @Inject constructor(
operator fun get(position: Int): QuickWizardEntry =
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
fun get(guid: String): QuickWizardEntry? {
for (i in 0 until storage.length()) {
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
if (entry.guid() == guid) {
return entry
}
}
return null
}
fun move(from: Int, to: Int) {
Log.i("QuickWizard", "moveItem: $from $to")
val fromEntry = storage[from] as JSONObject
storage.remove(from)
addToPos(to, fromEntry, storage)
save()
}
fun removePos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
for (i in jsonArr.length() downTo pos + 1) {
jsonArr.put(i, jsonArr[i - 1])
}
jsonArr.put(pos, jsonObj)
}
private fun addToPos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
for (i in jsonArr.length() downTo pos + 1) {
jsonArr.put(i, jsonArr[i - 1])
}
jsonArr.put(pos, jsonObj)
}
fun newEmptyItem(): QuickWizardEntry {
return QuickWizardEntry(injector)
}
@ -57,4 +103,5 @@ class QuickWizard @Inject constructor(
storage.remove(position)
save()
}
}

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
@ -41,11 +42,26 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
const val NO = 1
private const val POSITIVE_ONLY = 2
private const val NEGATIVE_ONLY = 3
const val DEVICE_ALL = 0
const val DEVICE_PHONE = 1
const val DEVICE_WATCH = 2
const val DEFAULT = 0
const val CUSTOM = 1
}
init {
injector.androidInjector().inject(this)
val emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}"
val guid = UUID.randomUUID().toString()
val emptyData = """{
"guid": "$guid",
"buttonText": "",
"carbs": 0,
"validFrom": 0,
"validTo": 86340,
"device": "all",
"usePercentage": "default",
"percentage": 100
}""".trimMargin()
try {
storage = JSONObject(emptyData)
} catch (e: JSONException) {
@ -55,6 +71,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
/*
{
guid: string,
device: string, // (phone, watch, all)
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
@ -66,15 +84,18 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
useTrend: 0,
useSuperBolus: 0,
useTemptarget: 0
usePercentage: string, // default, custom
percentage: int,
}
*/
fun from(entry: JSONObject, position: Int): QuickWizardEntry {
// TODO set guid if missing for migration
storage = entry
this.position = position
return this
}
fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo()
fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo() && forDevice(DEVICE_PHONE)
fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
@ -119,10 +140,16 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
trend = true
}
val percentage = sp.getInt(R.string.key_boluswizard_percentage, 100)
val percentage = if (usePercentage() == DEFAULT) sp.getInt(R.string.key_boluswizard_percentage, 100) else percentage()
return BolusWizard(injector).doCalc(profile, profileName, tempTarget, carbs(), cob, bg, 0.0, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, false, buttonText(), quickWizard = true) //tbc, ok if only quickwizard, but if other sources elsewhere use Sources.QuickWizard
}
fun guid(): String = safeGetString(storage, "guid", "")
fun device(): Int = safeGetInt(storage, "device", DEVICE_ALL)
fun forDevice(device: Int) = device() == device || device() == DEVICE_ALL
fun buttonText(): String = safeGetString(storage, "buttonText", "")
fun carbs(): Int = safeGetInt(storage, "carbs")
@ -148,4 +175,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
fun useSuperBolus(): Int = safeGetInt(storage, "useSuperBolus", NO)
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
}
fun usePercentage(): Int = safeGetInt(storage, "usePercentage", DEFAULT)
fun percentage(): Int = safeGetInt(storage, "percentage", 100)
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_xdrip" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_cp_bolus_carbs" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_bolus" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_fortyfiveup" />
</layer-list>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_bg" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_cob" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_iob" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_trend" />
</selector>

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="80"
android:viewportHeight="80">
<path
android:fillAlpha="0.5"
android:fillColor="#FFFFFF"
android:pathData="M 18 54 a 3 3 0 0 0 3 3 L 45 57 A 19 19 0 0 0 62 40 A 19 19 0 0 0 45 24 L 21 24 a 3 3 0 0 0 -3 3 Z M 67 40 A 22 22 0 0 1 45 62 L 19 62 a 6 6 0 0 1 -6 -6 L 13 25 a 6 6 0 0 1 6 -6 L 45 19 A 22 22 0 0 1 67 40"
android:strokeAlpha="0.5" />
</vector>

View file

@ -23,7 +23,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/carbs"
android:importantForAccessibility="no"
app:srcCompat="@mipmap/ic_launcher" />
<TextView

View file

@ -83,14 +83,14 @@
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:labelFor="@+id/age"
android:text="@string/age"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/age"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/age" />
</TableRow>
@ -105,14 +105,14 @@
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:labelFor="@+id/weight"
android:text="@string/tdd_total"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/tdd"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/tdd_total" />
</TableRow>
@ -123,18 +123,18 @@
android:gravity="center_vertical">
<TextView
android:id="@+id/weigth_label"
android:id="@+id/weight_label"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:labelFor="@+id/weight"
android:text="@string/weight_label"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/weight"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/weight_label" />
</TableRow>
@ -149,14 +149,14 @@
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:labelFor="@+id/basalpctfromtdd"
android:text="@string/basalpctfromtdd_label"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basalpctfromtdd"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/basalpctfromtdd_label" />
</TableRow>

View file

@ -23,7 +23,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/carbs"
android:importantForAccessibility="no"
app:srcCompat="@mipmap/ic_launcher" />
<TextView

View file

@ -1,68 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/bg_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="@color/cardColorBackground"
card_view:cardCornerRadius="6dp"
card_view:cardUseCompatPadding="true"
card_view:contentPadding="6dp">
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="16:55"
android:textStyle="bold" />
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="Name"
android:textStyle="bold" />
android:gravity="center"
android:orientation="horizontal"
android:padding="6dp">
<ImageView
android:id="@+id/direction"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
card_view:srcCompat="@drawable/ic_flat" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="16:55"
android:textStyle="bold" />
<TextView
android:id="@+id/ns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="NS"
android:textAlignment="viewEnd"
android:textColor="@color/colorSetTempButton" />
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="Name"
android:textStyle="bold" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" />
<ImageView
android:id="@+id/direction"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
card_view:srcCompat="@drawable/ic_flat" />
<TextView
android:id="@+id/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="@string/remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
<TextView
android:id="@+id/ns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="NS"
android:textAlignment="viewEnd"
android:textColor="@color/colorSetTempButton" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="@string/remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
</LinearLayout>
</LinearLayout>

View file

@ -8,7 +8,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -20,7 +21,6 @@
android:textSize="14sp"
app:drawableStartCompat="@drawable/ic_cp_age_sensor" />
<TextView
android:id="@+id/sensor_age_label"
android:layout_width="wrap_content"
@ -83,7 +83,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -158,9 +159,11 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:id="@+id/cannula_or_patch"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:gravity="center_vertical"
@ -229,7 +232,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:id="@+id/pb_label"

View file

@ -8,7 +8,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -63,7 +64,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -118,9 +120,11 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:id="@+id/cannula_or_patch"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:gravity="center_vertical"
@ -171,7 +175,8 @@
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:focusable="true">
<TextView
android:id="@+id/pb_label"

View file

@ -26,7 +26,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/overview_calibration"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calibration" />
<TextView
@ -58,6 +58,7 @@
android:paddingTop="10dp">
<TextView
android:id="@+id/bg_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -70,7 +71,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_bg_label" />
<TextView
android:id="@+id/units"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/carbs"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<TextView
@ -93,6 +93,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/time_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -105,25 +106,24 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_access_alarm_24dp" />
<CheckBox
android:id="@+id/alarmCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:padding="2dp" />
android:padding="2dp"
android:layoutDirection="rtl"
android:contentDescription="@string/a11y_carb_reminder"
android:drawableEnd="@drawable/ic_access_alarm_24dp" />
</LinearLayout>
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/time"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/time_offset" />
<TextView
android:layout_width="wrap_content"
@ -143,6 +143,7 @@
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -156,7 +157,8 @@
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
android:layout_gravity="center_horizontal"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"
@ -176,6 +178,7 @@
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -190,7 +193,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -26,7 +26,7 @@
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/careportal_profileswitch"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_profileswitch" />
<TextView
@ -86,6 +86,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/bg_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -98,7 +99,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_bg_label" />
<TextView
android:id="@+id/bg_units"
@ -121,6 +123,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -133,7 +136,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/virtualpump_extendedbolus_label"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_startextbolus" />
<TextView
@ -53,6 +53,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -65,7 +66,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/insulin"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView
android:layout_width="wrap_content"
@ -86,6 +88,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -98,7 +101,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/primefill"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_pump_canula" />
<TextView
@ -75,6 +75,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/fill_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -89,7 +90,8 @@
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
android:paddingRight="5dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/overview_insulin_label"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_bolus" />
<TextView
@ -76,6 +76,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/time_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -88,7 +89,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/time"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/time_offset"/>
<TextView
android:layout_width="wrap_content"
@ -109,6 +111,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -121,7 +124,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/amount"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label"/>
<TextView
android:layout_width="wrap_content"
@ -147,6 +151,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="Increment insuline with 0.5"
android:text="+0.5" />
<Button

View file

@ -26,7 +26,7 @@
android:id="@+id/loop_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="@string/boluswizard"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_loop_closed" />
<TextView

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/careportal_profileswitch"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_profileswitch" />
<TextView
@ -58,6 +58,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:width="120dp"
android:labelFor="@+id/profile"
android:padding="10dp"
android:text="@string/profile_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -95,6 +96,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -108,7 +110,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label"/>
<TextView
android:layout_width="wrap_content"
@ -129,6 +132,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/percentage_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -142,7 +146,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/percentage"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_percentage_label"/>
<TextView
android:layout_width="wrap_content"
@ -163,6 +168,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/timeshift_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -176,7 +182,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/timeshift"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_timeshift_label"/>
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tempbasal_label"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_basal_start" />
<TextView
@ -54,6 +54,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/basal_percent_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -66,7 +67,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basal_percent_input"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/basal_rate" />
<TextView
android:layout_width="wrap_content"
@ -88,6 +90,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/basal_absolute_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -100,7 +103,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basal_absolute_input"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/basal_rate" />
<TextView
android:layout_width="wrap_content"
@ -121,6 +125,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -133,7 +138,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/careportal_temporarytarget"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_temptarget_high" />
<TextView
@ -54,6 +54,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/temptarget_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -67,7 +68,8 @@
android:id="@+id/temptarget"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical" />
android:layout_gravity="center_vertical"
app:customContentDescription="@string/target_label" />
<TextView
android:id="@+id/units"
@ -89,6 +91,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -101,7 +104,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"
@ -127,6 +131,7 @@
android:layout_gravity="center_vertical"
android:width="120dp"
android:padding="10dp"
android:labelFor="@+id/reason"
android:text="@string/reason"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" />

View file

@ -25,30 +25,21 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/overview_treatment_label"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_bolus" />
</RelativeLayout>
<LinearLayout
android:id="@+id/spacer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="@string/overview_treatment_label"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/recordOnlyLayout"
@ -72,6 +63,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -84,7 +76,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/insulin"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView
android:layout_width="wrap_content"
@ -105,6 +98,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -117,7 +111,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="@string/boluswizard"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calculator" />
<TextView
@ -59,6 +59,7 @@
android:layout_height="match_parent">
<TextView
android:id="@+id/bg_input_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -70,7 +71,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg_input"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/a11y_current_bg" />
<TextView
android:id="@+id/bg_units"
@ -89,9 +91,11 @@
android:layout_height="match_parent">
<TextView
android:id="@+id/carbs_input_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:labelFor="@id/carbs_input"
android:padding="10dp"
android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -101,8 +105,8 @@
android:id="@+id/carbs_input"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
android:layout_gravity="center_horizontal"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView
android:layout_width="wrap_content"
@ -127,6 +131,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/correction_input_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -135,32 +140,26 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=" %"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<CheckBox
android:id="@+id/correction_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:padding="2dp" />
android:layoutDirection="rtl"
android:padding="2dp"
android:text="%"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/correction_input"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
android:layout_gravity="center_horizontal"
app:customContentDescription="@string/a11_correction_units" />
<TextView
android:id="@+id/correction_unit"
@ -241,6 +240,69 @@
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center_vertical"
android:layout_marginTop="0dp"
android:background="@android:color/transparent"
android:orientation="horizontal"
android:padding="0dp">
<CheckBox
android:id="@+id/bg_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_bg_icon"
android:checked="true"
android:contentDescription="@string/treatments_wizard_bg_label" />
<CheckBox
android:id="@+id/trend_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_trend_icon"
android:checked="true"
android:contentDescription="@string/bg_trend_label" />
<CheckBox
android:id="@+id/iob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.9"
android:scaleY="0.9"
android:button="@drawable/checkbox_iob_icon"
android:checked="true"
android:contentDescription="@string/iob" />
<CheckBox
android:id="@+id/cob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_cob_icon"
android:checked="true"
android:contentDescription="@string/treatments_wizard_cob_label" />
</LinearLayout>
<LinearLayout
android:id="@+id/done_background"
@ -255,77 +317,16 @@
<CheckBox
android:id="@+id/calculation_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:checked="false"
android:contentDescription="@string/show_calculation"
app:srcCompat="@drawable/ic_visibility" />
android:drawableEnd="@drawable/ic_visibility" />
<ImageView
android:id="@+id/bg_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_xdrip"/>
<include
android:id="@+id/okcancel"
layout="@layout/okcancel" />
<ImageView
android:id="@+id/trend_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_fortyfiveup" />
<ImageView
android:id="@+id/iob_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_bolus" />
<ImageView
android:id="@+id/cob_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<Button
android:id="@+id/cancel"
style="@style/mdtp_ActionButton.Text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/mdtp_cancel"
android:textAlignment="textEnd" />
<Button
android:id="@+id/ok"
style="@style/mdtp_ActionButton.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/mdtp_ok" />
</LinearLayout>
<View
@ -350,6 +351,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/carb_time_input_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -360,27 +362,23 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/alarm"
android:src="@drawable/ic_access_alarm_24dp" />
<CheckBox
android:id="@+id/alarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:contentDescription="set carb timer alarm"
android:drawableEnd="@drawable/ic_access_alarm_24dp"
android:layoutDirection="rtl"
android:padding="2dp" />
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carb_time_input"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center" />
android:layout_gravity="center"
app:contentDescription="carb time" />
<TextView
android:layout_width="wrap_content"
@ -402,6 +400,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:labelFor="@id/profile"
android:padding="10dp"
android:text="@string/profile_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -414,7 +413,6 @@
android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="0.5" />
<CheckBox
android:id="@+id/sb_checkbox"
android:layout_width="wrap_content"
@ -445,38 +443,24 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="@+id/bg_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
<CheckBox
android:id="@+id/bg_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="24dp"
android:text="@string/treatments_wizard_bg_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
android:checked="true"
android:text="@string/treatments_wizard_bg_label" />
<CheckBox
android:id="@+id/tt_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="false" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="30dp"
android:text="@string/treatments_wizard_tt_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
android:checked="false"
android:text="@string/treatments_wizard_tt_label" />
</LinearLayout>
@ -506,15 +490,9 @@
android:id="@+id/bg_trend_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="false" />
android:checked="false"
android:text="@string/bg_trend_label" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/bg_trend_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/bg_trend"
@ -542,15 +520,8 @@
android:id="@+id/iob_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="130dp"
android:text="@string/iob"
android:textAppearance="?android:attr/textAppearanceSmall" />
android:checked="true"
android:text="@string/iob" />
<TextView
android:layout_width="wrap_content"
@ -578,14 +549,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="false" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_cob_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
android:checked="false"
android:text="@string/treatments_wizard_cob_label" />
<TextView
android:id="@+id/cob"
@ -607,19 +572,27 @@
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:focusable="true">
<TextView
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView
android:id="@+id/carbs"
@ -642,19 +615,27 @@
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:focusable="true">
<TextView
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/superbolus"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/superbolus"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView
android:id="@+id/sb"
@ -676,19 +657,27 @@
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:focusable="true">
<TextView
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_correction_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_correction_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
@ -704,6 +693,7 @@
android:width="50dp"
android:gravity="end"
android:textAppearance="?android:attr/textAppearanceSmall" />
</TableRow>
</TableLayout>
@ -712,4 +702,4 @@
</LinearLayout>
</ScrollView>
</ScrollView>

View file

@ -25,7 +25,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/carbs"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calculator" />
<TextView

View file

@ -22,6 +22,7 @@
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/spinner"
android:text="@string/selected_profile"
android:textAppearance="?android:attr/textAppearanceMedium" />
@ -35,6 +36,40 @@
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/name"
android:text="@string/profile_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:ems="10"
android:importantForAutofill="no"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -63,7 +98,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/addnew"
android:contentDescription="@string/a11y_add_new_profile"
app:srcCompat="@drawable/ic_add" />
<ImageView
@ -72,7 +107,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/clone_label"
android:contentDescription="@string/a11y_clone_profile"
app:srcCompat="@drawable/ic_clone" />
<ImageView
@ -81,7 +116,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/remove_label"
android:contentDescription="@string/a11y_delete_current_profile"
android:scaleX="1"
android:scaleY="1"
app:srcCompat="@drawable/ic_remove" />
@ -152,32 +187,13 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/name"
android:text="@string/profile_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:ems="10"
android:importantForAutofill="no"
android:inputType="text" />
</LinearLayout>
android:gravity="center_horizontal"
android:text="@string/dia_long_label"
android:textColor="@android:color/white"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
@ -187,6 +203,7 @@
android:paddingTop="5dp">
<TextView
android:id="@+id/dia_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -199,7 +216,8 @@
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp" />
android:layout_marginBottom="10dp"
app:customContentDescription="@string/dia" />
<TextView
android:layout_width="wrap_content"
@ -210,6 +228,12 @@
</LinearLayout>
<info.nightscout.androidaps.plugins.insulin.ActivityGraph
android:id="@+id/insulin_graph"
android:layout_width="match_parent"
android:layout_height="100dip"
android:layout_margin="20dp" />
</LinearLayout>
<LinearLayout
@ -277,11 +301,23 @@
<LinearLayout
android:id="@+id/target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/target_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<info.nightscout.androidaps.utils.ui.TargetBgProfileGraph
android:id="@+id/target_graph"
android:layout_width="match_parent"
android:layout_height="100dip"
android:layout_margin="20dp" />
</LinearLayout>
<Button

View file

@ -20,6 +20,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -65,7 +66,9 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:focusable="true"
android:orientation="horizontal"
android:screenReaderFocusable="true">
<TextView
android:layout_width="match_parent"
@ -110,6 +113,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -155,6 +159,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -200,6 +205,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -245,6 +251,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -290,6 +297,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -335,6 +343,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -380,6 +389,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -425,6 +435,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
@ -470,6 +481,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView

View file

@ -27,7 +27,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -98,7 +99,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -143,7 +145,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -188,7 +191,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -233,7 +237,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -278,7 +283,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -323,7 +329,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -368,7 +375,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -448,7 +456,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -493,7 +502,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -538,7 +548,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"

View file

@ -126,6 +126,7 @@
android:layout_weight="0.5"
android:drawableTop="@drawable/ic_quick_wizard"
android:text="@string/quickwizard"
android:hint="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp"
tools:ignore="SmallSp" />

View file

@ -21,7 +21,7 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/quickwizard"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_quick_wizard" />
<TextView
@ -108,6 +108,35 @@
</LinearLayout>
<TextView
android:id="@+id/device_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_show_on_device"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<RadioGroup
android:id="@+id/device"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp">
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="All" />
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Phone" />
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Watch" />
</RadioGroup>
<TextView
android:layout_width="match_parent"
@ -276,7 +305,6 @@
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -301,6 +329,47 @@
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_usepercentage"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<RadioGroup
android:id="@+id/use_percentage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp">
<RadioButton
android:id="@+id/use_percentage_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_default" />
<RadioButton
android:id="@+id/use_percentage_custom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/custom" />
</RadioGroup>
<TextView
android:id="@+id/percentage_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_percentage"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<EditText
android:id="@+id/percentage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:maxLength="3"
android:paddingLeft="10dp" />
<include
android:id="@+id/okcancel"

View file

@ -39,6 +39,7 @@
android:gravity="center_vertical|center_horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:hint="active profile"
android:text="Profile"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
@ -52,6 +53,7 @@
android:gravity="center_vertical|center_horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:hint="temp target"
android:text="@string/notavailable"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"

View file

@ -14,7 +14,8 @@
<com.jjoe64.graphview.GraphView
android:id="@+id/bg_graph"
android:layout_width="wrap_content"
android:layout_height="200dp" />
android:layout_height="200dp"
android:contentDescription="@string/a11y_graph"/>
<ImageButton
android:id="@+id/chart_menu_button"

View file

@ -25,7 +25,7 @@
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="Blood glucose quality icon"
android:contentDescription="@string/a11y_bg_quality"
tools:ignore="HardcodedText" />
<TextView
@ -52,7 +52,8 @@
app:layout_constraintEnd_toStartOf="@+id/deltas_layout"
app:layout_constraintStart_toEndOf="@+id/delta_large"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView
android:id="@+id/arrow"
@ -87,7 +88,8 @@
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -95,6 +97,7 @@
android:layout_gravity="end"
android:textAlignment="textEnd"
android:text="Δ: "
android:contentDescription="last delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
@ -113,7 +116,8 @@
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -121,6 +125,7 @@
android:layout_gravity="end"
android:textAlignment="textEnd"
android:text="15m Δ: "
android:contentDescription="15 minutes delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
@ -139,7 +144,8 @@
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="wrap_content"
@ -147,6 +153,7 @@
android:layout_gravity="end"
android:textAlignment="textEnd"
android:text="40m Δ: "
android:contentDescription="40 minutes delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
@ -185,7 +192,7 @@
android:layout_marginBottom="-4dp"
android:visibility="gone"
app:srcCompat="@drawable/ic_loop_closed"
android:contentDescription="@string/closedloop" />
android:contentDescription="@string/apsmode_title" />
<TextView
android:id="@+id/aps_mode_text"
@ -282,7 +289,8 @@
app:layout_constraintEnd_toStartOf="@+id/basal_layout"
app:layout_constraintStart_toEndOf="@+id/iob_layout"
app:layout_constraintTop_toTopOf="@+id/iob_layout"
tools:ignore="UseCompoundDrawables">
tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView
android:id="@+id/carbs_icon"
@ -377,7 +385,8 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/extended_layout"
app:layout_constraintTop_toTopOf="@+id/iob_layout"
tools:ignore="UseCompoundDrawables">
tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView
android:id="@+id/sensitivity_icon"
@ -385,7 +394,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:srcCompat="@drawable/ic_swap_vert_black_48dp_green"
android:contentDescription="@string/autosenslabel" />
android:contentDescription="@string/a11y_autosenslabel" />
<TextView
android:id="@+id/sensitivity"
@ -398,6 +407,19 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/variable_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-9dp"
android:gravity="center_horizontal"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
android:visibility="visible"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -16,9 +16,9 @@
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
@ -29,37 +29,64 @@
card_view:srcCompat="@drawable/ic_quick_wizard" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/overview_quickwizard_item_buttonText"
<TextView
android:id="@+id/overview_quickwizard_item_buttonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="Sample button text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/cardObjectiveText"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/overview_quickwizard_item_carbs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="36g"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/cardObjectiveText"
android:textStyle="normal|bold" />
</LinearLayout>
<ImageView
android:id="@+id/overview_quickwizard_item_device"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="Sample button text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="normal|bold"
android:textColor="@color/cardObjectiveText" />
android:adjustViewBounds="false"
android:cropToPadding="false"
android:paddingRight="10dp"
android:scaleType="fitStart"
card_view:srcCompat="@drawable/ic_smartphone" />
<TextView
android:id="@+id/overview_quickwizard_item_carbs"
<ImageView
android:id="@+id/handleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="36g"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/cardObjectiveText"
android:textStyle="normal|bold" />
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:adjustViewBounds="false"
android:cropToPadding="false"
android:scaleType="fitStart"
card_view:srcCompat="@drawable/ic_reorder_gray_24dp" />
</LinearLayout>
@ -88,9 +115,9 @@
android:textStyle="normal|bold" />
<TextView
android:text="-"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:text="-" />
<TextView
android:id="@+id/overview_quickwizard_item_to"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_lights"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -11,100 +12,117 @@
android:paddingTop="4dp"
android:paddingBottom="4dp">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_cannula"
android:contentDescription="@string/cannula" />
android:focusable="true"
android:gravity="center_horizontal">
<TextView
android:id="@+id/cannula_age"
<ImageView
android:id="@+id/cannula_or_patch"
android:layout_width="38dp"
android:layout_height="fill_parent"
android:contentDescription="@string/statuslights_cannula_age"
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_cannula" />
<TextView
android:id="@+id/cannula_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
tools:text="1d12h" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:scaleX="1.8"
android:scaleY="1.8"
app:srcCompat="@drawable/ic_cp_age_insulin"
android:contentDescription="@string/insulin_label" />
android:focusable="true"
android:gravity="center_horizontal">
<TextView
android:id="@+id/insulin_age"
<ImageView
android:layout_width="26dp"
android:layout_height="fill_parent"
android:contentDescription="@string/a11y_insulin_label"
android:scaleX="1.7"
android:scaleY="1.7"
app:srcCompat="@drawable/ic_cp_age_insulin" />
<TextView
android:id="@+id/insulin_age"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:lines="1"
tools:text="12h" />
<TextView
android:id="@+id/reservoir_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:paddingStart="2dp"
tools:text="50+U" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/reservoir_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_sensor"
android:contentDescription="@string/careportal_sensor_label" />
android:focusable="true"
android:gravity="center_horizontal">
<TextView
android:id="@+id/sensor_age"
<ImageView
android:layout_width="28dp"
android:layout_height="fill_parent"
android:contentDescription="@string/careportal_sensor_label"
android:scaleX="1.6"
android:scaleY="1.6"
app:srcCompat="@drawable/ic_cp_age_sensor" />
<TextView
android:id="@+id/sensor_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
tools:text="1d12h" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_battery"
android:contentDescription="@string/battery_label" />
android:focusable="true"
android:gravity="center_horizontal">
<TextView
android:id="@+id/pb_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:textSize="14sp" />
<ImageView
android:layout_width="32dp"
android:layout_height="wrap_content"
android:contentDescription="@string/battery_label"
android:scaleX="1.8"
android:scaleY="1.8"
app:srcCompat="@drawable/ic_cp_age_battery" />
<TextView
android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/pb_age"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:lines="1"
tools:text="-" />
<TextView
android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:lines="1"
android:paddingStart="2dp"
tools:text="100%" />
</LinearLayout>
</LinearLayout>

View file

@ -38,6 +38,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:contentDescription="@string/addnew_above"
app:srcCompat="@drawable/ic_add" />
<ImageView
@ -46,5 +47,6 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:contentDescription="@string/remove_label"
app:srcCompat="@drawable/ic_remove" />
</LinearLayout>

View file

@ -38,6 +38,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:contentDescription="@string/addnew_above"
app:srcCompat="@drawable/ic_add" />
<ImageView
@ -46,5 +47,6 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:contentDescription="@string/remove_label"
app:srcCompat="@drawable/ic_remove" />
</LinearLayout>

View file

@ -12,6 +12,20 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:id="@+id/metadata_layout"
android:layout_width="match_parent"
@ -29,11 +43,11 @@
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/date"
android:id="@+id/calc_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="1.1.2000"
android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
@ -65,17 +79,17 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/bolus_date"
android:id="@+id/bolus_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="1.1.2000"
android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
@ -173,17 +187,17 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginStart="5dp"
android:gravity="center"
android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/carbs_date"
android:id="@+id/carbs_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="1.1.2000"
android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
@ -258,6 +272,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,11 +43,11 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/date"
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="10dp"
android:text="1.1.2000 18:00"
android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
@ -111,6 +124,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginStart="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,10 +43,10 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/date"
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.1.2000 18:00"
android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
@ -158,6 +171,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,11 +43,11 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/date"
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="1.1.2000 18:00"
android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
@ -124,6 +137,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,10 +43,10 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/date"
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.1.2000 18:00"
android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
@ -178,6 +191,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,7 +43,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/date"
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
@ -146,6 +159,7 @@
</LinearLayout>
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginLeft="5dp"

View file

@ -5,82 +5,96 @@
android:id="@+id/info_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:orientation="horizontal">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="3dp"
android:text="1.1.2021 09:00"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/iconSource"
app:layout_constraintBottom_toBottomOf="@+id/iconSource"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="3dp"
android:text="09:00"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="@+id/iconSource"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/iconSource"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/action"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="3dp"
android:text="USER ENTRY"
app:layout_constraintStart_toEndOf="@id/date"
app:layout_constraintEnd_toStartOf="@+id/iconSource"
app:layout_constraintTop_toTopOf="parent"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/action"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="3dp"
android:text="USER ENTRY"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintEnd_toStartOf="@+id/iconSource"
app:layout_constraintStart_toEndOf="@id/time"
app:layout_constraintTop_toBottomOf="@id/date" />
<ImageView
android:id="@+id/iconSource"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/action"
app:layout_constraintBottom_toBottomOf="@+id/action"
app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<ImageView
android:id="@+id/iconSource"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="@+id/action"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/action"
app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<TextView
android:id="@+id/values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="10dp"
android:text="Values with units"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/action" />
<TextView
android:id="@+id/values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="10dp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/action"
android:visibility="gone"
android:text="Values with units" />
<TextView
android:id="@+id/s"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/values"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="gone"
android:text="Notes"
tools:ignore="HardcodedText,RtlSymmetry" />
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/s"
android:background="@color/list_delimiter" />
<TextView
android:id="@+id/notes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="10dp"
android:text="Notes"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/values"
tools:ignore="HardcodedText,RtlSymmetry" />
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/notes" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -25,7 +25,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -69,7 +70,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -113,7 +115,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -157,7 +160,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -202,7 +206,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -247,7 +252,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -292,7 +298,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -337,7 +344,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:focusable="true">
<TextView
android:layout_width="match_parent"
@ -369,8 +377,6 @@
</LinearLayout>
</LinearLayout>
</ScrollView>

View file

@ -80,6 +80,7 @@
<string name="description_ns_client">Synchronizes your data with Nightscout</string>
<string name="description_ama">State of the algorithm in 2017</string>
<string name="description_smb">Most recent algorithm for advanced users</string>
<string name="description_smb_dynamic_isf">Most recent algorithm for advanced users with dynamic/automatic ISF</string>
<string name="description_overview">Displays the current state of your loop and buttons for most common actions</string>
<string name="description_persistent_notification">Shows an ongoing notification with a short overview of what your loop is doing</string>
<string name="description_profile_local">Define a profile which is available offline.</string>
@ -169,7 +170,6 @@
<string name="configbuilder_bgsource_description">Where should AndroidAPS gain it\'s data from?</string>
<string name="xdrip">xDrip+</string>
<string name="apsmode_title">APS Mode</string>
<string name="closedloop">Closed Loop</string>
<string name="openloop">Open Loop</string>
<string name="lowglucosesuspend">Low Glucose Suspend</string>
@ -314,7 +314,7 @@
<string name="wear">Wear</string>
<string name="resend_all_data">Resend All Data</string>
<string name="open_settings_on_wear">Open Settings on Wear</string>
<string name="basal_rate">Basal rate:</string>
<string name="basal_rate">Basal rate</string>
<string name="basalvaluebelowminimum">Basal value below minimum. Profile not set!</string>
<string name="sms_actualbg">BG:</string>
<string name="sms_lastbg">Last BG:</string>
@ -536,6 +536,7 @@
<string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip+). Do not enable if you have more than one instance of AAPS or NSClient installed!</string>
<string name="ns_localbroadcasts_title">Enable local Broadcasts.</string>
<string name="openapssmb">OpenAPS SMB</string>
<string name="openaps_smb_dynamic_isf">OpenAPS SMB Dynamic ISF</string>
<string name="key_use_smb" translatable="false">use_smb</string>
<string name="key_use_uam" translatable="false">use_uam</string>
<string name="key_smb_enable_carbs_suggestions_threshold" translatable="false">smb_enable_carbs_suggestions_threshold</string>
@ -618,6 +619,7 @@
<string name="negativeonly">Negative only</string>
<string name="overview_editquickwizard_usecob">COB calculation</string>
<string name="overview_editquickwizard_usetemptarget">Temporary target calculation</string>
<string name="overview_editquickwizard_usepercentage">Percentage calculation</string>
<string name="loopenabled">Loop enabled</string>
<string name="apsselected">APS selected</string>
<string name="nsclienthaswritepermission">NSClient has write permission</string>
@ -954,8 +956,8 @@
<string name="low_mark_comment">Lower value of in range area (display only)</string>
<string name="high_mark_comment">Higher value of in range area (display only)</string>
<string name="age">Age:</string>
<string name="weight_label">Weight:</string>
<string name="age">Age</string>
<string name="weight_label">Weight</string>
<string name="id">ID:</string>
<string name="submit">Submit</string>
<string name="mostcommonprofile">Most common profile:</string>
@ -1133,11 +1135,76 @@
<string name="errors">Errors</string>
<string name="ns_sync_slow">Slow down uploads</string>
<string name="data_status">BG data status</string>
<string name="statuslights_cannula_age">cannula age</string>
<string name="statuslights_patch_pump_age">patch pump age</string>
<string name="patch_pump">Patch pump</string>
<string name="recalculated_data_used">Recalculated data used</string>
<string name="bg_too_close">BG too close:\n%1$s\n%2$s</string>
<string name="key_last_processed_glunovo_timestamp" translatable="false">last_processed_glunovo_timestamp</string>
<string name="identification">Identification (email, FB or Discord nick etc)</string>
<string name="identification_not_set">Identification not set in dev mode</string>
<string name="a11y_dialog">dialog</string>
<string name="a11y_current_bg">current blood glucose</string>
<string name="a11_correction_percentage">correct outcome with %</string>
<string name="a11_correction_units">correct outcome with units</string>
<string name="not_available_full">Not available</string>
<string name="a11y_high">high</string>
<string name="a11y_inrange">in range</string>
<string name="a11y_low">low</string>
<string name="a11y_arrow_double_down">falling rapidly</string>
<string name="a11y_arrow_single_down">falling</string>
<string name="a11y_arrow_forty_five_down">falling slowly</string>
<string name="a11y_arrow_flat">stable</string>
<string name="a11y_arrow_forty_five_up">rising slowly</string>
<string name="a11y_arrow_single_up">rising</string>
<string name="a11y_arrow_double_up">rising rapidly</string>
<string name="a11y_arrow_none">none</string>
<string name="a11y_arrow_unknown">unknown</string>
<string name="a11y_graph">graph</string>
<string name="a11y_bg_quality">blood glucose quality</string>
<string name="a11y_bg_quality_recalculated">recalculated</string>
<string name="a11y_bg_quality_doubles">double entries</string>
<string name="a11y_insulin_label">insulin</string>
<string name="a11y_blood_glucose">blood glucose</string>
<string name="a11y_bg_outdated">outdated</string>
<string name="a11y_carb_reminder">set reminder</string>
<string name="a11y_add_new_profile">add new profile</string>
<string name="a11y_clone_profile">clone current profile</string>
<string name="a11y_delete_current_profile">delete current profile</string>
<string name="a11y_add_new_to_list">add new to list</string>
<!-- WEAR OS-->
<string name="wear_action_tempt_preset_error">Temptarget unknown preset: %1$s</string>
<string name="wear_action_tempt_cancel_message">Cancelling running Temp-Targets?</string>
<string name="wear_action_tempt_unit_error">Different units used on watch and phone!</string>
<string name="wear_action_tempt_zero_message">Zero-Temp-Target - cancelling running Temp-Targets?</string>
<string name="wear_action_tempt_min_bg_error">Min-BG out of range!</string>
<string name="wear_action_tempt_max_bg_error">Max-BG out of range!</string>
<string name="wear_action_tempt_manual_range_message">Temptarget:\nMin: %1$s\nMax: %2$s\nDuration: %3$s</string>
<string name="wear_action_tempt_manual_message">Temptarget:\nTarget: %1$s\nDuration: %2$s</string>
<string name="wear_action_tempt_preset_message">Temptarget:\Reason: %1$s\nTarget: %2$s\nDuration: %3$s</string>
<string name="quick_wizard_message">QuickWizard: %1$s\nInsulin: %2$.2fU\nCarbs: %3$dg</string>
<string name="wizard_result">Calc. Wizard:\nInsulin: %1$.2fU\nCarbs: %2$dg</string>
<string name="overview_editquickwizard_show_on_device">Show entry on device:</string>
<string name="quick_wizard_not_available">Selected quickwizard no longer available, please refresh your tile</string>
<string name="wizard_no_actual_bg">No recent BG to base calculation on!</string>
<string name="wizard_no_active_profile">No active profile set!</string>
<string name="wizard_no_cob">Unknown COB! BG reading missing or recent app restart?</string>
<string name="wizard_carbs_constraint">Carb constraint violation!</string>
<string name="wizard_explain_calc">Calc (IC: %2$.1f, ISF: %2$.1f) from:"</string>
<string name="wizard_explain_carbs">Carbs: %1$.2fU</string>
<string name="wizard_explain_cob">COB: %1$.0fg %2$.2fU</string>
<string name="wizard_explain_bg">BG: %1$.2fU</string>
<string name="wizard_explain_basal_iob">Basal IOB: %1$.2fU</string>
<string name="wizard_explain_bolus_iob">Bolus IOB: %1$.2fU</string>
<string name="wizard_explain_superbolus">Superbolus: %1$.2fU</string>
<string name="wizard_explain_trend">15\' trend: %1$.2fU</string>
<string name="wizard_explain_percent">Percentage: %1$.2fU x %2$d%% ≈ %3$.2fU</string>
<string name="wizard_constraint_bolus_size">Insulin constraint violation!\nCannot deliver %1$.2fU</string>
<string name="wizard_explain_tt">TempT: %1$s</string>
<string name="wizard_explain_tt_to">%1$s to %2$s</string>
<string name="wizard_pump_not_available">No pump available!</string>
<string name="wear_unknown_action_string">Unknown action command:</string>
<string name="overview_editquickwizard_percentage">Percentage</string>
<string name="app_default">Application default</string>
</resources>

Some files were not shown because too many files have changed in this diff Show more