commit
5627f38f97
124 changed files with 4316 additions and 875 deletions
|
@ -109,7 +109,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
versionCode 1500
|
versionCode 1500
|
||||||
version "3.0.0.1-dev"
|
version "3.0.0.1-dev-a"
|
||||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||||
|
|
1231
app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js
Normal file
1231
app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -239,6 +239,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
|
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)
|
switchTab(0, typeSelected[0], false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.openAPSAMA.DetermineBasalResultAMA
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
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.IobCobOref1Thread
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ abstract class APSModule {
|
||||||
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
|
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
|
||||||
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
||||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
||||||
|
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
|
||||||
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
|
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
|
||||||
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
|
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
|
||||||
}
|
}
|
|
@ -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.loop.LoopPlugin
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
|
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
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.configBuilder.ConfigBuilderPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
|
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
|
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
|
||||||
|
@ -212,6 +213,12 @@ abstract class PluginsModule {
|
||||||
@IntKey(220)
|
@IntKey(220)
|
||||||
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
|
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@APS
|
||||||
|
@IntoMap
|
||||||
|
@IntKey(222)
|
||||||
|
abstract fun bindOpenAPSSMBAutoISFPlugin(plugin: OpenAPSSMBDynamicISFPlugin): PluginBase
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@AllConfigs
|
@AllConfigs
|
||||||
@IntoMap
|
@IntoMap
|
||||||
|
|
|
@ -64,6 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
||||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: 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.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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -137,32 +137,39 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
savedInstanceState?.getDouble("carbs")
|
savedInstanceState?.getDouble("carbs")
|
||||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
|
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
|
||||||
)
|
)
|
||||||
|
val plus1text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||||
binding.plus1.text = 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.plus1.setOnClickListener {
|
||||||
binding.carbs.value = max(
|
binding.carbs.value = max(
|
||||||
0.0, binding.carbs.value
|
0.0, binding.carbs.value
|
||||||
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
|
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
|
||||||
)
|
)
|
||||||
validateInputs()
|
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.plus2.setOnClickListener {
|
||||||
binding.carbs.value = max(
|
binding.carbs.value = max(
|
||||||
0.0, binding.carbs.value
|
0.0, binding.carbs.value
|
||||||
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
|
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
|
||||||
)
|
)
|
||||||
validateInputs()
|
validateInputs()
|
||||||
|
binding.carbs.announceValue()
|
||||||
}
|
}
|
||||||
|
val plus3text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||||
binding.plus3.text = 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.plus3.setOnClickListener {
|
||||||
binding.carbs.value = max(
|
binding.carbs.value = max(
|
||||||
0.0, binding.carbs.value
|
0.0, binding.carbs.value
|
||||||
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
|
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
|
||||||
)
|
)
|
||||||
validateInputs()
|
validateInputs()
|
||||||
|
binding.carbs.announceValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
setOnValueChangedListener { eventTime: Long ->
|
setOnValueChangedListener { eventTime: Long ->
|
||||||
|
@ -188,6 +195,9 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
binding.hypoTt.isChecked = false
|
binding.hypoTt.isChecked = false
|
||||||
binding.activityTt.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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -165,6 +165,8 @@ class CareDialog : DialogFragmentWithDate() {
|
||||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: 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)
|
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
|
||||||
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
|
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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -70,6 +70,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||||
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
|
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
|
||||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||||
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: 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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -96,7 +96,7 @@ class FillDialog : DialogFragmentWithDate() {
|
||||||
} else {
|
} else {
|
||||||
binding.fillPresetButton3.visibility = View.GONE
|
binding.fillPresetButton3.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
binding.fillInsulinamount.editText?.id?.let { binding.fillLabel.labelFor = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -116,29 +116,40 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
binding.amount.setParams(savedInstanceState?.getDouble("amount")
|
binding.amount.setParams(savedInstanceState?.getDouble("amount")
|
||||||
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
?: 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.plus05.setOnClickListener {
|
||||||
binding.amount.value = max(0.0, binding.amount.value
|
binding.amount.value = max(0.0, binding.amount.value
|
||||||
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||||
validateInputs()
|
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.plus10.setOnClickListener {
|
||||||
binding.amount.value = max(0.0, binding.amount.value
|
binding.amount.value = max(0.0, binding.amount.value
|
||||||
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||||
validateInputs()
|
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.plus20.setOnClickListener {
|
||||||
binding.amount.value = max(0.0, binding.amount.value
|
binding.amount.value = max(0.0, binding.amount.value
|
||||||
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||||
validateInputs()
|
validateInputs()
|
||||||
|
binding.amount.announceValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.timeLayout.visibility = View.GONE
|
binding.timeLayout.visibility = View.GONE
|
||||||
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
||||||
binding.timeLayout.visibility = isChecked.toVisibility()
|
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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -148,6 +148,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.ttLayout.visibility = View.GONE
|
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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -86,6 +86,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
binding.percentLayout.visibility = View.GONE
|
binding.percentLayout.visibility = View.GONE
|
||||||
binding.absoluteLayout.visibility = View.VISIBLE
|
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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -120,6 +120,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
longClick(it)
|
longClick(it)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
||||||
|
binding.temptarget.editText?.id?.let { binding.temptargetLabel.labelFor = it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
||||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
||||||
binding.recordOnlyLayout.visibility = View.GONE
|
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() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -70,7 +70,7 @@ class WizardInfoDialog : DaggerDialogFragment() {
|
||||||
val units = profileFunction.getUnits()
|
val units = profileFunction.getUnits()
|
||||||
val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
|
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 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, profileFunction.getUnits())
|
val trend = Profile.toUnitsString(data.glucoseTrend * 3, data.glucoseTrend * 3 * Constants.MGDL_TO_MMOLL, units)
|
||||||
// BG
|
// BG
|
||||||
binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, isf)
|
binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, isf)
|
||||||
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)
|
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.MealData
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
|
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
|
||||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||||
|
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
|
||||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
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.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
|
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.loop.ScriptReader
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
@ -30,7 +32,7 @@ import java.nio.charset.StandardCharsets
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.min
|
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
|
private val injector: HasAndroidInjector
|
||||||
|
|
||||||
|
@ -48,21 +50,15 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
|
||||||
private var currentTemp = JSONObject()
|
private var currentTemp = JSONObject()
|
||||||
private var autosensData = JSONObject()
|
private var autosensData = JSONObject()
|
||||||
|
|
||||||
var currentTempParam: String? = null
|
override var currentTempParam: String? = null
|
||||||
private set
|
override var iobDataParam: String? = null
|
||||||
var iobDataParam: String? = null
|
override var glucoseStatusParam: String? = null
|
||||||
private set
|
override var profileParam: String? = null
|
||||||
var glucoseStatusParam: String? = null
|
override var mealDataParam: String? = null
|
||||||
private set
|
override var scriptDebug = ""
|
||||||
var profileParam: String? = null
|
|
||||||
private set
|
|
||||||
var mealDataParam: String? = null
|
|
||||||
private set
|
|
||||||
var scriptDebug = ""
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
operator fun invoke(): DetermineBasalResultAMA? {
|
override operator fun invoke(): APSResult? {
|
||||||
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
||||||
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
|
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
|
||||||
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
|
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
|
||||||
|
@ -143,18 +139,25 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
@Throws(JSONException::class) fun setData(profile: Profile,
|
@Throws(JSONException::class)
|
||||||
maxIob: Double,
|
override fun setData(
|
||||||
maxBasal: Double,
|
profile: Profile,
|
||||||
minBg: Double,
|
maxIob: Double,
|
||||||
maxBg: Double,
|
maxBasal: Double,
|
||||||
targetBg: Double,
|
minBg: Double,
|
||||||
basalRate: Double,
|
maxBg: Double,
|
||||||
iobArray: Array<IobTotal>,
|
targetBg: Double,
|
||||||
glucoseStatus: GlucoseStatus,
|
basalRate: Double,
|
||||||
mealData: MealData,
|
iobArray: Array<IobTotal>,
|
||||||
autosensDataRatio: Double,
|
glucoseStatus: GlucoseStatus,
|
||||||
tempTargetSet: Boolean) {
|
mealData: MealData,
|
||||||
|
autosensDataRatio: Double,
|
||||||
|
tempTargetSet: Boolean,
|
||||||
|
microBolusAllowed: Boolean,
|
||||||
|
uamAllowed: Boolean,
|
||||||
|
advancedFiltering: Boolean,
|
||||||
|
isSaveCgmSource: Boolean
|
||||||
|
) {
|
||||||
this.profile = JSONObject()
|
this.profile = JSONObject()
|
||||||
this.profile.put("max_iob", maxIob)
|
this.profile.put("max_iob", maxIob)
|
||||||
this.profile.put("dia", min(profile.dia, 3.0))
|
this.profile.put("dia", min(profile.dia, 3.0))
|
||||||
|
|
|
@ -96,7 +96,7 @@ class OpenAPSAMAFragment : DaggerFragment() {
|
||||||
binding.result.text = jsonFormatter.format(lastAPSResult.json)
|
binding.result.text = jsonFormatter.format(lastAPSResult.json)
|
||||||
binding.request.text = lastAPSResult.toSpanned()
|
binding.request.text = lastAPSResult.toSpanned()
|
||||||
}
|
}
|
||||||
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
|
openAPSAMAPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterAMAJS ->
|
||||||
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
|
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
|
||||||
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
|
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -60,8 +60,8 @@ class OpenAPSAMAPlugin @Inject constructor(
|
||||||
// last values
|
// last values
|
||||||
override var lastAPSRun: Long = 0
|
override var lastAPSRun: Long = 0
|
||||||
override var lastAPSResult: DetermineBasalResultAMA? = null
|
override var lastAPSResult: DetermineBasalResultAMA? = null
|
||||||
var lastDetermineBasalAdapterAMAJS: DetermineBasalAdapterAMAJS? = null
|
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
|
||||||
var lastAutosensResult: AutosensResult = AutosensResult()
|
override var lastAutosensResult: AutosensResult = AutosensResult()
|
||||||
|
|
||||||
override fun specialEnableCondition(): Boolean {
|
override fun specialEnableCondition(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
|
@ -158,7 +158,7 @@ class OpenAPSAMAPlugin @Inject constructor(
|
||||||
// Fix bug determine basal
|
// Fix bug determine basal
|
||||||
if (determineBasalResultAMA == null) {
|
if (determineBasalResultAMA == null) {
|
||||||
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
||||||
lastDetermineBasalAdapterAMAJS = null
|
lastDetermineBasalAdapter = null
|
||||||
lastAPSResult = null
|
lastAPSResult = null
|
||||||
lastAPSRun = 0
|
lastAPSRun = 0
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,8 +167,8 @@ class OpenAPSAMAPlugin @Inject constructor(
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
|
determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
|
||||||
determineBasalResultAMA.inputConstraints = inputConstraints
|
determineBasalResultAMA.inputConstraints = inputConstraints
|
||||||
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS
|
lastDetermineBasalAdapter = determineBasalAdapterAMAJS
|
||||||
lastAPSResult = determineBasalResultAMA
|
lastAPSResult = determineBasalResultAMA as DetermineBasalResultAMA
|
||||||
lastAPSRun = now
|
lastAPSRun = now
|
||||||
}
|
}
|
||||||
rxBus.send(EventOpenAPSUpdateGui())
|
rxBus.send(EventOpenAPSUpdateGui())
|
||||||
|
|
|
@ -7,14 +7,11 @@ import info.nightscout.androidaps.data.MealData
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
|
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
|
||||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.*
|
||||||
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.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
|
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.loop.ScriptReader
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
|
@ -31,7 +28,7 @@ import java.lang.reflect.InvocationTargetException
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import javax.inject.Inject
|
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 aapsLogger: AAPSLogger
|
||||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||||
|
@ -51,21 +48,16 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
|
||||||
private var smbAlwaysAllowed = false
|
private var smbAlwaysAllowed = false
|
||||||
private var currentTime: Long = 0
|
private var currentTime: Long = 0
|
||||||
private var saveCgmSource = false
|
private var saveCgmSource = false
|
||||||
var currentTempParam: String? = null
|
|
||||||
private set
|
override var currentTempParam: String? = null
|
||||||
var iobDataParam: String? = null
|
override var iobDataParam: String? = null
|
||||||
private set
|
override var glucoseStatusParam: String? = null
|
||||||
var glucoseStatusParam: String? = null
|
override var profileParam: String? = null
|
||||||
private set
|
override var mealDataParam: String? = null
|
||||||
var profileParam: String? = null
|
override var scriptDebug = ""
|
||||||
private set
|
|
||||||
var mealDataParam: String? = null
|
|
||||||
private set
|
|
||||||
var scriptDebug = ""
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
operator fun invoke(): DetermineBasalResultSMB? {
|
override operator fun invoke(): APSResult? {
|
||||||
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
||||||
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
|
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, "IOB data: " + iobData.toString().also { iobDataParam = it })
|
||||||
|
@ -155,22 +147,24 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
|
||||||
return determineBasalResultSMB
|
return determineBasalResultSMB
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection") fun setData(profile: Profile,
|
@Suppress("SpellCheckingInspection")
|
||||||
maxIob: Double,
|
override fun setData(
|
||||||
maxBasal: Double,
|
profile: Profile,
|
||||||
minBg: Double,
|
maxIob: Double,
|
||||||
maxBg: Double,
|
maxBasal: Double,
|
||||||
targetBg: Double,
|
minBg: Double,
|
||||||
basalRate: Double,
|
maxBg: Double,
|
||||||
iobArray: Array<IobTotal>,
|
targetBg: Double,
|
||||||
glucoseStatus: GlucoseStatus,
|
basalRate: Double,
|
||||||
mealData: MealData,
|
iobArray: Array<IobTotal>,
|
||||||
autosensDataRatio: Double,
|
glucoseStatus: GlucoseStatus,
|
||||||
tempTargetSet: Boolean,
|
mealData: MealData,
|
||||||
microBolusAllowed: Boolean,
|
autosensDataRatio: Double,
|
||||||
uamAllowed: Boolean,
|
tempTargetSet: Boolean,
|
||||||
advancedFiltering: Boolean,
|
microBolusAllowed: Boolean,
|
||||||
isSaveCgmSource: Boolean
|
uamAllowed: Boolean,
|
||||||
|
advancedFiltering: Boolean,
|
||||||
|
isSaveCgmSource: Boolean
|
||||||
) {
|
) {
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
val pumpBolusStep = pump.pumpDescription.bolusStep
|
val pumpBolusStep = pump.pumpDescription.bolusStep
|
||||||
|
|
|
@ -10,6 +10,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
|
||||||
|
|
||||||
private var eventualBG = 0.0
|
private var eventualBG = 0.0
|
||||||
private var snoozeBG = 0.0
|
private var snoozeBG = 0.0
|
||||||
|
var variableSens: Double? = null
|
||||||
|
|
||||||
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
|
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
|
||||||
date = dateUtil.now()
|
date = dateUtil.now()
|
||||||
|
@ -50,6 +51,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
|
||||||
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
|
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.has("variable_sens")) variableSens = result.getDouble("variable_sens");
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
|
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ import android.view.ViewGroup
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
|
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
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.JSONFormatter
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
@ -34,7 +35,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
||||||
@Inject lateinit var rxBus: RxBus
|
@Inject lateinit var rxBus: RxBus
|
||||||
@Inject lateinit var rh: ResourceHelper
|
@Inject lateinit var rh: ResourceHelper
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var jsonFormatter: JSONFormatter
|
@Inject lateinit var jsonFormatter: JSONFormatter
|
||||||
|
|
||||||
|
@ -44,8 +45,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
|
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
binding.run.setOnClickListener {
|
binding.run.setOnClickListener {
|
||||||
openAPSSMBPlugin.invoke("OpenAPSSMB button", false)
|
activePlugin.activeAPS.invoke("OpenAPSSMB button", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,11 +92,12 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun updateGUI() {
|
fun updateGUI() {
|
||||||
if (_binding == null) return
|
if (_binding == null) return
|
||||||
|
val openAPSSMBPlugin = activePlugin.activeAPS
|
||||||
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
|
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
|
||||||
binding.result.text = jsonFormatter.format(lastAPSResult.json)
|
binding.result.text = jsonFormatter.format(lastAPSResult.json)
|
||||||
binding.request.text = lastAPSResult.toSpanned()
|
binding.request.text = lastAPSResult.toSpanned()
|
||||||
}
|
}
|
||||||
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
|
openAPSSMBPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterSMBJS ->
|
||||||
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
|
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
|
||||||
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
|
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -10,8 +10,6 @@ import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.extensions.target
|
import info.nightscout.androidaps.extensions.target
|
||||||
import info.nightscout.androidaps.interfaces.*
|
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.EventOpenAPSUpdateGui
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
|
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.Profiler
|
||||||
import info.nightscout.androidaps.utils.Round
|
import info.nightscout.androidaps.utils.Round
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
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 info.nightscout.shared.sharedPreferences.SP
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -37,7 +37,7 @@ class OpenAPSSMBPlugin @Inject constructor(
|
||||||
private val constraintChecker: ConstraintChecker,
|
private val constraintChecker: ConstraintChecker,
|
||||||
rh: ResourceHelper,
|
rh: ResourceHelper,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val context: Context,
|
val context: Context,
|
||||||
private val activePlugin: ActivePlugin,
|
private val activePlugin: ActivePlugin,
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
private val iobCobCalculator: IobCobCalculator,
|
||||||
private val hardLimits: HardLimits,
|
private val hardLimits: HardLimits,
|
||||||
|
@ -46,23 +46,24 @@ class OpenAPSSMBPlugin @Inject constructor(
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val repository: AppRepository,
|
private val repository: AppRepository,
|
||||||
private val glucoseStatusProvider: GlucoseStatusProvider
|
private val glucoseStatusProvider: GlucoseStatusProvider
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(
|
||||||
.mainType(PluginType.APS)
|
PluginDescription()
|
||||||
.fragmentClass(OpenAPSSMBFragment::class.java.name)
|
.mainType(PluginType.APS)
|
||||||
.pluginIcon(R.drawable.ic_generic_icon)
|
.fragmentClass(OpenAPSSMBFragment::class.java.name)
|
||||||
.pluginName(R.string.openapssmb)
|
.pluginIcon(R.drawable.ic_generic_icon)
|
||||||
.shortName(R.string.smb_shortname)
|
.pluginName(R.string.openapssmb)
|
||||||
.preferencesId(R.xml.pref_openapssmb)
|
.shortName(R.string.smb_shortname)
|
||||||
.description(R.string.description_smb)
|
.preferencesId(R.xml.pref_openapssmb)
|
||||||
.setDefault(),
|
.description(R.string.description_smb)
|
||||||
|
.setDefault(),
|
||||||
aapsLogger, rh, injector
|
aapsLogger, rh, injector
|
||||||
), APS, Constraints {
|
), APS, Constraints {
|
||||||
|
|
||||||
// last values
|
// last values
|
||||||
override var lastAPSRun: Long = 0
|
override var lastAPSRun: Long = 0
|
||||||
override var lastAPSResult: DetermineBasalResultSMB? = null
|
override var lastAPSResult: DetermineBasalResultSMB? = null
|
||||||
var lastDetermineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS? = null
|
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
|
||||||
var lastAutosensResult = AutosensResult()
|
override var lastAutosensResult = AutosensResult()
|
||||||
|
|
||||||
override fun specialEnableCondition(): Boolean {
|
override fun specialEnableCondition(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
|
@ -120,15 +121,34 @@ class OpenAPSSMBPlugin @Inject constructor(
|
||||||
}.value()
|
}.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 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 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
|
var isTempTarget = false
|
||||||
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
||||||
if (tempTarget is ValueWrapper.Existing) {
|
if (tempTarget is ValueWrapper.Existing) {
|
||||||
isTempTarget = true
|
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())
|
minBg =
|
||||||
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())
|
hardLimits.verifyHardLimits(
|
||||||
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())
|
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.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
|
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)
|
profiler.log(LTag.APS, "SMB data gathering", start)
|
||||||
start = System.currentTimeMillis()
|
start = System.currentTimeMillis()
|
||||||
|
|
||||||
DetermineBasalAdapterSMBJS(ScriptReader(context), injector).also { determineBasalAdapterSMBJS ->
|
provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS ->
|
||||||
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg,
|
determineBasalAdapterSMBJS.setData(
|
||||||
|
profile, maxIob, maxBasal, minBg, maxBg, targetBg,
|
||||||
activePlugin.activePump.baseBasalRate,
|
activePlugin.activePump.baseBasalRate,
|
||||||
iobArray,
|
iobArray,
|
||||||
glucoseStatus,
|
glucoseStatus,
|
||||||
|
@ -176,24 +197,26 @@ class OpenAPSSMBPlugin @Inject constructor(
|
||||||
smbAllowed.value(),
|
smbAllowed.value(),
|
||||||
uam.value(),
|
uam.value(),
|
||||||
advancedFiltering.value(),
|
advancedFiltering.value(),
|
||||||
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin")
|
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin"
|
||||||
|
)
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
|
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
|
||||||
profiler.log(LTag.APS, "SMB calculation", start)
|
profiler.log(LTag.APS, "SMB calculation", start)
|
||||||
if (determineBasalResultSMB == null) {
|
if (determineBasalResultSMB == null) {
|
||||||
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
||||||
lastDetermineBasalAdapterSMBJS = null
|
lastDetermineBasalAdapter = null
|
||||||
lastAPSResult = null
|
lastAPSResult = null
|
||||||
lastAPSRun = 0
|
lastAPSRun = 0
|
||||||
} else {
|
} else {
|
||||||
// TODO still needed with oref1?
|
// TODO still needed with oref1?
|
||||||
// Fix bug determine basal
|
// 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.iob = iobArray[0]
|
||||||
determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
|
determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
|
||||||
determineBasalResultSMB.inputConstraints = inputConstraints
|
determineBasalResultSMB.inputConstraints = inputConstraints
|
||||||
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS
|
lastDetermineBasalAdapter = determineBasalAdapterSMBJS
|
||||||
lastAPSResult = determineBasalResultSMB
|
lastAPSResult = determineBasalResultSMB as DetermineBasalResultSMB
|
||||||
lastAPSRun = now
|
lastAPSRun = now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,4 +227,6 @@ class OpenAPSSMBPlugin @Inject constructor(
|
||||||
value.set(aapsLogger, false)
|
value.set(aapsLogger, false)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBJS(ScriptReader(context), injector)
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -48,6 +48,7 @@ import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
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.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
|
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
|
||||||
|
@ -603,7 +604,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
binding.infoLayout.apsMode.stateDescription = rh.gs(stringRes)
|
binding.infoLayout.apsMode.stateDescription = rh.gs(stringRes)
|
||||||
} else {
|
} else {
|
||||||
binding.infoLayout.apsMode.contentDescription = rh.gs(R.string.apsmode_title) + " " + rh.gs(stringRes)
|
binding.infoLayout.apsMode.contentDescription = rh.gs(R.string.apsmode_title) + " " + rh.gs(stringRes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,6 +672,21 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
binding.infoLayout.apsModeText.visibility = View.GONE
|
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 {
|
} else {
|
||||||
//nsclient
|
//nsclient
|
||||||
binding.infoLayout.apsMode.visibility = View.GONE
|
binding.infoLayout.apsMode.visibility = View.GONE
|
||||||
|
@ -774,7 +790,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
|
|
||||||
val outDate = (if (!overviewData.isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
|
val outDate = (if (!overviewData.isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
|
||||||
binding.infoLayout.bg.contentDescription =
|
binding.infoLayout.bg.contentDescription =
|
||||||
rh.gs(R.string.a11y_blood_glucose) + " " + binding.infoLayout.bg.text.toString() + " " + overviewData.lastBgDescription + " " + outDate
|
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.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
|
||||||
binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, overviewData.lastBg?.timestamp)
|
binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, overviewData.lastBg?.timestamp)
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.activities
|
package info.nightscout.androidaps.plugins.general.overview.activities
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper.*
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -20,6 +26,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -30,20 +38,95 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var quickWizard: QuickWizard
|
@Inject lateinit var quickWizard: QuickWizard
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
private lateinit var binding: OverviewQuickwizardlistActivityBinding
|
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>() {
|
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>() {
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
|
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) {
|
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
|
||||||
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
|
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
|
||||||
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate())
|
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.buttonText.text = quickWizard[position].buttonText()
|
||||||
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs())
|
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 buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
|
||||||
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
|
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
|
||||||
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
|
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)
|
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 editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
|
||||||
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -84,6 +179,7 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(this)
|
binding.recyclerview.layoutManager = LinearLayoutManager(this)
|
||||||
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
|
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
|
||||||
|
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
|
||||||
|
|
||||||
binding.addButton.setOnClickListener {
|
binding.addButton.setOnClickListener {
|
||||||
val manager = supportFragmentManager
|
val manager = supportFragmentManager
|
||||||
|
@ -98,13 +194,13 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
|
||||||
.toObservable(EventQuickWizardChange::class.java)
|
.toObservable(EventQuickWizardChange::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
val adapter = RecyclerViewAdapter(supportFragmentManager)
|
val adapter = RecyclerViewAdapter(supportFragmentManager)
|
||||||
binding.recyclerview.swapAdapter(adapter, false)
|
binding.recyclerview.swapAdapter(adapter, false)
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import dagger.android.support.DaggerDialogFragment
|
import dagger.android.support.DaggerDialogFragment
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding
|
import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
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.extensions.setSelection
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -30,9 +32,9 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
@Inject lateinit var quickWizard: QuickWizard
|
@Inject lateinit var quickWizard: QuickWizard
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
|
||||||
var position = -1
|
var position = -1
|
||||||
|
|
||||||
var fromSeconds: Int = 0
|
var fromSeconds: Int = 0
|
||||||
var toSeconds: Int = 0
|
var toSeconds: Int = 0
|
||||||
|
|
||||||
|
@ -42,8 +44,10 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(
|
||||||
savedInstanceState: Bundle?): View {
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||||
isCancelable = true
|
isCancelable = true
|
||||||
|
@ -57,6 +61,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
position = bundle.getInt("position", -1)
|
position = bundle.getInt("position", -1)
|
||||||
}
|
}
|
||||||
val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position]
|
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 {
|
binding.okcancel.ok.setOnClickListener {
|
||||||
try {
|
try {
|
||||||
entry.storage.put("buttonText", binding.buttonEdit.text.toString())
|
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("useBG", binding.useBg.selectedItemPosition)
|
||||||
entry.storage.put("useCOB", binding.useCob.selectedItemPosition)
|
entry.storage.put("useCOB", binding.useCob.selectedItemPosition)
|
||||||
entry.storage.put("useBolusIOB", binding.useBolusIob.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("useBasalIOB", binding.useBasalIob.selectedItemPosition)
|
||||||
entry.storage.put("useTrend", binding.useTrend.selectedItemPosition)
|
entry.storage.put("useTrend", binding.useTrend.selectedItemPosition)
|
||||||
entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition)
|
entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition)
|
||||||
entry.storage.put("useTempTarget", binding.useTempTarget.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) {
|
} catch (e: JSONException) {
|
||||||
aapsLogger.error("Unhandled exception", e)
|
aapsLogger.error("Unhandled exception", e)
|
||||||
}
|
}
|
||||||
|
@ -88,7 +104,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
|
|
||||||
binding.from.setOnClickListener {
|
binding.from.setOnClickListener {
|
||||||
context?.let {
|
context?.let {
|
||||||
TimePickerDialog(it, fromTimeSetListener,
|
TimePickerDialog(
|
||||||
|
it, fromTimeSetListener,
|
||||||
T.secs(fromSeconds.toLong()).hours().toInt(),
|
T.secs(fromSeconds.toLong()).hours().toInt(),
|
||||||
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
|
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
|
||||||
DateFormat.is24HourFormat(context)
|
DateFormat.is24HourFormat(context)
|
||||||
|
@ -105,13 +122,29 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
|
|
||||||
binding.to.setOnClickListener {
|
binding.to.setOnClickListener {
|
||||||
context?.let {
|
context?.let {
|
||||||
TimePickerDialog(it, toTimeSetListener,
|
TimePickerDialog(
|
||||||
|
it, toTimeSetListener,
|
||||||
T.secs(toSeconds.toLong()).hours().toInt(),
|
T.secs(toSeconds.toLong()).hours().toInt(),
|
||||||
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
|
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
|
||||||
DateFormat.is24HourFormat(context)
|
DateFormat.is24HourFormat(context)
|
||||||
).show()
|
).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()
|
toSeconds = entry.validTo()
|
||||||
binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
|
binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
|
||||||
|
|
||||||
|
@ -122,10 +155,13 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
binding.useCob.setSelection(entry.useCOB())
|
binding.useCob.setSelection(entry.useCOB())
|
||||||
binding.useBolusIob.setSelection(entry.useBolusIOB())
|
binding.useBolusIob.setSelection(entry.useBolusIOB())
|
||||||
binding.useBasalIob.setSelection(entry.useBasalIOB())
|
binding.useBasalIob.setSelection(entry.useBasalIOB())
|
||||||
|
binding.device.setSelection(entry.device())
|
||||||
binding.useTrend.setSelection(entry.useTrend())
|
binding.useTrend.setSelection(entry.useTrend())
|
||||||
binding.useSuperBolus.setSelection(entry.useSuperBolus())
|
binding.useSuperBolus.setSelection(entry.useSuperBolus())
|
||||||
binding.useTempTarget.setSelection(entry.useTempTarget())
|
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.useCobYes.setOnClickListener(this)
|
||||||
binding.useCobNo.setOnClickListener(this)
|
binding.useCobNo.setOnClickListener(this)
|
||||||
processCob()
|
processCob()
|
||||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.wear
|
||||||
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
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.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.DecimalFormat
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -71,6 +72,7 @@ class ActionStringHandler @Inject constructor(
|
||||||
private val activePlugin: ActivePlugin,
|
private val activePlugin: ActivePlugin,
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
private val iobCobCalculator: IobCobCalculator,
|
||||||
private val localInsightPlugin: LocalInsightPlugin,
|
private val localInsightPlugin: LocalInsightPlugin,
|
||||||
|
private val quickWizard: QuickWizard,
|
||||||
private val danaRPlugin: DanaRPlugin,
|
private val danaRPlugin: DanaRPlugin,
|
||||||
private val danaRKoreanPlugin: DanaRKoreanPlugin,
|
private val danaRKoreanPlugin: DanaRKoreanPlugin,
|
||||||
private val danaRv2Plugin: DanaRv2Plugin,
|
private val danaRv2Plugin: DanaRv2Plugin,
|
||||||
|
@ -79,7 +81,8 @@ class ActionStringHandler @Inject constructor(
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val repository: AppRepository,
|
private val repository: AppRepository,
|
||||||
private val uel: UserEntryLogger
|
private val uel: UserEntryLogger,
|
||||||
|
private val defaultValueHelper: DefaultValueHelper
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val timeout = 65 * 1000
|
private val timeout = 65 * 1000
|
||||||
|
@ -107,9 +110,11 @@ class ActionStringHandler @Inject constructor(
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun handleInitiate(actionString: String) {
|
private fun handleInitiate(actionString: String) {
|
||||||
|
//TODO: i18n
|
||||||
|
Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString)
|
||||||
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
var rTitle = "CONFIRM" //TODO: i18n
|
var rTitle = rh.gs(R.string.confirm).uppercase()
|
||||||
var rMessage = ""
|
var rMessage = ""
|
||||||
var rAction = ""
|
var rAction = ""
|
||||||
// do the parsing and check constraints
|
// do the parsing and check constraints
|
||||||
|
@ -136,6 +141,11 @@ class ActionStringHandler @Inject constructor(
|
||||||
val carbs = SafeParse.stringToInt(act[2])
|
val carbs = SafeParse.stringToInt(act[2])
|
||||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).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.bolus) + ": " + insulinAfterConstraints + "U\n"
|
||||||
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
|
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
|
||||||
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
|
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
|
||||||
|
@ -143,32 +153,72 @@ class ActionStringHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
|
||||||
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
|
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
|
||||||
val isMGDL = java.lang.Boolean.parseBoolean(act[1])
|
aapsLogger.info(LTag.WEAR, "temptarget received: $act")
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
|
if ("cancel" == act[1]) {
|
||||||
sendError("Different units used on watch and phone!")
|
rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
|
||||||
return
|
|
||||||
}
|
|
||||||
val duration = SafeParse.stringToInt(act[2])
|
|
||||||
if (duration == 0) {
|
|
||||||
rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"
|
|
||||||
rAction = "temptarget true 0 0 0"
|
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 {
|
} else {
|
||||||
var low = SafeParse.stringToDouble(act[3])
|
val isMGDL = java.lang.Boolean.parseBoolean(act[1])
|
||||||
var high = SafeParse.stringToDouble(act[4])
|
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
|
||||||
if (!isMGDL) {
|
sendError(rh.gs(R.string.wear_action_tempt_unit_error))
|
||||||
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!")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
|
val duration = SafeParse.stringToInt(act[2])
|
||||||
sendError("Max-BG out of range!")
|
if (duration == 0) {
|
||||||
return
|
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
|
} else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS
|
||||||
rTitle = "STATUS"
|
rTitle = "STATUS"
|
||||||
|
@ -186,10 +236,15 @@ class ActionStringHandler @Inject constructor(
|
||||||
sendError("Update APP on Watch!")
|
sendError("Update APP on Watch!")
|
||||||
return
|
return
|
||||||
} else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD
|
} 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 carbsBeforeConstraints = SafeParse.stringToInt(act[1])
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
|
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
|
||||||
if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
|
if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
|
||||||
sendError("Carb constraint violation!")
|
sendError(rh.gs(R.string.wizard_carbs_constraint))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
|
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
|
||||||
|
@ -202,52 +257,94 @@ class ActionStringHandler @Inject constructor(
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
val profileName = profileFunction.getProfileName()
|
val profileName = profileFunction.getProfileName()
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
sendError("No profile found!")
|
sendError(rh.gs(R.string.wizard_no_active_profile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val bgReading = iobCobCalculator.ads.actualBg()
|
val bgReading = iobCobCalculator.ads.actualBg()
|
||||||
if (bgReading == null) {
|
if (bgReading == null) {
|
||||||
sendError("No recent BG to base calculation on!")
|
sendError(rh.gs(R.string.wizard_no_actual_bg))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
|
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
|
||||||
if (cobInfo.displayCob == null) {
|
if (cobInfo.displayCob == null) {
|
||||||
sendError("Unknown COB! BG reading missing or recent app restart?")
|
sendError(rh.gs(R.string.wizard_no_cob))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val format = DecimalFormat("0.00")
|
|
||||||
val formatInt = DecimalFormat("0")
|
|
||||||
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
||||||
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
|
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
|
||||||
|
|
||||||
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget,
|
val bolusWizard = BolusWizard(injector).doCalc(
|
||||||
carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()),
|
profile, profileName, tempTarget,
|
||||||
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
|
carbsAfterConstraints, cobInfo.displayCob!!, bgReading.valueToUnits(profileFunction.getUnits()),
|
||||||
if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) {
|
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false
|
||||||
sendError("Insulin constraint violation!" +
|
)
|
||||||
"\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!")
|
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
|
return
|
||||||
}
|
}
|
||||||
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
|
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
|
||||||
rAction = "info"
|
rAction = "info"
|
||||||
rTitle = "INFO"
|
rTitle = rh.gs(R.string.info)
|
||||||
} else {
|
} else {
|
||||||
rAction = actionString
|
rAction = actionString
|
||||||
}
|
}
|
||||||
rMessage += "Carbs: " + bolusWizard.carbs + "g"
|
rMessage += rh.gs(R.string.wizard_result, bolusWizard.calculatedTotalInsulin, bolusWizard.carbs)
|
||||||
rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"
|
|
||||||
rMessage += "\n_____________"
|
rMessage += "\n_____________"
|
||||||
rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "
|
rMessage += "\n" + bolusWizard.explainShort()
|
||||||
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"
|
|
||||||
}
|
|
||||||
lastBolusWizard = bolusWizard
|
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]) {
|
} else if ("opencpp" == act[0]) {
|
||||||
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
||||||
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
|
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
|
||||||
|
@ -331,7 +428,10 @@ class ActionStringHandler @Inject constructor(
|
||||||
rAction = "cancelChangeRequest"
|
rAction = "cancelChangeRequest"
|
||||||
wearPlugin.requestNotificationCancel(rAction)
|
wearPlugin.requestNotificationCancel(rAction)
|
||||||
return
|
return
|
||||||
} else return
|
} else {
|
||||||
|
sendError(rh.gs(R.string.wear_unknown_action_string) + act[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
// send result
|
// send result
|
||||||
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
|
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
|
||||||
lastSentTimestamp = System.currentTimeMillis()
|
lastSentTimestamp = System.currentTimeMillis()
|
||||||
|
@ -560,39 +660,45 @@ class ActionStringHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
//send profile to pump
|
//send profile to pump
|
||||||
uel.log(Action.PROFILE_SWITCH, Sources.Wear,
|
uel.log(Action.PROFILE_SWITCH, Sources.Wear,
|
||||||
ValueWithUnit.Percent(percentage),
|
ValueWithUnit.Percent(percentage),
|
||||||
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
|
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
|
||||||
profileFunction.createProfileSwitch(0, percentage, timeshift)
|
profileFunction.createProfileSwitch(0, percentage, timeshift)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
|
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
|
||||||
if (duration != 0) {
|
if (duration != 0) {
|
||||||
disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(
|
disposable += repository.runTransactionForResult(
|
||||||
timestamp = System.currentTimeMillis(),
|
InsertAndCancelCurrentTemporaryTargetTransaction(
|
||||||
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
|
timestamp = System.currentTimeMillis(),
|
||||||
reason = TemporaryTarget.Reason.WEAR,
|
duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
|
||||||
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
|
reason = TemporaryTarget.Reason.WEAR,
|
||||||
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
|
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
|
||||||
)).subscribe({ result ->
|
highTarget = Profile.toMgdl(high, profileFunction.getUnits())
|
||||||
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
|
)
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
).subscribe({ result ->
|
||||||
}, {
|
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
||||||
})
|
}, {
|
||||||
uel.log(Action.TT, Sources.Wear,
|
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
||||||
|
})
|
||||||
|
uel.log(
|
||||||
|
Action.TT, Sources.Wear,
|
||||||
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
|
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
|
||||||
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
|
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
|
||||||
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
|
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
|
||||||
ValueWithUnit.Minute(duration))
|
ValueWithUnit.Minute(duration)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
|
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
|
||||||
.subscribe({ result ->
|
.subscribe({ result ->
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
|
||||||
}, {
|
}, {
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
||||||
})
|
})
|
||||||
uel.log(Action.CANCEL_TT, Sources.Wear,
|
uel.log(
|
||||||
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR))
|
Action.CANCEL_TT, Sources.Wear,
|
||||||
|
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,13 +707,15 @@ class ActionStringHandler @Inject constructor(
|
||||||
detailedBolusInfo.insulin = amount
|
detailedBolusInfo.insulin = amount
|
||||||
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
|
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
|
||||||
uel.log(Action.PRIME_BOLUS, Sources.Wear,
|
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() {
|
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
sendError(rh.gs(R.string.treatmentdeliveryerror) +
|
sendError(
|
||||||
"\n" +
|
rh.gs(R.string.treatmentdeliveryerror) +
|
||||||
result.comment)
|
"\n" +
|
||||||
|
result.comment
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -615,9 +723,9 @@ class ActionStringHandler @Inject constructor(
|
||||||
|
|
||||||
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
|
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
|
||||||
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
|
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
|
||||||
ValueWithUnit.Timestamp(time),
|
ValueWithUnit.Timestamp(time),
|
||||||
ValueWithUnit.Gram(carbs),
|
ValueWithUnit.Gram(carbs),
|
||||||
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
|
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
|
||||||
doBolus(0.0, carbs, time, duration)
|
doBolus(0.0, carbs, time, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,15 +744,17 @@ class ActionStringHandler @Inject constructor(
|
||||||
else -> Action.TREATMENT
|
else -> Action.TREATMENT
|
||||||
}
|
}
|
||||||
uel.log(action, Sources.Wear,
|
uel.log(action, Sources.Wear,
|
||||||
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
|
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
|
||||||
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
|
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
|
||||||
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
|
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
|
||||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
sendError(rh.gs(R.string.treatmentdeliveryerror) +
|
sendError(
|
||||||
"\n" +
|
rh.gs(R.string.treatmentdeliveryerror) +
|
||||||
result.comment)
|
"\n" +
|
||||||
|
result.comment
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -665,4 +775,4 @@ class ActionStringHandler @Inject constructor(
|
||||||
lastConfirmActionString = null
|
lastConfirmActionString = null
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import info.nightscout.androidaps.interfaces.Loop;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.Profile;
|
import info.nightscout.androidaps.interfaces.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
||||||
import info.nightscout.shared.logging.AAPSLogger;
|
import info.nightscout.shared.logging.AAPSLogger;
|
||||||
import info.nightscout.shared.logging.LTag;
|
import info.nightscout.shared.logging.LTag;
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
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.DefaultValueHelper;
|
||||||
import info.nightscout.androidaps.utils.TrendCalculator;
|
import info.nightscout.androidaps.utils.TrendCalculator;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
||||||
import info.nightscout.shared.sharedPreferences.SP;
|
import info.nightscout.shared.sharedPreferences.SP;
|
||||||
|
|
||||||
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
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 ReceiverStatusStore receiverStatusStore;
|
||||||
@Inject Config config;
|
@Inject Config config;
|
||||||
@Inject public TrendCalculator trendCalculator;
|
@Inject public TrendCalculator trendCalculator;
|
||||||
|
@Inject public QuickWizard quickWizard;
|
||||||
|
|
||||||
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
|
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
|
||||||
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
|
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 OPEN_SETTINGS_PATH = "/openwearsettings";
|
||||||
private static final String NEW_STATUS_PATH = "/sendstatustowear";
|
private static final String NEW_STATUS_PATH = "/sendstatustowear";
|
||||||
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
|
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 BASAL_DATA_PATH = "/nightscout_watch_basal";
|
||||||
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
|
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_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
|
||||||
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
|
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
|
||||||
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
|
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
|
||||||
|
|
||||||
|
String TAG = "WatchUpdateService";
|
||||||
|
|
||||||
private static boolean lastLoopStatus;
|
private static boolean lastLoopStatus;
|
||||||
|
|
||||||
|
@ -156,7 +161,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
String action = intent != null ? intent.getAction() : null;
|
String action = intent != null ? intent.getAction() : null;
|
||||||
|
|
||||||
// Log.d(TAG, logPrefix + "onStartCommand: " + action);
|
// Log.d(TAG, "onStartCommand: " + action);
|
||||||
|
|
||||||
if (wearIntegration()) {
|
if (wearIntegration()) {
|
||||||
handler.post(() -> {
|
handler.post(() -> {
|
||||||
|
@ -235,7 +240,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
super.onPeerConnected(peer);
|
super.onPeerConnected(peer);
|
||||||
String id = peer.getId();
|
String id = peer.getId();
|
||||||
String name = peer.getDisplayName();
|
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);
|
super.onPeerDisconnected(peer);
|
||||||
String id = peer.getId();
|
String id = peer.getId();
|
||||||
String name = peer.getDisplayName();
|
String name = peer.getDisplayName();
|
||||||
// Log.d(TAG, logPrefix + "onPeerDisconnected peer name & ID: " + name + "|" + id);
|
Log.d(TAG, "onPeerDisconnected peer name & ID: " + name + "|" + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(MessageEvent event) {
|
public void onMessageReceived(MessageEvent event) {
|
||||||
|
|
||||||
// Log.d(TAG, logPrefix + "onMessageRecieved: " + event);
|
// Log.d(TAG, "onMessageRecieved: " + event);
|
||||||
|
|
||||||
if (wearIntegration()) {
|
if (wearIntegration()) {
|
||||||
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
|
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
|
||||||
|
@ -283,7 +288,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
private void sendData() {
|
private void sendData() {
|
||||||
|
|
||||||
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
|
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
|
||||||
// Log.d(TAG, logPrefix + "LastBg=" + lastBG);
|
// Log.d(TAG, "LastBg=" + lastBG);
|
||||||
if (lastBG != null) {
|
if (lastBG != null) {
|
||||||
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
|
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
|
||||||
|
|
||||||
|
@ -364,6 +369,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
|
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
|
||||||
googleApiConnect();
|
googleApiConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendPreferences();
|
||||||
|
sendQuickWizard();
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
|
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
|
||||||
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
|
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
|
||||||
|
|
||||||
|
@ -382,7 +391,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
entries.putDataMapArrayList("entries", dataMaps);
|
entries.putDataMapArrayList("entries", dataMaps);
|
||||||
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
|
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
|
||||||
}
|
}
|
||||||
sendPreferences();
|
|
||||||
sendBasals();
|
sendBasals();
|
||||||
sendStatus();
|
sendStatus();
|
||||||
}
|
}
|
||||||
|
@ -720,19 +728,62 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
private void sendPreferences() {
|
private void sendPreferences() {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
|
|
||||||
|
GlucoseUnit units = profileFunction.getUnits();
|
||||||
boolean wearcontrol = sp.getBoolean(R.string.key_wear_control, false);
|
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);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
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_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();
|
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
||||||
} else {
|
} 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
|
@NonNull
|
||||||
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {
|
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
processVisibilityOnClick(it)
|
processVisibilityOnClick(it)
|
||||||
binding.target.visibility = View.VISIBLE
|
binding.target.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build() {
|
fun build() {
|
||||||
|
|
|
@ -58,13 +58,13 @@ class TddCalculator @Inject constructor(
|
||||||
val tbr = tempBasals[t]
|
val tbr = tempBasals[t]
|
||||||
val profile = profileFunction.getProfile(t) ?: continue
|
val profile = profileFunction.getProfile(t) ?: continue
|
||||||
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
|
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) {
|
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
||||||
// they are not included in TBRs
|
// they are not included in TBRs
|
||||||
val eb = iobCobCalculator.getExtendedBolus(t)
|
val eb = iobCobCalculator.getExtendedBolus(t)
|
||||||
val absoluteEbRate = eb?.rate ?: 0.0
|
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)
|
result.put(midnight, tdd)
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,54 @@ class TddCalculator @Inject constructor(
|
||||||
return result
|
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())
|
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
|
||||||
for (i in 0 until tdds.size()) {
|
for (i in 0 until tdds.size()) {
|
||||||
val tdd = tdds.valueAt(i)
|
val tdd = tdds.valueAt(i)
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class TimeListEdit {
|
||||||
float factor = layout.getContext().getResources().getDisplayMetrics().density;
|
float factor = layout.getContext().getResources().getDisplayMetrics().density;
|
||||||
finalAdd = new ImageView(context);
|
finalAdd = new ImageView(context);
|
||||||
finalAdd.setImageResource(R.drawable.ic_add);
|
finalAdd.setImageResource(R.drawable.ic_add);
|
||||||
finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.addnew));
|
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));
|
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.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
|
||||||
illp.gravity = Gravity.CENTER;
|
illp.gravity = Gravity.CENTER;
|
||||||
|
|
|
@ -18,6 +18,8 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
|
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
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.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
|
@ -135,27 +137,28 @@ class BolusWizard @Inject constructor(
|
||||||
private var quickWizard: Boolean = true
|
private var quickWizard: Boolean = true
|
||||||
var usePercentage: Boolean = false
|
var usePercentage: Boolean = false
|
||||||
|
|
||||||
fun doCalc(profile: Profile,
|
fun doCalc(
|
||||||
profileName: String,
|
profile: Profile,
|
||||||
tempTarget: TemporaryTarget?,
|
profileName: String,
|
||||||
carbs: Int,
|
tempTarget: TemporaryTarget?,
|
||||||
cob: Double,
|
carbs: Int,
|
||||||
bg: Double,
|
cob: Double,
|
||||||
correction: Double,
|
bg: Double,
|
||||||
percentageCorrection: Int = 100,
|
correction: Double,
|
||||||
useBg: Boolean,
|
percentageCorrection: Int = 100,
|
||||||
useCob: Boolean,
|
useBg: Boolean,
|
||||||
includeBolusIOB: Boolean,
|
useCob: Boolean,
|
||||||
includeBasalIOB: Boolean,
|
includeBolusIOB: Boolean,
|
||||||
useSuperBolus: Boolean,
|
includeBasalIOB: Boolean,
|
||||||
useTT: Boolean,
|
useSuperBolus: Boolean,
|
||||||
useTrend: Boolean,
|
useTT: Boolean,
|
||||||
useAlarm: Boolean,
|
useTrend: Boolean,
|
||||||
notes: String = "",
|
useAlarm: Boolean,
|
||||||
carbTime: Int = 0,
|
notes: String = "",
|
||||||
usePercentage: Boolean = false,
|
carbTime: Int = 0,
|
||||||
totalPercentage: Double = 100.0,
|
usePercentage: Boolean = false,
|
||||||
quickWizard: Boolean = false
|
totalPercentage: Double = 100.0,
|
||||||
|
quickWizard: Boolean = false
|
||||||
): BolusWizard {
|
): BolusWizard {
|
||||||
|
|
||||||
this.profile = profile
|
this.profile = profile
|
||||||
|
@ -314,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)
|
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs).formatColor(rh, R.color.carbs) + timeShift)
|
||||||
}
|
}
|
||||||
if (insulinFromCOB > 0) {
|
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)
|
val absorptionRate = iobCobCalculator.ads.slowAbsorptionPercentage(60)
|
||||||
if (absorptionRate > .25)
|
if (absorptionRate > .25)
|
||||||
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt()))
|
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt()))
|
||||||
|
@ -344,8 +349,8 @@ class BolusWizard @Inject constructor(
|
||||||
carbTimer.removeEatReminder()
|
carbTimer.removeEatReminder()
|
||||||
if (sp.getBoolean(R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0)
|
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),
|
OKDialog.showYesNoCancel(ctx, rh.gs(R.string.bolusadvisor), rh.gs(R.string.bolusadvisormessage),
|
||||||
{ bolusAdvisorProcessing(ctx) },
|
{ bolusAdvisorProcessing(ctx) },
|
||||||
{ commonProcessing(ctx) }
|
{ commonProcessing(ctx) }
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
commonProcessing(ctx)
|
commonProcessing(ctx)
|
||||||
|
@ -367,10 +372,13 @@ class BolusWizard @Inject constructor(
|
||||||
carbTime = 0
|
carbTime = 0
|
||||||
bolusCalculatorResult = createBolusCalculatorResult()
|
bolusCalculatorResult = createBolusCalculatorResult()
|
||||||
notes = this@BolusWizard.notes
|
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,
|
notes,
|
||||||
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
|
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
|
||||||
ValueWithUnit.Insulin(insulinAfterConstraints))
|
ValueWithUnit.Insulin(insulinAfterConstraints)
|
||||||
|
)
|
||||||
if (insulin > 0) {
|
if (insulin > 0) {
|
||||||
commandQueue.bolus(this, object : Callback() {
|
commandQueue.bolus(this, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -385,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) {
|
private fun commonProcessing(ctx: Context) {
|
||||||
val profile = profileFunction.getProfile() ?: return
|
val profile = profileFunction.getProfile() ?: return
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
|
@ -433,17 +461,17 @@ class BolusWizard @Inject constructor(
|
||||||
bolusCalculatorResult = createBolusCalculatorResult()
|
bolusCalculatorResult = createBolusCalculatorResult()
|
||||||
notes = this@BolusWizard.notes
|
notes = this@BolusWizard.notes
|
||||||
if (insulin > 0 || carbs > 0) {
|
if (insulin > 0 || carbs > 0) {
|
||||||
val action = when {
|
val action = when {
|
||||||
insulinAfterConstraints.equals(0.0) -> Action.CARBS
|
insulinAfterConstraints.equals(0.0) -> Action.CARBS
|
||||||
carbs.equals(0.0) -> Action.BOLUS
|
carbs.equals(0.0) -> Action.BOLUS
|
||||||
else -> Action.TREATMENT
|
else -> Action.TREATMENT
|
||||||
}
|
}
|
||||||
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
|
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
|
||||||
notes,
|
notes,
|
||||||
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
|
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
|
||||||
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
|
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
|
||||||
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
|
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
|
||||||
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
|
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
|
||||||
commandQueue.bolus(this, object : Callback() {
|
commandQueue.bolus(this, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -469,9 +497,9 @@ class BolusWizard @Inject constructor(
|
||||||
private fun calcPercentageWithConstraints() {
|
private fun calcPercentageWithConstraints() {
|
||||||
calculatedPercentage = 100.0
|
calculatedPercentage = 100.0
|
||||||
if (totalBeforePercentageAdjustment != insulinFromCorrection)
|
if (totalBeforePercentageAdjustment != insulinFromCorrection)
|
||||||
calculatedPercentage = calculatedTotalInsulin/(totalBeforePercentageAdjustment-insulinFromCorrection) * 100
|
calculatedPercentage = calculatedTotalInsulin / (totalBeforePercentageAdjustment - insulinFromCorrection) * 100
|
||||||
calculatedPercentage = max(calculatedPercentage, 10.0)
|
calculatedPercentage = max(calculatedPercentage, 10.0)
|
||||||
calculatedPercentage = min(calculatedPercentage,250.0)
|
calculatedPercentage = min(calculatedPercentage, 250.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calcCorrectionWithConstraints() {
|
private fun calcCorrectionWithConstraints() {
|
||||||
|
@ -481,4 +509,4 @@ class BolusWizard @Inject constructor(
|
||||||
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
|
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package info.nightscout.androidaps.utils.wizard
|
package info.nightscout.androidaps.utils.wizard
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -18,6 +20,18 @@ class QuickWizard @Inject constructor(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setData(JSONArray(sp.getString(R.string.key_quickwizard, "[]")))
|
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? {
|
fun getActive(): QuickWizardEntry? {
|
||||||
|
@ -41,6 +55,38 @@ class QuickWizard @Inject constructor(
|
||||||
operator fun get(position: Int): QuickWizardEntry =
|
operator fun get(position: Int): QuickWizardEntry =
|
||||||
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
|
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 {
|
fun newEmptyItem(): QuickWizardEntry {
|
||||||
return QuickWizardEntry(injector)
|
return QuickWizardEntry(injector)
|
||||||
}
|
}
|
||||||
|
@ -57,4 +103,5 @@ class QuickWizard @Inject constructor(
|
||||||
storage.remove(position)
|
storage.remove(position)
|
||||||
save()
|
save()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
|
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
|
||||||
|
@ -41,11 +42,26 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
|
||||||
const val NO = 1
|
const val NO = 1
|
||||||
private const val POSITIVE_ONLY = 2
|
private const val POSITIVE_ONLY = 2
|
||||||
private const val NEGATIVE_ONLY = 3
|
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 {
|
init {
|
||||||
injector.androidInjector().inject(this)
|
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 {
|
try {
|
||||||
storage = JSONObject(emptyData)
|
storage = JSONObject(emptyData)
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
|
@ -55,6 +71,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
|
guid: string,
|
||||||
|
device: string, // (phone, watch, all)
|
||||||
buttonText: "Meal",
|
buttonText: "Meal",
|
||||||
carbs: 36,
|
carbs: 36,
|
||||||
validFrom: 8 * 60 * 60, // seconds from midnight
|
validFrom: 8 * 60 * 60, // seconds from midnight
|
||||||
|
@ -66,15 +84,18 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
|
||||||
useTrend: 0,
|
useTrend: 0,
|
||||||
useSuperBolus: 0,
|
useSuperBolus: 0,
|
||||||
useTemptarget: 0
|
useTemptarget: 0
|
||||||
|
usePercentage: string, // default, custom
|
||||||
|
percentage: int,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
fun from(entry: JSONObject, position: Int): QuickWizardEntry {
|
fun from(entry: JSONObject, position: Int): QuickWizardEntry {
|
||||||
|
// TODO set guid if missing for migration
|
||||||
storage = entry
|
storage = entry
|
||||||
this.position = position
|
this.position = position
|
||||||
return this
|
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 {
|
fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
|
||||||
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
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) {
|
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
|
||||||
trend = true
|
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
|
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 buttonText(): String = safeGetString(storage, "buttonText", "")
|
||||||
|
|
||||||
fun carbs(): Int = safeGetInt(storage, "carbs")
|
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 useSuperBolus(): Int = safeGetInt(storage, "useSuperBolus", NO)
|
||||||
|
|
||||||
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
|
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
|
||||||
}
|
|
||||||
|
fun usePercentage(): Int = safeGetInt(storage, "usePercentage", DEFAULT)
|
||||||
|
|
||||||
|
fun percentage(): Int = safeGetInt(storage, "percentage", 100)
|
||||||
|
}
|
||||||
|
|
|
@ -83,14 +83,14 @@
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:labelFor="@+id/age"
|
|
||||||
android:text="@string/age"
|
android:text="@string/age"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/age"
|
android:id="@+id/age"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/age" />
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
@ -105,14 +105,14 @@
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:labelFor="@+id/weight"
|
|
||||||
android:text="@string/tdd_total"
|
android:text="@string/tdd_total"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/tdd"
|
android:id="@+id/tdd"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/tdd_total" />
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
@ -123,18 +123,18 @@
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/weigth_label"
|
android:id="@+id/weight_label"
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:labelFor="@+id/weight"
|
|
||||||
android:text="@string/weight_label"
|
android:text="@string/weight_label"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/weight"
|
android:id="@+id/weight"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/weight_label" />
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
@ -149,14 +149,14 @@
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:labelFor="@+id/basalpctfromtdd"
|
|
||||||
android:text="@string/basalpctfromtdd_label"
|
android:text="@string/basalpctfromtdd_label"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/basalpctfromtdd"
|
android:id="@+id/basalpctfromtdd"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/basalpctfromtdd_label" />
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
android:paddingTop="10dp">
|
android:paddingTop="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/bg_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -70,7 +71,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/bg"
|
android:id="@+id/bg"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/treatments_wizard_bg_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/units"
|
android:id="@+id/units"
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/time_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -105,25 +106,24 @@
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
android:textStyle="bold" />
|
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
|
<CheckBox
|
||||||
android:id="@+id/alarmCheckBox"
|
android:id="@+id/alarmCheckBox"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:checked="false"
|
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>
|
</LinearLayout>
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/time"
|
android:id="@+id/time"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/time_offset" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -143,6 +143,7 @@
|
||||||
android:layout_gravity="center_vertical">
|
android:layout_gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
@ -156,7 +157,8 @@
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_horizontal" />
|
android:layout_gravity="center_horizontal"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -176,6 +178,7 @@
|
||||||
android:layout_gravity="center_vertical">
|
android:layout_gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/carbs_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
@ -190,7 +193,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/carbs"
|
android:id="@+id/carbs"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/treatments_wizard_carbs_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/bg_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -98,7 +99,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/bg"
|
android:id="@+id/bg"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/treatments_wizard_bg_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/bg_units"
|
android:id="@+id/bg_units"
|
||||||
|
@ -121,6 +123,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -133,7 +136,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/insulin_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -65,7 +66,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/insulin"
|
android:id="@+id/insulin"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/overview_insulin_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -86,6 +88,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -98,7 +101,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/fill_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
@ -89,7 +90,8 @@
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:paddingLeft="5dp"
|
android:paddingLeft="5dp"
|
||||||
android:paddingRight="5dp" />
|
android:paddingRight="5dp"
|
||||||
|
app:customContentDescription="@string/overview_insulin_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/time_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -88,7 +89,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/time"
|
android:id="@+id/time"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/time_offset"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -109,6 +111,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/insulin_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -121,7 +124,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/amount"
|
android:id="@+id/amount"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/overview_insulin_label"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -147,6 +151,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:contentDescription="Increment insuline with 0.5"
|
||||||
android:text="+0.5" />
|
android:text="+0.5" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:width="120dp"
|
android:width="120dp"
|
||||||
|
android:labelFor="@+id/profile"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:text="@string/profile_label"
|
android:text="@string/profile_label"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
@ -95,6 +96,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -108,7 +110,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -129,6 +132,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/percentage_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -142,7 +146,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/percentage"
|
android:id="@+id/percentage"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_percentage_label"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -163,6 +168,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/timeshift_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -176,7 +182,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/timeshift"
|
android:id="@+id/timeshift"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_timeshift_label"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/basal_percent_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -66,7 +67,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/basal_percent_input"
|
android:id="@+id/basal_percent_input"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/basal_rate" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/basal_absolute_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -100,7 +103,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/basal_absolute_input"
|
android:id="@+id/basal_absolute_input"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/basal_rate" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -121,6 +125,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -133,7 +138,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/temptarget_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
@ -67,7 +68,8 @@
|
||||||
android:id="@+id/temptarget"
|
android:id="@+id/temptarget"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_vertical" />
|
android:layout_gravity="center_vertical"
|
||||||
|
app:customContentDescription="@string/target_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/units"
|
android:id="@+id/units"
|
||||||
|
@ -89,6 +91,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/duration_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -101,7 +104,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
android:id="@+id/duration"
|
android:id="@+id/duration"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -127,6 +131,7 @@
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:width="120dp"
|
android:width="120dp"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
|
android:labelFor="@+id/reason"
|
||||||
android:text="@string/reason"
|
android:text="@string/reason"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/insulin_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -75,7 +76,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/insulin"
|
android:id="@+id/insulin"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/overview_insulin_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -96,6 +98,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/carbs_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
@ -108,7 +111,8 @@
|
||||||
<info.nightscout.androidaps.utils.ui.NumberPicker
|
<info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
android:id="@+id/carbs"
|
android:id="@+id/carbs"
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp"
|
||||||
|
app:customContentDescription="@string/treatments_wizard_carbs_label" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -240,6 +240,69 @@
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
</LinearLayout>
|
</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
|
<LinearLayout
|
||||||
android:id="@+id/done_background"
|
android:id="@+id/done_background"
|
||||||
|
@ -260,39 +323,7 @@
|
||||||
android:contentDescription="@string/show_calculation"
|
android:contentDescription="@string/show_calculation"
|
||||||
android:drawableEnd="@drawable/ic_visibility" />
|
android:drawableEnd="@drawable/ic_visibility" />
|
||||||
|
|
||||||
<CheckBox
|
<include
|
||||||
android:id="@+id/bg_checkbox_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
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="fill_parent"
|
|
||||||
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="fill_parent"
|
|
||||||
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="fill_parent"
|
|
||||||
android:button="@drawable/checkbox_cob_icon"
|
|
||||||
android:checked="true"
|
|
||||||
android:contentDescription="@string/treatments_wizard_cob_label" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/okcancel"
|
android:id="@+id/okcancel"
|
||||||
layout="@layout/okcancel" />
|
layout="@layout/okcancel" />
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
|
android:labelFor="@+id/spinner"
|
||||||
android:text="@string/selected_profile"
|
android:text="@string/selected_profile"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:contentDescription="@string/addnew"
|
android:contentDescription="@string/a11y_add_new_profile"
|
||||||
app:srcCompat="@drawable/ic_add" />
|
app:srcCompat="@drawable/ic_add" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -106,7 +107,7 @@
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:contentDescription="@string/clone_label"
|
android:contentDescription="@string/a11y_clone_profile"
|
||||||
app:srcCompat="@drawable/ic_clone" />
|
app:srcCompat="@drawable/ic_clone" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -115,7 +116,7 @@
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:contentDescription="@string/remove_label"
|
android:contentDescription="@string/a11y_delete_current_profile"
|
||||||
android:scaleX="1"
|
android:scaleX="1"
|
||||||
android:scaleY="1"
|
android:scaleY="1"
|
||||||
app:srcCompat="@drawable/ic_remove" />
|
app:srcCompat="@drawable/ic_remove" />
|
||||||
|
@ -190,7 +191,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:text="@string/dia_label"
|
android:text="@string/dia_long_label"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
@ -202,6 +203,7 @@
|
||||||
android:paddingTop="5dp">
|
android:paddingTop="5dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/dia_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
@ -214,7 +216,8 @@
|
||||||
android:layout_width="130dp"
|
android:layout_width="130dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginBottom="10dp" />
|
android:layout_marginBottom="10dp"
|
||||||
|
app:customContentDescription="@string/dia" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -108,6 +108,35 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</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
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -276,7 +305,6 @@
|
||||||
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -301,6 +329,47 @@
|
||||||
|
|
||||||
</RadioGroup>
|
</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
|
<include
|
||||||
android:id="@+id/okcancel"
|
android:id="@+id/okcancel"
|
||||||
|
|
|
@ -407,6 +407,19 @@
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:ignore="HardcodedText" />
|
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>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -16,9 +16,9 @@
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -29,37 +29,64 @@
|
||||||
card_view:srcCompat="@drawable/ic_quick_wizard" />
|
card_view:srcCompat="@drawable/ic_quick_wizard" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:baselineAligned="true"
|
android:baselineAligned="true"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/overview_quickwizard_item_buttonText"
|
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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="10dp"
|
android:adjustViewBounds="false"
|
||||||
android:text="Sample button text"
|
android:cropToPadding="false"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
android:paddingRight="10dp"
|
||||||
android:textStyle="normal|bold"
|
android:scaleType="fitStart"
|
||||||
android:textColor="@color/cardObjectiveText" />
|
card_view:srcCompat="@drawable/ic_smartphone" />
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:id="@+id/overview_quickwizard_item_carbs"
|
android:id="@+id/handleView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="10dp"
|
android:layout_alignParentEnd="true"
|
||||||
android:text="36g"
|
android:layout_centerVertical="true"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
android:adjustViewBounds="false"
|
||||||
android:textColor="@color/cardObjectiveText"
|
android:cropToPadding="false"
|
||||||
android:textStyle="normal|bold" />
|
android:scaleType="fitStart"
|
||||||
|
card_view:srcCompat="@drawable/ic_reorder_gray_24dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -88,9 +115,9 @@
|
||||||
android:textStyle="normal|bold" />
|
android:textStyle="normal|bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="-"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
android:text="-" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/overview_quickwizard_item_to"
|
android:id="@+id/overview_quickwizard_item_to"
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
<string name="description_ns_client">Synchronizes your data with Nightscout</string>
|
<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_ama">State of the algorithm in 2017</string>
|
||||||
<string name="description_smb">Most recent algorithm for advanced users</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_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_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>
|
<string name="description_profile_local">Define a profile which is available offline.</string>
|
||||||
|
@ -313,7 +314,7 @@
|
||||||
<string name="wear">Wear</string>
|
<string name="wear">Wear</string>
|
||||||
<string name="resend_all_data">Resend All Data</string>
|
<string name="resend_all_data">Resend All Data</string>
|
||||||
<string name="open_settings_on_wear">Open Settings on Wear</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="basalvaluebelowminimum">Basal value below minimum. Profile not set!</string>
|
||||||
<string name="sms_actualbg">BG:</string>
|
<string name="sms_actualbg">BG:</string>
|
||||||
<string name="sms_lastbg">Last BG:</string>
|
<string name="sms_lastbg">Last BG:</string>
|
||||||
|
@ -535,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">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="ns_localbroadcasts_title">Enable local Broadcasts.</string>
|
||||||
<string name="openapssmb">OpenAPS SMB</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_smb" translatable="false">use_smb</string>
|
||||||
<string name="key_use_uam" translatable="false">use_uam</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>
|
<string name="key_smb_enable_carbs_suggestions_threshold" translatable="false">smb_enable_carbs_suggestions_threshold</string>
|
||||||
|
@ -617,6 +619,7 @@
|
||||||
<string name="negativeonly">Negative only</string>
|
<string name="negativeonly">Negative only</string>
|
||||||
<string name="overview_editquickwizard_usecob">COB calculation</string>
|
<string name="overview_editquickwizard_usecob">COB calculation</string>
|
||||||
<string name="overview_editquickwizard_usetemptarget">Temporary target 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="loopenabled">Loop enabled</string>
|
||||||
<string name="apsselected">APS selected</string>
|
<string name="apsselected">APS selected</string>
|
||||||
<string name="nsclienthaswritepermission">NSClient has write permission</string>
|
<string name="nsclienthaswritepermission">NSClient has write permission</string>
|
||||||
|
@ -953,8 +956,8 @@
|
||||||
<string name="low_mark_comment">Lower value of in range area (display only)</string>
|
<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="high_mark_comment">Higher value of in range area (display only)</string>
|
||||||
|
|
||||||
<string name="age">Age:</string>
|
<string name="age">Age</string>
|
||||||
<string name="weight_label">Weight:</string>
|
<string name="weight_label">Weight</string>
|
||||||
<string name="id">ID:</string>
|
<string name="id">ID:</string>
|
||||||
<string name="submit">Submit</string>
|
<string name="submit">Submit</string>
|
||||||
<string name="mostcommonprofile">Most common profile:</string>
|
<string name="mostcommonprofile">Most common profile:</string>
|
||||||
|
@ -1164,5 +1167,44 @@
|
||||||
<string name="a11y_insulin_label">insulin</string>
|
<string name="a11y_insulin_label">insulin</string>
|
||||||
<string name="a11y_blood_glucose">blood glucose</string>
|
<string name="a11y_blood_glucose">blood glucose</string>
|
||||||
<string name="a11y_bg_outdated">outdated</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>
|
</resources>
|
||||||
|
|
|
@ -278,7 +278,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun removeIfExists(event: AutomationEvent) {
|
fun removeIfExists(event: AutomationEvent) {
|
||||||
for (e in automationEvents) {
|
for (e in automationEvents.reversed()) {
|
||||||
if (event.title == e.title) {
|
if (event.title == e.title) {
|
||||||
automationEvents.remove(e)
|
automationEvents.remove(e)
|
||||||
rxBus.send(EventAutomationDataChanged())
|
rxBus.send(EventAutomationDataChanged())
|
||||||
|
@ -301,6 +301,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun at(index: Int) = automationEvents[index]
|
fun at(index: Int) = automationEvents[index]
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
fun size() = automationEvents.size
|
fun size() = automationEvents.size
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -309,6 +310,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
rxBus.send(EventAutomationDataChanged())
|
rxBus.send(EventAutomationDataChanged())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
fun userEvents(): List<AutomationEvent> {
|
fun userEvents(): List<AutomationEvent> {
|
||||||
val list = mutableListOf<AutomationEvent>()
|
val list = mutableListOf<AutomationEvent>()
|
||||||
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
||||||
|
|
|
@ -9,7 +9,7 @@ buildscript {
|
||||||
rxkotlin_version = '2.4.0'
|
rxkotlin_version = '2.4.0'
|
||||||
room_version = '2.3.0'
|
room_version = '2.3.0'
|
||||||
lifecycle_version = '2.3.1'
|
lifecycle_version = '2.3.1'
|
||||||
dagger_version = '2.40.5'
|
dagger_version = '2.41'
|
||||||
coroutines_version = '1.4.1'
|
coroutines_version = '1.4.1'
|
||||||
activity_version = '1.3.1'
|
activity_version = '1.3.1'
|
||||||
fragmentktx_version = '1.3.6'
|
fragmentktx_version = '1.3.6'
|
||||||
|
@ -41,7 +41,7 @@ buildscript {
|
||||||
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
|
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.1.1'
|
classpath 'com.android.tools.build:gradle:7.1.0'
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.telephony.SmsManager
|
import android.telephony.SmsManager
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
|
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -17,7 +18,7 @@ open class CoreModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideResources(context: Context): ResourceHelper = ResourceHelperImplementation(context)
|
fun provideResources(context: Context, fabricPrivacy: FabricPrivacy): ResourceHelper = ResourceHelperImplementation(context, fabricPrivacy)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun smsManager() : SmsManager = SmsManager.getDefault()
|
fun smsManager() : SmsManager = SmsManager.getDefault()
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package info.nightscout.androidaps.interfaces
|
package info.nightscout.androidaps.interfaces
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||||
|
|
||||||
interface APS {
|
interface APS {
|
||||||
|
|
||||||
val lastAPSResult: APSResult?
|
val lastAPSResult: APSResult?
|
||||||
val lastAPSRun: Long
|
val lastAPSRun: Long
|
||||||
|
var lastDetermineBasalAdapter: DetermineBasalAdapterInterface?
|
||||||
|
var lastAutosensResult: AutosensResult
|
||||||
|
|
||||||
operator fun invoke(initiator: String, tempBasalFallback: Boolean)
|
operator fun invoke(initiator: String, tempBasalFallback: Boolean)
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.interfaces
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.data.IobTotal
|
||||||
|
import info.nightscout.androidaps.data.MealData
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
|
|
||||||
|
interface DetermineBasalAdapterInterface {
|
||||||
|
|
||||||
|
var currentTempParam: String?
|
||||||
|
var iobDataParam: String?
|
||||||
|
var glucoseStatusParam: String?
|
||||||
|
var profileParam: String?
|
||||||
|
var mealDataParam: String?
|
||||||
|
var scriptDebug: String
|
||||||
|
|
||||||
|
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 = false,
|
||||||
|
uamAllowed: Boolean = false,
|
||||||
|
advancedFiltering: Boolean = false,
|
||||||
|
isSaveCgmSource: Boolean = false
|
||||||
|
) {}
|
||||||
|
|
||||||
|
operator fun invoke(): APSResult?
|
||||||
|
}
|
|
@ -35,5 +35,5 @@ class PluginDescription {
|
||||||
fun enableByDefault(enableByDefault: Boolean): PluginDescription = this.also { it.enableByDefault = enableByDefault }
|
fun enableByDefault(enableByDefault: Boolean): PluginDescription = this.also { it.enableByDefault = enableByDefault }
|
||||||
fun visibleByDefault(visibleByDefault: Boolean): PluginDescription = this.also { it.visibleByDefault = visibleByDefault }
|
fun visibleByDefault(visibleByDefault: Boolean): PluginDescription = this.also { it.visibleByDefault = visibleByDefault }
|
||||||
fun description(description: Int): PluginDescription = this.also { it.description = description }
|
fun description(description: Int): PluginDescription = this.also { it.description = description }
|
||||||
fun setDefault(): PluginDescription = this.also { it.defaultPlugin = true }
|
fun setDefault(value: Boolean = true): PluginDescription = this.also { it.defaultPlugin = value }
|
||||||
}
|
}
|
|
@ -77,10 +77,16 @@ class FabricPrivacy @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crashlytics log message
|
||||||
|
fun logMessage(message: String) {
|
||||||
|
aapsLogger.info(LTag.CORE,"Crashlytics log message: $message")
|
||||||
|
FirebaseCrashlytics.getInstance().log(message)
|
||||||
|
}
|
||||||
|
|
||||||
// Crashlytics logException
|
// Crashlytics logException
|
||||||
fun logException(throwable: Throwable) {
|
fun logException(throwable: Throwable) {
|
||||||
|
aapsLogger.error("Crashlytics log exception: ", throwable)
|
||||||
FirebaseCrashlytics.getInstance().recordException(throwable)
|
FirebaseCrashlytics.getInstance().recordException(throwable)
|
||||||
aapsLogger.error("Exception: ", throwable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fabricEnabled(): Boolean {
|
fun fabricEnabled(): Boolean {
|
||||||
|
|
|
@ -11,17 +11,35 @@ import android.util.DisplayMetrics
|
||||||
import androidx.annotation.*
|
import androidx.annotation.*
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 2019-12-23.
|
* Created by adrian on 2019-12-23.
|
||||||
*/
|
*/
|
||||||
class ResourceHelperImplementation @Inject constructor(private val context: Context) : ResourceHelper {
|
class ResourceHelperImplementation @Inject constructor(private val context: Context, private val fabricPrivacy: FabricPrivacy) : ResourceHelper {
|
||||||
|
|
||||||
override fun gs(@StringRes id: Int): String = context.getString(id)
|
override fun gs(@StringRes id: Int): String = context.getString(id)
|
||||||
|
|
||||||
override fun gs(@StringRes id: Int, vararg args: Any?): String = context.getString(id, *args)
|
override fun gs(@StringRes id: Int, vararg args: Any?) : String {
|
||||||
|
return try {
|
||||||
|
context.getString(id, *args)
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
val resourceName = context.resources.getResourceEntryName(id)
|
||||||
|
val resourceValue = context.getString(id)
|
||||||
|
val currentLocale: Locale = context.resources.configuration.locale
|
||||||
|
fabricPrivacy.logMessage("Failed to get string for resource $resourceName ($id) '$resourceValue' for locale $currentLocale with args ${args.map{it.toString()}}")
|
||||||
|
fabricPrivacy.logException(exception)
|
||||||
|
try {
|
||||||
|
gsNotLocalised(id, *args)
|
||||||
|
} catch (exceptionNonLocalized: Exception) {
|
||||||
|
fabricPrivacy.logMessage("Fallback failed to get string for resource $resourceName ($id) '$resourceValue' with args ${args.map { it.toString() }}")
|
||||||
|
fabricPrivacy.logException(exceptionNonLocalized)
|
||||||
|
"FAILED to get string $resourceName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String =
|
override fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String =
|
||||||
context.resources.getQuantityString(id, quantity, *args)
|
context.resources.getQuantityString(id, quantity, *args)
|
||||||
|
@ -29,7 +47,7 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
||||||
override fun gsNotLocalised(@StringRes id: Int, vararg args: Any?): String =
|
override fun gsNotLocalised(@StringRes id: Int, vararg args: Any?): String =
|
||||||
with(Configuration(context.resources.configuration)) {
|
with(Configuration(context.resources.configuration)) {
|
||||||
setLocale(Locale.ENGLISH)
|
setLocale(Locale.ENGLISH)
|
||||||
context.createConfigurationContext(this).getString(id, args)
|
context.createConfigurationContext(this).getString(id, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun gc(@ColorRes id: Int): Int = ContextCompat.getColor(context, id)
|
override fun gc(@ColorRes id: Int): Int = ContextCompat.getColor(context, id)
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
<stroke android:width="1dp" android:color="@color/colorLightGray" />
|
<stroke android:width="1dp" android:color="@color/colorLightGray" />
|
||||||
<solid android:color="@android:color/white" />
|
<solid android:color="@android:color/white" />
|
||||||
<corners android:radius="4dp" />
|
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<vector
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:height="48dp"
|
|
||||||
android:width="48dp"
|
android:width="48dp"
|
||||||
android:viewportHeight="24"
|
android:height="48dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
android:viewportHeight="24">
|
||||||
<path android:fillColor="#67DFE8" android:pathData="M18.501,12.002l-0.428,0.564L8.179,5.064c-0.092,-0.07 -0.212,-0.09 -0.323,-0.055L5.115,5.89L1.571,3.501L4.755,6.36L4.647,9.243c-0.004,0.116 0.047,0.226 0.14,0.296l9.895,7.502l-0.428,0.564c-0.26,0.343 -0.193,0.832 0.15,1.092s0.832,0.193 1.092,-0.15l1.653,-2.18l2.219,1.683l-0.719,0.948c-0.26,0.343 -0.193,0.832 0.15,1.092c0.343,0.26 0.832,0.193 1.092,-0.15l2.379,-3.138c0.26,-0.343 0.193,-0.832 -0.15,-1.092c-0.343,-0.26 -0.832,-0.193 -1.092,0.15l-0.719,0.948l-2.219,-1.683l1.653,-2.18c0.26,-0.343 0.193,-0.832 -0.15,-1.092S18.762,11.659 18.501,12.002zM5.458,6.524l2.44,-0.783l9.748,7.39L17.26,13.64l-5.754,-4.362c-0.091,-0.069 -0.221,-0.053 -0.293,0.035L9.087,11.91l-0.67,-0.508l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027l-1.538,1.848l-0.769,-0.583l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027L6.97,10.305L6.201,9.721l1.526,-1.833C7.728,7.886 7.731,7.882 7.732,7.88c0.068,-0.09 0.054,-0.219 -0.033,-0.291C7.609,7.513 7.475,7.526 7.4,7.616L5.861,9.464L5.362,9.085L5.458,6.524z"/>
|
<path
|
||||||
|
android:fillColor="#67DFE8"
|
||||||
|
android:pathData="M18.501,12.002l-0.428,0.564L8.179,5.064c-0.092,-0.07 -0.212,-0.09 -0.323,-0.055L5.115,5.89L1.571,3.501L4.755,6.36L4.647,9.243c-0.004,0.116 0.047,0.226 0.14,0.296l9.895,7.502l-0.428,0.564c-0.26,0.343 -0.193,0.832 0.15,1.092s0.832,0.193 1.092,-0.15l1.653,-2.18l2.219,1.683l-0.719,0.948c-0.26,0.343 -0.193,0.832 0.15,1.092c0.343,0.26 0.832,0.193 1.092,-0.15l2.379,-3.138c0.26,-0.343 0.193,-0.832 -0.15,-1.092c-0.343,-0.26 -0.832,-0.193 -1.092,0.15l-0.719,0.948l-2.219,-1.683l1.653,-2.18c0.26,-0.343 0.193,-0.832 -0.15,-1.092S18.762,11.659 18.501,12.002zM5.458,6.524l2.44,-0.783l9.748,7.39L17.26,13.64l-5.754,-4.362c-0.091,-0.069 -0.221,-0.053 -0.293,0.035L9.087,11.91l-0.67,-0.508l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027l-1.538,1.848l-0.769,-0.583l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027L6.97,10.305L6.201,9.721l1.526,-1.833C7.728,7.886 7.731,7.882 7.732,7.88c0.068,-0.09 0.054,-0.219 -0.033,-0.291C7.609,7.513 7.475,7.526 7.4,7.616L5.861,9.464L5.362,9.085L5.458,6.524z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|
5
core/src/main/res/drawable/ic_smartphone.xml
Normal file
5
core/src/main/res/drawable/ic_smartphone.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19H7V5h10v14z"/>
|
||||||
|
</vector>
|
|
@ -9,13 +9,13 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:width="120dp"
|
android:width="120dp"
|
||||||
|
android:labelFor="@+id/eventtime"
|
||||||
android:paddingLeft="10dp"
|
android:paddingLeft="10dp"
|
||||||
android:paddingRight="4dp"
|
android:paddingRight="4dp"
|
||||||
android:text="@string/event_time_label"
|
android:text="@string/event_time_label"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/eventdate"
|
android:id="@+id/eventdate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<string name="key_virtualpump_type" translatable="false">virtualpump_type</string>
|
<string name="key_virtualpump_type" translatable="false">virtualpump_type</string>
|
||||||
<string name="key_quickwizard" translatable="false">QuickWizard</string>
|
<string name="key_quickwizard" translatable="false">QuickWizard</string>
|
||||||
<string name="key_wear_control" translatable="false">wearcontrol</string>
|
<string name="key_wear_control" translatable="false">wearcontrol</string>
|
||||||
|
<string name="key_units_mgdl" translatable="false">units_mgdl</string>
|
||||||
<string name="key_show_notes_entry_dialogs" translatable="false">show_notes_entry_dialogs</string>
|
<string name="key_show_notes_entry_dialogs" translatable="false">show_notes_entry_dialogs</string>
|
||||||
<string name="key_openapsama_autosens_max" translatable="false">autosens_max</string>
|
<string name="key_openapsama_autosens_max" translatable="false">autosens_max</string>
|
||||||
<string name="key_openapsama_autosens_min" translatable="false">autosens_min</string>
|
<string name="key_openapsama_autosens_min" translatable="false">autosens_min</string>
|
||||||
|
|
|
@ -25,7 +25,7 @@ dependencies {
|
||||||
api "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
|
api "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
|
||||||
api("io.reactivex.rxjava2:rxkotlin:$rxkotlin_version")
|
api("io.reactivex.rxjava2:rxkotlin:$rxkotlin_version")
|
||||||
|
|
||||||
api "com.google.code.gson:gson:2.8.9"
|
api "com.google.code.gson:gson:2.9.0"
|
||||||
|
|
||||||
api "androidx.room:room-runtime:$room_version"
|
api "androidx.room:room-runtime:$room_version"
|
||||||
kapt "androidx.room:room-compiler:$room_version"
|
kapt "androidx.room:room-compiler:$room_version"
|
||||||
|
|
|
@ -30,7 +30,7 @@ android {
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lint {
|
||||||
checkReleaseBuilds false
|
checkReleaseBuilds false
|
||||||
disable 'MissingTranslation'
|
disable 'MissingTranslation'
|
||||||
disable 'ExtraTranslation'
|
disable 'ExtraTranslation'
|
||||||
|
|
|
@ -768,7 +768,7 @@ class MedtronicPumpPlugin @Inject constructor(
|
||||||
medtronicPumpStatus.tempBasalAmount = absoluteRate
|
medtronicPumpStatus.tempBasalAmount = absoluteRate
|
||||||
medtronicPumpStatus.tempBasalLength = durationInMinutes
|
medtronicPumpStatus.tempBasalLength = durationInMinutes
|
||||||
|
|
||||||
val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType)
|
val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes * 60, tbrType)
|
||||||
|
|
||||||
medtronicPumpStatus.runningTBRWithTemp = tempData
|
medtronicPumpStatus.runningTBRWithTemp = tempData
|
||||||
pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this)
|
pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this)
|
||||||
|
|
|
@ -3,7 +3,11 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.bluetooth.*
|
import android.bluetooth.*
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes
|
||||||
|
@ -32,14 +36,15 @@ import javax.inject.Singleton
|
||||||
* Added: State handling, configuration of RF for different configuration ranges, connection handling
|
* Added: State handling, configuration of RF for different configuration ranges, connection handling
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class RileyLinkBLE @Inject constructor(private val context: Context) {
|
class RileyLinkBLE @Inject constructor(
|
||||||
|
private val context: Context,
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
private val aapsLogger: AAPSLogger,
|
||||||
@Inject lateinit var rileyLinkServiceData: RileyLinkServiceData
|
private val rileyLinkServiceData: RileyLinkServiceData,
|
||||||
@Inject lateinit var rileyLinkUtil: RileyLinkUtil
|
private val rileyLinkUtil: RileyLinkUtil,
|
||||||
@Inject lateinit var sp: SP
|
private val sp: SP,
|
||||||
@Inject lateinit var orangeLink: OrangeLinkImpl
|
private val orangeLink: OrangeLinkImpl,
|
||||||
|
private val config: Config
|
||||||
|
) {
|
||||||
private val gattDebugEnabled = true
|
private val gattDebugEnabled = true
|
||||||
private var manualDisconnect = false
|
private var manualDisconnect = false
|
||||||
|
|
||||||
|
@ -154,7 +159,12 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device is null, can't do connectGatt.")
|
aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device is null, can't do connectGatt.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback)
|
if (config.PUMPDRIVERS && Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31 &&
|
||||||
|
ContextCompat.checkSelfPermission(context, "android.permission.BLUETOOTH_CONNECT") == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "no permission")
|
||||||
|
return
|
||||||
|
} else bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback)
|
||||||
// , BluetoothDevice.TRANSPORT_LE
|
// , BluetoothDevice.TRANSPORT_LE
|
||||||
if (bluetoothConnectionGatt == null)
|
if (bluetoothConnectionGatt == null)
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter?.address)
|
aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter?.address)
|
||||||
|
|
|
@ -53,7 +53,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "info.nightscout.androidaps"
|
applicationId "info.nightscout.androidaps"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 28
|
targetSdkVersion 29
|
||||||
versionCode 2
|
versionCode 2
|
||||||
versionName "1.0.3"
|
versionName "1.0.3"
|
||||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||||
|
@ -107,7 +107,6 @@ dependencies {
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.wear:wear:1.2.0'
|
implementation 'androidx.wear:wear:1.2.0'
|
||||||
|
|
||||||
|
|
||||||
compileOnly "com.google.android.wearable:wearable:${wearableVersion}"
|
compileOnly "com.google.android.wearable:wearable:${wearableVersion}"
|
||||||
implementation "com.google.android.support:wearable:${wearableVersion}"
|
implementation "com.google.android.support:wearable:${wearableVersion}"
|
||||||
implementation "com.google.android.gms:play-services-wearable:${playServicesWearable}"
|
implementation "com.google.android.gms:play-services-wearable:${playServicesWearable}"
|
||||||
|
@ -115,6 +114,10 @@ dependencies {
|
||||||
implementation(name: 'wearpreferenceactivity-0.5.0', ext: 'aar')
|
implementation(name: 'wearpreferenceactivity-0.5.0', ext: 'aar')
|
||||||
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
|
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
|
||||||
|
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0'
|
||||||
|
implementation "androidx.core:core-ktx:$core_version"
|
||||||
|
implementation "androidx.wear.tiles:tiles:1.0.1"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
testImplementation "junit:junit:$junit_version"
|
testImplementation "junit:junit:$junit_version"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="info.nightscout.androidaps">
|
package="info.nightscout.androidaps">
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.type.watch" />
|
<uses-feature android:name="android.hardware.type.watch" />
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
|
||||||
|
<uses-sdk tools:overrideLibrary="androidx.wear.tiles" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".Aaps"
|
android:name=".Aaps"
|
||||||
|
@ -256,6 +258,10 @@
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/openwearsettings"
|
android:pathPrefix="/openwearsettings"
|
||||||
android:scheme="wear" />
|
android:scheme="wear" />
|
||||||
|
<data
|
||||||
|
android:host="*"
|
||||||
|
android:pathPrefix="/send_quick_wizard"
|
||||||
|
android:scheme="wear" />
|
||||||
<data
|
<data
|
||||||
android:host="*"
|
android:host="*"
|
||||||
android:pathPrefix="/sendstatustowear"
|
android:pathPrefix="/sendstatustowear"
|
||||||
|
@ -508,6 +514,54 @@
|
||||||
android:value="0" />
|
android:value="0" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".tile.ActionsTileService"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/label_actions_tile"
|
||||||
|
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.clockwork.tiles.PROVIDER_CONFIG_ACTION"
|
||||||
|
android:value="tile_configuration_activity" />
|
||||||
|
<meta-data
|
||||||
|
android:name="androidx.wear.tiles.PREVIEW"
|
||||||
|
android:resource="@drawable/action_tile_preview" />
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".tile.TempTargetTileService"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/label_temp_target_tile"
|
||||||
|
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.clockwork.tiles.PROVIDER_CONFIG_ACTION"
|
||||||
|
android:value="tile_configuration_tempt" />
|
||||||
|
<meta-data
|
||||||
|
android:name="androidx.wear.tiles.PREVIEW"
|
||||||
|
android:resource="@drawable/temp_target_tile_preview" />
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".tile.QuickWizardTileService"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/label_quick_wizard_tile"
|
||||||
|
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="androidx.wear.tiles.PREVIEW"
|
||||||
|
android:resource="@drawable/quick_wizard_tile_preview" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver android:name=".complications.ComplicationTapBroadcastReceiver" />
|
<receiver android:name=".complications.ComplicationTapBroadcastReceiver" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
@ -523,6 +577,7 @@
|
||||||
android:label="@string/menu_settings" />
|
android:label="@string/menu_settings" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.WizardActivity"
|
android:name=".interaction.actions.WizardActivity"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/menu_wizard" />
|
android:label="@string/menu_wizard" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.menus.FillMenuActivity"
|
android:name=".interaction.menus.FillMenuActivity"
|
||||||
|
@ -530,9 +585,14 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.menus.StatusMenuActivity"
|
android:name=".interaction.menus.StatusMenuActivity"
|
||||||
android:label="@string/menu_status" />
|
android:label="@string/menu_status" />
|
||||||
|
<activity
|
||||||
|
android:name=".interaction.actions.TreatmentActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/menu_treatment" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.BolusActivity"
|
android:name=".interaction.actions.BolusActivity"
|
||||||
android:label="@string/action_bolus" />
|
android:exported="true"
|
||||||
|
android:label="@string/action_insulin" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.CPPActivity"
|
android:name=".interaction.actions.CPPActivity"
|
||||||
android:label="@string/status_cpp" />
|
android:label="@string/status_cpp" />
|
||||||
|
@ -542,14 +602,21 @@
|
||||||
android:launchMode="singleInstance" />
|
android:launchMode="singleInstance" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.FillActivity"
|
android:name=".interaction.actions.FillActivity"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/menu_prime_fill" />
|
android:label="@string/menu_prime_fill" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.ECarbActivity"
|
android:name=".interaction.actions.ECarbActivity"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/action_carbs" />
|
android:label="@string/action_carbs" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".interaction.actions.TempTargetActivity"
|
android:name=".interaction.actions.TempTargetActivity"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/menu_tempt" />
|
android:label="@string/menu_tempt" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".interaction.actions.BackgroundActionActivity"
|
||||||
|
android:exported="true" />
|
||||||
|
|
||||||
<activity android:name=".interaction.ConfigurationActivity">
|
<activity android:name=".interaction.ConfigurationActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<!-- action-name must be equal with name of xml-ressource where the configuration is describe -->
|
<!-- action-name must be equal with name of xml-ressource where the configuration is describe -->
|
||||||
|
@ -567,5 +634,16 @@
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".interaction.TileConfigurationActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="tile_configuration_activity" />
|
||||||
|
<action android:name="tile_configuration_tempt" />
|
||||||
|
|
||||||
|
<category android:name="com.google.android.clockwork.tiles.category.PROVIDER_CONFIG" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.DaggerBroadcastReceiver;
|
import dagger.android.DaggerBroadcastReceiver;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.interaction.actions.BolusActivity;
|
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
|
||||||
|
@ -77,7 +77,7 @@ public class ComplicationTapBroadcastReceiver extends DaggerBroadcastReceiver {
|
||||||
intentOpen = new Intent(context, WizardActivity.class);
|
intentOpen = new Intent(context, WizardActivity.class);
|
||||||
break;
|
break;
|
||||||
case BOLUS:
|
case BOLUS:
|
||||||
intentOpen = new Intent(context, BolusActivity.class);
|
intentOpen = new Intent(context, TreatmentActivity.class);
|
||||||
break;
|
break;
|
||||||
case ECARB:
|
case ECARB:
|
||||||
intentOpen = new Intent(context, ECarbActivity.class);
|
intentOpen = new Intent(context, ECarbActivity.class);
|
||||||
|
|
|
@ -13,18 +13,16 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
import androidx.wear.tiles.TileService;
|
||||||
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
import com.google.android.gms.common.ConnectionResult;
|
||||||
import com.google.android.gms.common.api.GoogleApiClient;
|
import com.google.android.gms.common.api.GoogleApiClient;
|
||||||
import com.google.android.gms.common.api.PendingResult;
|
|
||||||
import com.google.android.gms.common.api.ResultCallback;
|
|
||||||
import com.google.android.gms.wearable.CapabilityApi;
|
|
||||||
import com.google.android.gms.wearable.CapabilityInfo;
|
|
||||||
import com.google.android.gms.wearable.ChannelApi;
|
import com.google.android.gms.wearable.ChannelApi;
|
||||||
import com.google.android.gms.wearable.DataEvent;
|
import com.google.android.gms.wearable.DataEvent;
|
||||||
import com.google.android.gms.wearable.DataEventBuffer;
|
import com.google.android.gms.wearable.DataEventBuffer;
|
||||||
|
@ -35,7 +33,8 @@ import com.google.android.gms.wearable.NodeApi;
|
||||||
import com.google.android.gms.wearable.Wearable;
|
import com.google.android.gms.wearable.Wearable;
|
||||||
import com.google.android.gms.wearable.WearableListenerService;
|
import com.google.android.gms.wearable.WearableListenerService;
|
||||||
|
|
||||||
import java.util.Set;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -46,9 +45,11 @@ import info.nightscout.androidaps.interaction.AAPSPreferences;
|
||||||
import info.nightscout.androidaps.interaction.actions.AcceptActivity;
|
import info.nightscout.androidaps.interaction.actions.AcceptActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.CPPActivity;
|
import info.nightscout.androidaps.interaction.actions.CPPActivity;
|
||||||
import info.nightscout.androidaps.interaction.utils.Persistence;
|
import info.nightscout.androidaps.interaction.utils.Persistence;
|
||||||
import info.nightscout.shared.SafeParse;
|
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
import info.nightscout.androidaps.interaction.utils.WearUtil;
|
||||||
|
import info.nightscout.androidaps.tile.ActionsTileService;
|
||||||
|
import info.nightscout.androidaps.tile.QuickWizardTileService;
|
||||||
|
import info.nightscout.androidaps.tile.TempTargetTileService;
|
||||||
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by emmablack on 12/26/14.
|
* Created by emmablack on 12/26/14.
|
||||||
|
@ -59,7 +60,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
@Inject WearUtil wearUtil;
|
@Inject WearUtil wearUtil;
|
||||||
@Inject Persistence persistence;
|
@Inject Persistence persistence;
|
||||||
|
|
||||||
private static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
|
|
||||||
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
|
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
|
||||||
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
|
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
|
||||||
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
|
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
|
||||||
|
@ -68,13 +68,13 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
private static final String OPEN_SETTINGS = "/openwearsettings";
|
private static final String OPEN_SETTINGS = "/openwearsettings";
|
||||||
private static final String NEW_STATUS_PATH = "/sendstatustowear";
|
private static final String NEW_STATUS_PATH = "/sendstatustowear";
|
||||||
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
|
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 BASAL_DATA_PATH = "/nightscout_watch_basal";
|
||||||
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
|
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_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
|
||||||
public static final String NEW_CHANGECONFIRMATIONREQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
|
public static final String NEW_CHANGECONFIRMATIONREQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
|
||||||
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
|
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
|
||||||
|
|
||||||
|
|
||||||
public static final int BOLUS_PROGRESS_NOTIF_ID = 1;
|
public static final int BOLUS_PROGRESS_NOTIF_ID = 1;
|
||||||
public static final int CONFIRM_NOTIF_ID = 2;
|
public static final int CONFIRM_NOTIF_ID = 2;
|
||||||
public static final int CHANGE_NOTIF_ID = 556677;
|
public static final int CHANGE_NOTIF_ID = 556677;
|
||||||
|
@ -85,29 +85,15 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
private static final String ACTION_CONFIRMCHANGE = "com.dexdrip.stephenblack.nightwatch.CONFIRMCHANGE";
|
private static final String ACTION_CONFIRMCHANGE = "com.dexdrip.stephenblack.nightwatch.CONFIRMCHANGE";
|
||||||
private static final String ACTION_INITIATE_ACTION = "com.dexdrip.stephenblack.nightwatch.INITIATE_ACTION";
|
private static final String ACTION_INITIATE_ACTION = "com.dexdrip.stephenblack.nightwatch.INITIATE_ACTION";
|
||||||
|
|
||||||
|
|
||||||
private static final String ACTION_RESEND_BULK = "com.dexdrip.stephenblack.nightwatch.RESEND_BULK_DATA";
|
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_OPENLOOP = "AndroidAPS-OpenLoop";
|
private static final String AAPS_NOTIFY_CHANNEL_ID_OPENLOOP = "AndroidAPS-OpenLoop";
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS = "bolus progress vibration";
|
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS = "bolus progress vibration";
|
||||||
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT = "bolus progress silent";
|
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT = "bolus progress silent";
|
||||||
|
|
||||||
|
|
||||||
GoogleApiClient googleApiClient;
|
GoogleApiClient googleApiClient;
|
||||||
private long lastRequest = 0;
|
|
||||||
private DismissThread bolusprogressThread;
|
private DismissThread bolusprogressThread;
|
||||||
private static final String TAG = "ListenerService";
|
private static final String TAG = "ListenerService";
|
||||||
|
|
||||||
private DataRequester mDataRequester = null;
|
|
||||||
private static final int GET_CAPABILITIES_TIMEOUT_MS = 5000;
|
|
||||||
|
|
||||||
// Phone
|
|
||||||
private static final String CAPABILITY_PHONE_APP = "phone_app_sync_bgs";
|
|
||||||
private static final String MESSAGE_PATH_PHONE = "/phone_message_path";
|
|
||||||
// Wear
|
|
||||||
private static final String CAPABILITY_WEAR_APP = "wear_app_sync_bgs";
|
|
||||||
private static final String MESSAGE_PATH_WEAR = "/wear_message_path";
|
|
||||||
private final String mPhoneNodeId = null;
|
|
||||||
private String localnode = null;
|
|
||||||
private final String logPrefix = ""; // "WR: "
|
private final String logPrefix = ""; // "WR: "
|
||||||
|
|
||||||
// Not derived from DaggerService, do injection here
|
// Not derived from DaggerService, do injection here
|
||||||
|
@ -117,143 +103,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataRequester extends AsyncTask<Void, Void, Void> {
|
|
||||||
Context mContext;
|
|
||||||
String path;
|
|
||||||
byte[] payload;
|
|
||||||
|
|
||||||
|
|
||||||
DataRequester(Context context, String thispath, byte[] thispayload) {
|
|
||||||
path = thispath;
|
|
||||||
payload = thispayload;
|
|
||||||
// Log.d(TAG, logPrefix + "DataRequester DataRequester: " + thispath + " lastRequest:" + lastRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
// Log.d(TAG, logPrefix + "DataRequester: doInBack: " + params);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
forceGoogleApiConnect();
|
|
||||||
DataMap datamap;
|
|
||||||
|
|
||||||
if (isCancelled()) {
|
|
||||||
Log.d(TAG, "doInBackground CANCELLED programmatically");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (googleApiClient != null) {
|
|
||||||
if (!googleApiClient.isConnected())
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this code might not be needed in this way, but we need to see that later
|
|
||||||
if ((googleApiClient != null) && (googleApiClient.isConnected())) {
|
|
||||||
if ((System.currentTimeMillis() - lastRequest > 20 * 1000)) {
|
|
||||||
|
|
||||||
// enforce 20-second debounce period
|
|
||||||
lastRequest = System.currentTimeMillis();
|
|
||||||
|
|
||||||
// NodeApi.GetConnectedNodesResult nodes =
|
|
||||||
// Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
if (localnode == null || (localnode != null && localnode.isEmpty()))
|
|
||||||
setLocalNodeName();
|
|
||||||
|
|
||||||
CapabilityInfo capabilityInfo = getCapabilities();
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
Node phoneNode = null;
|
|
||||||
|
|
||||||
if (capabilityInfo != null) {
|
|
||||||
phoneNode = updatePhoneSyncBgsCapability(capabilityInfo);
|
|
||||||
count = capabilityInfo.getNodes().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "doInBackground connected. CapabilityApi.GetCapabilityResult mPhoneNodeID="
|
|
||||||
+ (phoneNode != null ? phoneNode.getId() : "") + " count=" + count + " localnode="
|
|
||||||
+ localnode);// KS
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
|
|
||||||
for (Node node : capabilityInfo.getNodes()) {
|
|
||||||
|
|
||||||
// Log.d(TAG, "doInBackground path: " + path);
|
|
||||||
|
|
||||||
switch (path) {
|
|
||||||
// simple send as is payloads
|
|
||||||
|
|
||||||
case WEARABLE_RESEND_PATH:
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(),
|
|
||||||
WEARABLE_RESEND_PATH, null);
|
|
||||||
break;
|
|
||||||
case WEARABLE_DATA_PATH:
|
|
||||||
case WEARABLE_CANCELBOLUS_PATH:
|
|
||||||
case WEARABLE_CONFIRM_ACTIONSTRING_PATH:
|
|
||||||
case WEARABLE_INITIATE_ACTIONSTRING_PATH:
|
|
||||||
case OPEN_SETTINGS:
|
|
||||||
case NEW_STATUS_PATH:
|
|
||||||
case NEW_PREFERENCES_PATH:
|
|
||||||
case BASAL_DATA_PATH:
|
|
||||||
case BOLUS_PROGRESS_PATH:
|
|
||||||
case ACTION_CONFIRMATION_REQUEST_PATH:
|
|
||||||
case NEW_CHANGECONFIRMATIONREQUEST_PATH:
|
|
||||||
case ACTION_CANCELNOTIFICATION_REQUEST_PATH: {
|
|
||||||
Log.w(TAG, logPrefix + "Unhandled path");
|
|
||||||
// sendMessagePayload(node, path, path, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
default:// SYNC_ALL_DATA
|
|
||||||
// this fall through is messy and non-deterministic for new paths
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Log.d(TAG, logPrefix + "doInBackground connected but getConnectedNodes returns 0.");
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no resend
|
|
||||||
Log.d(TAG, logPrefix + "Inside the timeout, will not be executed");
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, logPrefix + "Not connected for sending: api "
|
|
||||||
+ ((googleApiClient == null) ? "is NULL!" : "not null"));
|
|
||||||
if (googleApiClient != null) {
|
|
||||||
googleApiClient.connect();
|
|
||||||
} else {
|
|
||||||
googleApiConnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Log.e(TAG, logPrefix + "Error executing DataRequester in background. Exception: " + ex.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public CapabilityInfo getCapabilities() {
|
|
||||||
|
|
||||||
CapabilityApi.GetCapabilityResult capabilityResult = Wearable.CapabilityApi.getCapability(googleApiClient,
|
|
||||||
CAPABILITY_PHONE_APP, CapabilityApi.FILTER_REACHABLE).await(GET_CAPABILITIES_TIMEOUT_MS,
|
|
||||||
TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
if (!capabilityResult.getStatus().isSuccess()) {
|
|
||||||
Log.e(TAG, logPrefix + "doInBackground Failed to get capabilities, status: "
|
|
||||||
+ capabilityResult.getStatus().getStatusMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return capabilityResult.getCapability();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BolusCancelTask extends AsyncTask<Void, Void, Void> {
|
public class BolusCancelTask extends AsyncTask<Void, Void, Void> {
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
|
@ -263,8 +112,11 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
// Log.d(TAG, logPrefix + "BolusCancelTask: doInBack: " + params);
|
Log.d(TAG, logPrefix + "BolusCancelTask.doInBackground: " + params);
|
||||||
|
if (!googleApiClient.isConnected()) {
|
||||||
|
Log.i(TAG, "BolusCancelTask.doInBackground: not connected");
|
||||||
|
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
if (googleApiClient.isConnected()) {
|
if (googleApiClient.isConnected()) {
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
NodeApi.GetConnectedNodesResult nodes =
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
||||||
|
@ -272,16 +124,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
|
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -300,9 +142,12 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
|
Log.i(TAG, "MessageActionTask.doInBackground: ");
|
||||||
|
|
||||||
forceGoogleApiConnect();
|
if (!googleApiClient.isConnected()) {
|
||||||
|
Log.i(TAG, "MessageActionTask.doInBackground: not connected");
|
||||||
|
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
if (googleApiClient.isConnected()) {
|
if (googleApiClient.isConnected()) {
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
NodeApi.GetConnectedNodesResult nodes =
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
||||||
|
@ -310,22 +155,42 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
|
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
|
||||||
if (googleApiClient.isConnected()) {
|
|
||||||
NodeApi.GetConnectedNodesResult nodes =
|
|
||||||
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
|
||||||
for (Node node : nodes.getNodes()) {
|
|
||||||
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ResendDataTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
Context mContext;
|
||||||
|
|
||||||
|
ResendDataTask(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
Log.d(TAG, logPrefix + "ResendDataTask.doInBackground: " + params);
|
||||||
|
|
||||||
|
if (!googleApiClient.isConnected()) {
|
||||||
|
Log.i(TAG, "ResendDataTask.doInBackground: not connected");
|
||||||
|
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
if (googleApiClient.isConnected()) {
|
||||||
|
Log.i(TAG, "ResendDataTask.doInBackground: connected");
|
||||||
|
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
||||||
|
for (Node node : nodes.getNodes()) {
|
||||||
|
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "ResendDataTask.doInBackground: could not connect");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void requestData() {
|
public void requestData() {
|
||||||
sendData(WEARABLE_RESEND_PATH, null);
|
new ResendDataTask(this).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelBolus() {
|
public void cancelBolus() {
|
||||||
|
@ -340,59 +205,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
new MessageActionTask(this, WEARABLE_INITIATE_ACTIONSTRING_PATH, actionstring).execute();
|
new MessageActionTask(this, WEARABLE_INITIATE_ACTIONSTRING_PATH, actionstring).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Node updatePhoneSyncBgsCapability(CapabilityInfo capabilityInfo) {
|
|
||||||
// Log.d(TAG, "CapabilityInfo: " + capabilityInfo);
|
|
||||||
|
|
||||||
Set<Node> connectedNodes = capabilityInfo.getNodes();
|
|
||||||
return pickBestNode(connectedNodes);
|
|
||||||
// mPhoneNodeId = pickBestNodeId(connectedNodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Node pickBestNode(Set<Node> nodes) {
|
|
||||||
Node bestNode = null;
|
|
||||||
// Find a nearby node or pick one arbitrarily
|
|
||||||
for (Node node : nodes) {
|
|
||||||
if (node.isNearby()) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
bestNode = node;
|
|
||||||
}
|
|
||||||
return bestNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private synchronized void sendData(String path, byte[] payload) {
|
|
||||||
// Log.d(TAG, "WR: sendData: path: " + path + ", payload=" + payload);
|
|
||||||
|
|
||||||
if (path == null)
|
|
||||||
return;
|
|
||||||
if (mDataRequester != null) {
|
|
||||||
// Log.d(TAG, logPrefix + "sendData DataRequester != null lastRequest:" +
|
|
||||||
// WearUtil.dateTimeText(lastRequest));
|
|
||||||
if (mDataRequester.getStatus() != AsyncTask.Status.FINISHED) {
|
|
||||||
// Log.d(TAG, logPrefix + "sendData Should be canceled? Let run 'til finished.");
|
|
||||||
// mDataRequester.cancel(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG,
|
|
||||||
logPrefix + "sendData: execute lastRequest:" + wearUtil.dateTimeText(lastRequest));
|
|
||||||
mDataRequester = (DataRequester) new DataRequester(this, path, payload).execute();
|
|
||||||
// executeTask(mDataRequester);
|
|
||||||
|
|
||||||
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
||||||
// Log.d(TAG, "sendData SDK < M call execute lastRequest:" + WearUtil.dateTimeText(lastRequest));
|
|
||||||
// mDataRequester = (DataRequester) new DataRequester(this, path, payload).execute();
|
|
||||||
// } else {
|
|
||||||
// Log.d(TAG, "sendData SDK >= M call executeOnExecutor lastRequest:" + WearUtil.dateTimeText(lastRequest));
|
|
||||||
// // TODO xdrip executor
|
|
||||||
// mDataRequester = (DataRequester) new DataRequester(this, path, payload).executeOnExecutor(xdrip.executor);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void googleApiConnect() {
|
private void googleApiConnect() {
|
||||||
if (googleApiClient != null) {
|
if (googleApiClient != null) {
|
||||||
// Remove old listener(s)
|
// Remove old listener(s)
|
||||||
|
@ -416,20 +228,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
Wearable.MessageApi.addListener(googleApiClient, this);
|
Wearable.MessageApi.addListener(googleApiClient, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void forceGoogleApiConnect() {
|
|
||||||
if (googleApiClient == null || (!googleApiClient.isConnected() && !googleApiClient.isConnecting())) {
|
|
||||||
try {
|
|
||||||
Log.d(TAG, "forceGoogleApiConnect: forcing google api reconnection");
|
|
||||||
googleApiConnect();
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
|
||||||
|
@ -483,7 +281,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDataChanged(DataEventBuffer dataEvents) {
|
public void onDataChanged(DataEventBuffer dataEvents) {
|
||||||
|
|
||||||
|
@ -541,12 +338,62 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
|
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
|
||||||
} else if (path.equals(NEW_PREFERENCES_PATH)) {
|
} else if (path.equals(NEW_PREFERENCES_PATH)) {
|
||||||
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
||||||
if (dataMap.containsKey("wearcontrol")) {
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
boolean wearcontrol = dataMap.getBoolean("wearcontrol", false);
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
String keyControl = getString(R.string.key_wear_control);
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
if (dataMap.containsKey(keyControl)) {
|
||||||
editor.putBoolean("wearcontrol", wearcontrol);
|
boolean previousWearControl = sharedPreferences.getBoolean(keyControl, false);
|
||||||
|
boolean wearControl = dataMap.getBoolean(keyControl, false);
|
||||||
|
editor.putBoolean(keyControl, wearControl);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
if (wearControl != previousWearControl) {
|
||||||
|
updateTiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String keyPercentage = getString(R.string.key_boluswizard_percentage);
|
||||||
|
if (dataMap.containsKey(keyPercentage)) {
|
||||||
|
int wpercentage = dataMap.getInt(keyPercentage, 100);
|
||||||
|
editor.putInt(keyPercentage, wpercentage);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
String keyUnits = getString(R.string.key_units_mgdl);
|
||||||
|
if (dataMap.containsKey(keyUnits)) {
|
||||||
|
boolean mgdl = dataMap.getBoolean(keyUnits, true);
|
||||||
|
editor.putBoolean(keyUnits, mgdl);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
String keyMaxCarbs = getString(R.string.key_treatmentssafety_maxcarbs);
|
||||||
|
if (dataMap.containsKey(keyMaxCarbs)) {
|
||||||
|
int maxCarbs = dataMap.getInt(keyMaxCarbs, 48);
|
||||||
|
editor.putInt(keyMaxCarbs, maxCarbs);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
String keyMaxBolus = getString(R.string.key_treatmentssafety_maxbolus);
|
||||||
|
if (dataMap.containsKey(keyMaxBolus)) {
|
||||||
|
float maxBolus = (float)dataMap.getDouble(keyMaxBolus, 3.0f);
|
||||||
|
editor.putFloat(keyMaxBolus, maxBolus);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (path.equals(QUICK_WIZARD_PATH)) {
|
||||||
|
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
|
||||||
|
Log.i(TAG, "onDataChanged: QUICK_WIZARD_PATH" + dataMap);
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
dataMap.remove("timestamp");
|
||||||
|
String key = getString(R.string.key_quick_wizard_data_map);
|
||||||
|
String dataString = Base64.encodeToString(dataMap.toByteArray(), Base64.DEFAULT);
|
||||||
|
if (!dataString.equals(sharedPreferences.getString(key, ""))) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putString(key, dataString);
|
||||||
|
editor.apply();
|
||||||
|
// Todo maybe add debounce function, due to 20 seconds update limit?
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(QuickWizardTileService.class);
|
||||||
|
}
|
||||||
|
Log.i(TAG, "onDataChanged: updated QUICK_WIZARD");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "onDataChanged: ignore update");
|
||||||
}
|
}
|
||||||
} else if (path.equals(NEW_CHANGECONFIRMATIONREQUEST_PATH)) {
|
} else if (path.equals(NEW_CHANGECONFIRMATIONREQUEST_PATH)) {
|
||||||
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
|
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
|
||||||
|
@ -568,6 +415,19 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateTiles() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(ActionsTileService.class);
|
||||||
|
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(TempTargetTileService.class);
|
||||||
|
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(QuickWizardTileService.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyChangeRequest(String title, String message, String actionstring) {
|
private void notifyChangeRequest(String title, String message, String actionstring) {
|
||||||
// Create the NotificationChannel, but only on API 26+ because
|
// Create the NotificationChannel, but only on API 26+ because
|
||||||
// the NotificationChannel class is new and not in the support library
|
// the NotificationChannel class is new and not in the support library
|
||||||
|
@ -639,7 +499,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0);
|
PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0);
|
||||||
|
|
||||||
NotificationCompat.Builder notificationBuilder =
|
NotificationCompat.Builder notificationBuilder =
|
||||||
new NotificationCompat.Builder(this, vibrate ? AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS: AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
|
new NotificationCompat.Builder(this, vibrate ? AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS : AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
|
||||||
.setSmallIcon(R.drawable.ic_icon)
|
.setSmallIcon(R.drawable.ic_icon)
|
||||||
.setContentTitle(getString(R.string.bolus_progress))
|
.setContentTitle(getString(R.string.bolus_progress))
|
||||||
.setContentText(progresspercent + "% - " + progresstatus)
|
.setContentText(progresspercent + "% - " + progresstatus)
|
||||||
|
@ -696,7 +556,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
bolusprogressThread.start();
|
bolusprogressThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class DismissThread extends Thread {
|
private class DismissThread extends Thread {
|
||||||
private final int notificationID;
|
private final int notificationID;
|
||||||
private final int seconds;
|
private final int seconds;
|
||||||
|
@ -730,7 +589,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initiateAction(Context context, String actionstring) {
|
public static void initiateAction(Context context, @NotNull String actionstring) {
|
||||||
Intent intent = new Intent(context, ListenerService.class);
|
Intent intent = new Intent(context, ListenerService.class);
|
||||||
intent.putExtra("actionstring", actionstring);
|
intent.putExtra("actionstring", actionstring);
|
||||||
intent.setAction(ACTION_INITIATE_ACTION);
|
intent.setAction(ACTION_INITIATE_ACTION);
|
||||||
|
@ -753,20 +612,8 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
public void onConnected(Bundle bundle) {
|
public void onConnected(Bundle bundle) {
|
||||||
// Log.d(TAG, logPrefix + "onConnected call requestData");
|
// Log.d(TAG, logPrefix + "onConnected call requestData");
|
||||||
|
|
||||||
CapabilityApi.CapabilityListener capabilityListener = new CapabilityApi.CapabilityListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
|
|
||||||
updatePhoneSyncBgsCapability(capabilityInfo);
|
|
||||||
Log.d(TAG, logPrefix + "onConnected onCapabilityChanged mPhoneNodeID:" + mPhoneNodeId
|
|
||||||
+ ", Capability: " + capabilityInfo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Wearable.CapabilityApi.addCapabilityListener(googleApiClient, capabilityListener, CAPABILITY_PHONE_APP);
|
|
||||||
|
|
||||||
Wearable.ChannelApi.addListener(googleApiClient, this);
|
Wearable.ChannelApi.addListener(googleApiClient, this);
|
||||||
requestData();
|
// requestData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -779,28 +626,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setLocalNodeName() {
|
|
||||||
forceGoogleApiConnect();
|
|
||||||
PendingResult<NodeApi.GetLocalNodeResult> result = Wearable.NodeApi.getLocalNode(googleApiClient);
|
|
||||||
result.setResultCallback(new ResultCallback<NodeApi.GetLocalNodeResult>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResult(NodeApi.GetLocalNodeResult getLocalNodeResult) {
|
|
||||||
if (!getLocalNodeResult.getStatus().isSuccess()) {
|
|
||||||
Log.e(TAG, "ERROR: failed to getLocalNode Status="
|
|
||||||
+ getLocalNodeResult.getStatus().getStatusMessage());
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "getLocalNode Status=: " + getLocalNodeResult.getStatus().getStatusMessage());
|
|
||||||
Node getnode = getLocalNodeResult.getNode();
|
|
||||||
localnode = getnode != null ? getnode.getDisplayName() + "|" + getnode.getId() : "";
|
|
||||||
Log.d(TAG, "setLocalNodeName. localnode=" + localnode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
|
@ -5,6 +5,8 @@ import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import preference.WearPreferenceActivity;
|
import preference.WearPreferenceActivity;
|
||||||
|
|
||||||
|
@ -14,21 +16,15 @@ public class AAPSPreferences extends WearPreferenceActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
ViewGroup view = (ViewGroup)getWindow().getDecorView();
|
ViewGroup view = (ViewGroup) getWindow().getDecorView();
|
||||||
removeBackgroundRecursively(view);
|
removeBackgroundRecursively(view);
|
||||||
view.setBackground(getResources().getDrawable(R.drawable.settings_background));
|
view.setBackground(ContextCompat.getDrawable(this, R.drawable.settings_background));
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause(){
|
|
||||||
super.onPause();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeBackgroundRecursively(View parent) {
|
void removeBackgroundRecursively(View parent) {
|
||||||
if (parent instanceof ViewGroup) {
|
if (parent instanceof ViewGroup) {
|
||||||
ViewGroup group = (ViewGroup)parent;
|
ViewGroup group = (ViewGroup) parent;
|
||||||
for (int i = 0; i < group.getChildCount(); i++) {
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
removeBackgroundRecursively(group.getChildAt(i));
|
removeBackgroundRecursively(group.getChildAt(i));
|
||||||
}
|
}
|
||||||
|
@ -36,5 +32,4 @@ public class AAPSPreferences extends WearPreferenceActivity {
|
||||||
parent.setBackground(null);
|
parent.setBackground(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import preference.WearPreferenceActivity;
|
import preference.WearPreferenceActivity;
|
||||||
|
|
||||||
|
@ -14,14 +17,14 @@ public class ConfigurationActivity extends WearPreferenceActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setTitle("Watchface");
|
setTitle("Watchface");
|
||||||
String configFileName=getIntent().getAction();
|
String configFileName = getIntent().getAction();
|
||||||
int resXmlId = getResources().getIdentifier(configFileName, "xml", getApplicationContext().getPackageName());
|
int resXmlId = getResources().getIdentifier(configFileName, "xml", getApplicationContext().getPackageName());
|
||||||
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()",configFileName);
|
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()", configFileName);
|
||||||
Log.d("ConfigurationActivity::onCreate --->> resXmlId",String.valueOf(resXmlId));
|
Log.d("ConfigurationActivity::onCreate --->> resXmlId", String.valueOf(resXmlId));
|
||||||
addPreferencesFromResource(resXmlId);
|
addPreferencesFromResource(resXmlId);
|
||||||
ViewGroup view = (ViewGroup) getWindow().getDecorView();
|
ViewGroup view = (ViewGroup) getWindow().getDecorView();
|
||||||
removeBackgroundRecursively(view);
|
removeBackgroundRecursively(view);
|
||||||
view.setBackground(getResources().getDrawable(R.drawable.settings_background));
|
view.setBackground(ContextCompat.getDrawable(this, R.drawable.settings_background));
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,5 +44,4 @@ public class ConfigurationActivity extends WearPreferenceActivity {
|
||||||
parent.setBackground(null);
|
parent.setBackground(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.interaction
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.wear.tiles.TileService
|
||||||
|
import preference.WearPreferenceActivity
|
||||||
|
import info.nightscout.androidaps.tile.ActionsTileService
|
||||||
|
import info.nightscout.androidaps.tile.TempTargetTileService
|
||||||
|
|
||||||
|
var TAG = "ASTAG-config"
|
||||||
|
|
||||||
|
class TileConfigurationActivity : WearPreferenceActivity() {
|
||||||
|
|
||||||
|
private var configFileName: String? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
title = "Tile"
|
||||||
|
configFileName = intent.action
|
||||||
|
val resXmlId = resources.getIdentifier(configFileName, "xml", applicationContext.packageName)
|
||||||
|
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()", configFileName!!)
|
||||||
|
Log.d("ConfigurationActivity::onCreate --->> resXmlId", resXmlId.toString())
|
||||||
|
addPreferencesFromResource(resXmlId)
|
||||||
|
val view = window.decorView as ViewGroup
|
||||||
|
view.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
// Note that TileService updates are hard limited to once every 20 seconds.
|
||||||
|
if (configFileName === "tile_configuration_activity") {
|
||||||
|
Log.i(TAG, "onDestroy a: requestUpdate!!")
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(ActionsTileService::class.java)
|
||||||
|
} else if (configFileName === "tile_configuration_tempt") {
|
||||||
|
Log.i(TAG, "onDestroy tt: requestUpdate!!")
|
||||||
|
TileService.getUpdater(this)
|
||||||
|
.requestUpdate(TempTargetTileService::class.java)
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "onDestroy : NO tile service available for $configFileName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,12 +103,9 @@ public class AcceptActivity extends ViewSelectorActivity {
|
||||||
} else {
|
} else {
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
ListenerService.confirmAction(AcceptActivity.this, actionstring);
|
||||||
public void onClick(View v) {
|
finishAffinity();
|
||||||
ListenerService.confirmAction(AcceptActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.interaction.actions
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import info.nightscout.androidaps.data.ListenerService
|
||||||
|
|
||||||
|
const val TAG = "QuickWizard"
|
||||||
|
|
||||||
|
class BackgroundActionActivity : Activity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val actionString = intent.extras?.getString("actionString")
|
||||||
|
Log.i(TAG, "QuickWizardActivity.onCreate: actionString=$actionString")
|
||||||
|
if (actionString != null) {
|
||||||
|
ListenerService.initiateAction(this, actionString)
|
||||||
|
val message = intent.extras?.getString("message")
|
||||||
|
if (message != null) {
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "BackgroundActionActivity.onCreate extras 'actionString' required")
|
||||||
|
}
|
||||||
|
finishAffinity()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -14,19 +16,17 @@ import info.nightscout.androidaps.data.ListenerService;
|
||||||
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
import info.nightscout.shared.SafeParse;
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 09/02/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BolusActivity extends ViewSelectorActivity {
|
public class BolusActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
PlusMinusEditText editCarbs;
|
|
||||||
PlusMinusEditText editInsulin;
|
PlusMinusEditText editInsulin;
|
||||||
|
float maxBolus;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,11 +35,10 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount(int arg0) {
|
public int getColumnCount(int arg0) {
|
||||||
return 3;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,35 +55,20 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
if (editInsulin != null) {
|
if (editInsulin != null) {
|
||||||
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
||||||
}
|
}
|
||||||
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 30d, 0.1d, new DecimalFormat("#0.0"), false);
|
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxBolus, 0.1d, new DecimalFormat("#0.0"),false);
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
|
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
return view;
|
return view;
|
||||||
} else if (col == 1) {
|
|
||||||
final View view = getInflatedPlusMinusView(container);
|
|
||||||
double def = 0;
|
|
||||||
if (editCarbs != null) {
|
|
||||||
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
|
||||||
}
|
|
||||||
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
|
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
|
||||||
container.addView(view);
|
|
||||||
return view;
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
|
||||||
public void onClick(View v) {
|
+ " 0"; // Zero carbs
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
ListenerService.initiateAction(BolusActivity.this, actionstring);
|
||||||
// (you have to swipe past them anyways - but still)
|
confirmAction(BolusActivity.this, R.string.action_bolus_confirmation);
|
||||||
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
|
finishAffinity();
|
||||||
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
|
|
||||||
ListenerService.initiateAction(BolusActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
@ -93,8 +77,6 @@ public class BolusActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyItem(ViewGroup container, int row, int col, Object view) {
|
public void destroyItem(ViewGroup container, int row, int col, Object view) {
|
||||||
// Handle this to get the data before the view is destroyed?
|
|
||||||
// Object should still be kept by this, just setup for reinit?
|
|
||||||
container.removeView((View) view);
|
container.removeView((View) view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,18 +89,15 @@ public class CPPActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
//check if it can happen that the fagment is never created that hold data?
|
||||||
public void onClick(View v) {
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
String actionstring = "cppset " + SafeParse.stringToInt(editTimeshift.editText.getText().toString())
|
||||||
// (you have to swipe past them anyways - but still)
|
+ " " + SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
||||||
|
ListenerService.initiateAction(CPPActivity.this, actionstring);
|
||||||
String actionstring = "cppset " + SafeParse.stringToInt(editTimeshift.editText.getText().toString())
|
confirmAction(CPPActivity.this, R.string.action_cpp_confirmation);
|
||||||
+ " " + SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
finishAffinity();
|
||||||
ListenerService.initiateAction(CPPActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.wearable.view.GridPagerAdapter;
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -23,11 +25,14 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
PlusMinusEditText editCarbs;
|
PlusMinusEditText editCarbs;
|
||||||
PlusMinusEditText editStartTime;
|
PlusMinusEditText editStartTime;
|
||||||
PlusMinusEditText editDuration;
|
PlusMinusEditText editDuration;
|
||||||
|
int maxCarbs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,7 +61,7 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
if (editCarbs != null) {
|
if (editCarbs != null) {
|
||||||
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
||||||
}
|
}
|
||||||
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), true);
|
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"), true);
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
view.requestFocus();
|
view.requestFocus();
|
||||||
|
@ -85,19 +90,18 @@ public class ECarbActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
|
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fagment is never created that hold data?
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
|
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
||||||
|
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
|
||||||
|
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
|
||||||
|
ListenerService.initiateAction(ECarbActivity.this, actionstring);
|
||||||
|
confirmAction(ECarbActivity.this, R.string.action_ecarb_confirmation);
|
||||||
|
finishAffinity();
|
||||||
|
|
||||||
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
|
||||||
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
|
|
||||||
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
|
|
||||||
ListenerService.initiateAction(ECarbActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -63,17 +63,14 @@ public class FillActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
|
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
//check if it can happen that the fagment is never created that hold data?
|
||||||
// (you have to swipe past them anyways - but still)
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
String actionstring = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
String actionstring = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
||||||
ListenerService.initiateAction(FillActivity.this, actionstring);
|
ListenerService.initiateAction(FillActivity.this, actionstring);
|
||||||
|
confirmAction(FillActivity.this, R.string.action_fill_confirmation);
|
||||||
finishAffinity();
|
finishAffinity();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -8,7 +8,6 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
@ -32,6 +31,7 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
|
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
@ -61,8 +61,6 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
if (col == 0) {
|
if (col == 0) {
|
||||||
final View view = getInflatedPlusMinusView(container);
|
final View view = getInflatedPlusMinusView(container);
|
||||||
final TextView textView = view.findViewById(R.id.label);
|
|
||||||
textView.setText("duration");
|
|
||||||
if (time == null) {
|
if (time == null) {
|
||||||
time = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 60d, 0d, 24 * 60d, 5d, new DecimalFormat("0"), false);
|
time = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 60d, 0d, 24 * 60d, 5d, new DecimalFormat("0"), false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,22 +116,19 @@ public class TempTargetActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
//check if it can happen that the fagment is never created that hold data?
|
||||||
public void onClick(View v) {
|
// (you have to swipe past them anyways - but still)
|
||||||
|
|
||||||
//check if it can happen that the fagment is never created that hold data?
|
String actionstring = "temptarget"
|
||||||
// (you have to swipe past them anyways - but still)
|
+ " " + isMGDL
|
||||||
|
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
|
||||||
|
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
|
||||||
|
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
|
||||||
|
|
||||||
String actionstring = "temptarget "
|
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
|
||||||
+ " " + isMGDL
|
confirmAction(TempTargetActivity.this, R.string.action_tempt_confirmation);
|
||||||
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
|
finishAffinity();
|
||||||
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
|
|
||||||
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
|
|
||||||
|
|
||||||
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.wearable.view.GridPagerAdapter;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.ListenerService;
|
||||||
|
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
|
||||||
|
import info.nightscout.shared.SafeParse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adrian on 09/02/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TreatmentActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
|
PlusMinusEditText editCarbs;
|
||||||
|
PlusMinusEditText editInsulin;
|
||||||
|
int maxCarbs;
|
||||||
|
float maxBolus;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
|
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class MyGridViewPagerAdapter extends GridPagerAdapter {
|
||||||
|
@Override
|
||||||
|
public int getColumnCount(int arg0) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object instantiateItem(ViewGroup container, int row, int col) {
|
||||||
|
|
||||||
|
if (col == 0) {
|
||||||
|
final View view = getInflatedPlusMinusView(container);
|
||||||
|
double def = 0;
|
||||||
|
if (editInsulin != null) {
|
||||||
|
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
|
||||||
|
}
|
||||||
|
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double) maxBolus, 0.1d, new DecimalFormat("#0.0"),false);
|
||||||
|
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
|
||||||
|
container.addView(view);
|
||||||
|
view.requestFocus();
|
||||||
|
return view;
|
||||||
|
} else if (col == 1) {
|
||||||
|
final View view = getInflatedPlusMinusView(container);
|
||||||
|
double def = 0;
|
||||||
|
if (editCarbs != null) {
|
||||||
|
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
||||||
|
}
|
||||||
|
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"),false);
|
||||||
|
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
||||||
|
container.addView(view);
|
||||||
|
return view;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
|
//check if it can happen that the fagment is never created that hold data?
|
||||||
|
// (you have to swipe past them anyways - but still)
|
||||||
|
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
|
||||||
|
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
|
||||||
|
ListenerService.initiateAction(TreatmentActivity.this, actionstring);
|
||||||
|
confirmAction(TreatmentActivity.this, R.string.action_treatment_confirmation);
|
||||||
|
finishAffinity();
|
||||||
|
});
|
||||||
|
container.addView(view);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyItem(ViewGroup container, int row, int col, Object view) {
|
||||||
|
// Handle this to get the data before the view is destroyed?
|
||||||
|
// Object should still be kept by this, just setup for reinit?
|
||||||
|
container.removeView((View) view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isViewFromObject(View view, Object object) {
|
||||||
|
return view == object;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package info.nightscout.androidaps.interaction.actions;
|
package info.nightscout.androidaps.interaction.actions;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
@ -11,6 +12,7 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.wear.widget.CurvedTextView;
|
import androidx.wear.widget.CurvedTextView;
|
||||||
|
|
||||||
|
@ -62,9 +64,9 @@ public class ViewSelectorActivity extends Activity {
|
||||||
private void setTitleBasedOnScreenShape() {
|
private void setTitleBasedOnScreenShape() {
|
||||||
// intents can inject dynamic titles, otherwise we'll use the default
|
// intents can inject dynamic titles, otherwise we'll use the default
|
||||||
String title = String.valueOf(getTitle());
|
String title = String.valueOf(getTitle());
|
||||||
if (getIntent().getExtras() != null)
|
if (getIntent().getExtras() != null) {
|
||||||
title = getIntent().getExtras().getString("title", title);
|
title = getIntent().getExtras().getString("title", title);
|
||||||
|
}
|
||||||
CurvedTextView titleViewCurved = findViewById(R.id.title_curved);
|
CurvedTextView titleViewCurved = findViewById(R.id.title_curved);
|
||||||
TextView titleView = findViewById(R.id.title);
|
TextView titleView = findViewById(R.id.title);
|
||||||
if (this.getResources().getConfiguration().isScreenRound()) {
|
if (this.getResources().getConfiguration().isScreenRound()) {
|
||||||
|
@ -96,8 +98,12 @@ public class ViewSelectorActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLabelToPlusMinusView(View view, String labelText) {
|
void setLabelToPlusMinusView(View view, String labelText) {
|
||||||
final TextView textView = view.findViewById(R.id.label);
|
final TextView textView = view.findViewById(R.id.label);
|
||||||
textView.setText(labelText);
|
textView.setText(labelText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void confirmAction(Context context, int text) {
|
||||||
|
Toast.makeText(context, getString(text), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
PlusMinusEditText editPercentage;
|
PlusMinusEditText editPercentage;
|
||||||
|
|
||||||
boolean hasPercentage;
|
boolean hasPercentage;
|
||||||
|
int percentage;
|
||||||
|
int maxCarbs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -33,6 +35,8 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
setAdapter(new MyGridViewPagerAdapter());
|
setAdapter(new MyGridViewPagerAdapter());
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
hasPercentage = sp.getBoolean("wizardpercentage", false);
|
hasPercentage = sp.getBoolean("wizardpercentage", false);
|
||||||
|
percentage = sp.getInt(getString(R.string.key_boluswizard_percentage), 100);
|
||||||
|
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,10 +62,10 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
if (col == 0) {
|
if (col == 0) {
|
||||||
final View view = getInflatedPlusMinusView(container);
|
final View view = getInflatedPlusMinusView(container);
|
||||||
if (editCarbs == null) {
|
if (editCarbs == null) {
|
||||||
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 0d, 0d, 150d, 1d, new DecimalFormat("0"), false);
|
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 0d, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"), false);
|
||||||
} else {
|
} else {
|
||||||
double def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
double def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
|
||||||
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
|
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"),false);
|
||||||
}
|
}
|
||||||
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
|
@ -70,7 +74,7 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
} else if (col == 1 && hasPercentage) {
|
} else if (col == 1 && hasPercentage) {
|
||||||
final View view = getInflatedPlusMinusView(container);
|
final View view = getInflatedPlusMinusView(container);
|
||||||
if (editPercentage == null) {
|
if (editPercentage == null) {
|
||||||
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 100d, 50d, 150d, 1d, new DecimalFormat("0"), false);
|
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, (double)percentage, 50d, 150d, 1d, new DecimalFormat("0"), false);
|
||||||
} else {
|
} else {
|
||||||
double def = SafeParse.stringToDouble(editPercentage.editText.getText().toString());
|
double def = SafeParse.stringToDouble(editPercentage.editText.getText().toString());
|
||||||
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 50d, 150d, 1d, new DecimalFormat("0"), false);
|
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 50d, 150d, 1d, new DecimalFormat("0"), false);
|
||||||
|
@ -82,23 +86,16 @@ public class WizardActivity extends ViewSelectorActivity {
|
||||||
|
|
||||||
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
|
||||||
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
|
||||||
confirmbutton.setOnClickListener(new View.OnClickListener() {
|
confirmbutton.setOnClickListener((View v) -> {
|
||||||
@Override
|
if (editPercentage != null) {
|
||||||
public void onClick(View v) {
|
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
||||||
|
|
||||||
// check if it can happen that the fragment is never created that hold data?
|
|
||||||
// (you have to swipe past them anyways - but still)
|
|
||||||
|
|
||||||
int percentage = 100;
|
|
||||||
|
|
||||||
if (editPercentage != null)
|
|
||||||
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
|
|
||||||
|
|
||||||
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
|
||||||
+ " " + percentage;
|
|
||||||
ListenerService.initiateAction(WizardActivity.this, actionstring);
|
|
||||||
finishAffinity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
|
||||||
|
+ " " + percentage;
|
||||||
|
ListenerService.initiateAction(WizardActivity.this, actionstring);
|
||||||
|
confirmAction(WizardActivity.this, R.string.action_wizard_confirmation);
|
||||||
|
finishAffinity();
|
||||||
});
|
});
|
||||||
container.addView(view);
|
container.addView(view);
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import java.util.List;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ListenerService;
|
import info.nightscout.androidaps.data.ListenerService;
|
||||||
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
import info.nightscout.androidaps.interaction.AAPSPreferences;
|
||||||
import info.nightscout.androidaps.interaction.actions.BolusActivity;
|
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
|
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
|
||||||
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
import info.nightscout.androidaps.interaction.actions.WizardActivity;
|
||||||
|
@ -49,7 +49,7 @@ public class MainMenuActivity extends MenuListActivity {
|
||||||
|
|
||||||
if (showWizard) menuItems.add(new MenuItem(R.drawable.ic_calculator, getString(R.string.menu_wizard)));
|
if (showWizard) menuItems.add(new MenuItem(R.drawable.ic_calculator, getString(R.string.menu_wizard)));
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_e_carbs, getString(R.string.menu_ecarb)));
|
menuItems.add(new MenuItem(R.drawable.ic_e_carbs, getString(R.string.menu_ecarb)));
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_bolus, getString(R.string.menu_bolus)));
|
menuItems.add(new MenuItem(R.drawable.ic_treatment, getString(R.string.menu_treatment)));
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_temptarget, getString(R.string.menu_tempt)));
|
menuItems.add(new MenuItem(R.drawable.ic_temptarget, getString(R.string.menu_tempt)));
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)));
|
menuItems.add(new MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)));
|
||||||
menuItems.add(new MenuItem(R.drawable.ic_status, getString(R.string.menu_status)));
|
menuItems.add(new MenuItem(R.drawable.ic_status, getString(R.string.menu_status)));
|
||||||
|
@ -73,8 +73,8 @@ public class MainMenuActivity extends MenuListActivity {
|
||||||
intent = new Intent(this, TempTargetActivity.class);
|
intent = new Intent(this, TempTargetActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
this.startActivity(intent);
|
this.startActivity(intent);
|
||||||
} else if (getString(R.string.menu_bolus).equals(action)) {
|
} else if (getString(R.string.menu_treatment).equals(action)) {
|
||||||
intent = new Intent(this, BolusActivity.class);
|
intent = new Intent(this, TreatmentActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
this.startActivity(intent);
|
this.startActivity(intent);
|
||||||
} else if (getString(R.string.menu_wizard).equals(action)) {
|
} else if (getString(R.string.menu_wizard).equals(action)) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
|
||||||
Double minValue = 0d;
|
Double minValue = 0d;
|
||||||
Double maxValue = 1d;
|
Double maxValue = 1d;
|
||||||
Double step = 1d;
|
Double step = 1d;
|
||||||
NumberFormat formater;
|
NumberFormat formatter;
|
||||||
boolean allowZero = false;
|
boolean allowZero = false;
|
||||||
boolean roundRobin;
|
boolean roundRobin;
|
||||||
|
|
||||||
|
@ -74,11 +74,11 @@ public class PlusMinusEditText implements View.OnKeyListener,
|
||||||
private static final int MSG_INC = 0;
|
private static final int MSG_INC = 0;
|
||||||
private static final int MSG_DEC = 1;
|
private static final int MSG_DEC = 1;
|
||||||
|
|
||||||
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) {
|
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero) {
|
||||||
this(view, editTextID, plusID, minusID, initValue, minValue, maxValue, step, formater, allowZero, false);
|
this(view, editTextID, plusID, minusID, initValue, minValue, maxValue, step, formatter, allowZero, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, boolean roundRobin) {
|
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero, boolean roundRobin) {
|
||||||
editText = view.findViewById(editTextID);
|
editText = view.findViewById(editTextID);
|
||||||
minusImage = view.findViewById(minusID);
|
minusImage = view.findViewById(minusID);
|
||||||
plusImage = view.findViewById(plusID);
|
plusImage = view.findViewById(plusID);
|
||||||
|
@ -87,7 +87,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
|
||||||
this.minValue = minValue;
|
this.minValue = minValue;
|
||||||
this.maxValue = maxValue;
|
this.maxValue = maxValue;
|
||||||
this.step = step;
|
this.step = step;
|
||||||
this.formater = formater;
|
this.formatter = formatter;
|
||||||
this.allowZero = allowZero;
|
this.allowZero = allowZero;
|
||||||
this.roundRobin = roundRobin;
|
this.roundRobin = roundRobin;
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
|
||||||
if (value == 0d && !allowZero)
|
if (value == 0d && !allowZero)
|
||||||
editText.setText("");
|
editText.setText("");
|
||||||
else
|
else
|
||||||
editText.setText(formater.format(value));
|
editText.setText(formatter.format(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startUpdating(boolean inc) {
|
private void startUpdating(boolean inc) {
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.interaction.actions.BolusActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.TreatmentActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.ECarbActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.WizardActivity
|
||||||
|
|
||||||
|
object ActionSource : StaticTileSource() {
|
||||||
|
|
||||||
|
override val preferencePrefix = "tile_action_"
|
||||||
|
|
||||||
|
override fun getActions(resources: Resources): List<StaticAction> {
|
||||||
|
return listOf(
|
||||||
|
StaticAction(
|
||||||
|
settingName = "wizard",
|
||||||
|
buttonText = resources.getString(R.string.menu_wizard_short),
|
||||||
|
iconRes = R.drawable.ic_calculator_green,
|
||||||
|
activityClass = WizardActivity::class.java.name,
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "treatment",
|
||||||
|
buttonText = resources.getString(R.string.menu_treatment_short),
|
||||||
|
iconRes = R.drawable.ic_bolus_carbs,
|
||||||
|
activityClass = TreatmentActivity::class.java.name,
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "bolus",
|
||||||
|
buttonText = resources.getString(R.string.action_insulin),
|
||||||
|
iconRes = R.drawable.ic_bolus,
|
||||||
|
activityClass = BolusActivity::class.java.name,
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "carbs",
|
||||||
|
buttonText = resources.getString(R.string.action_carbs),
|
||||||
|
iconRes = R.drawable.ic_carbs_orange,
|
||||||
|
activityClass = ECarbActivity::class.java.name,
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "temp_target",
|
||||||
|
buttonText = resources.getString(R.string.menu_tempt),
|
||||||
|
iconRes = R.drawable.ic_temptarget_flat,
|
||||||
|
activityClass = TempTargetActivity::class.java.name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResourceReferences(resources: Resources): List<Int> {
|
||||||
|
return getActions(resources).map { it.iconRes }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDefaultConfig(): Map<String, String> {
|
||||||
|
return mapOf(
|
||||||
|
"tile_action_1" to "wizard",
|
||||||
|
"tile_action_2" to "treatment",
|
||||||
|
"tile_action_3" to "carbs",
|
||||||
|
"tile_action_4" to "temp_target"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
class ActionsTileService : TileBase() {
|
||||||
|
override val resourceVersion = "ActionsTileService"
|
||||||
|
override val source = ActionSource
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.google.android.gms.wearable.DataMap
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object QuickWizardSource : TileSource {
|
||||||
|
|
||||||
|
override fun getSelectedActions(context: Context): List<Action> {
|
||||||
|
val quickList = mutableListOf<Action>()
|
||||||
|
val quickMap = getDataMap(context)
|
||||||
|
val sfm = secondsFromMidnight()
|
||||||
|
|
||||||
|
for (quick in quickMap) {
|
||||||
|
val validFrom = quick.getInt("from", 0)
|
||||||
|
val validTo = quick.getInt("to", 0)
|
||||||
|
val isActive = sfm in validFrom..validTo
|
||||||
|
val guid = quick.getString("guid", "")
|
||||||
|
if (isActive && guid != "") {
|
||||||
|
quickList.add(
|
||||||
|
Action(
|
||||||
|
buttonText = quick.getString("button_text", "?"),
|
||||||
|
buttonTextSub = "${quick.getInt("carbs", 0)} g",
|
||||||
|
iconRes = R.drawable.ic_quick_wizard,
|
||||||
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
|
actionString = "quick_wizard $guid",
|
||||||
|
message = context.resources.getString(R.string.action_quick_wizard_confirmation),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Log.i(TAG, "getSelectedActions: active " + quick.getString("button_text", "?") + " guid=" + guid)
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "getSelectedActions: not active " + quick.getString("button_text", "?") + " guid=" + guid)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return quickList
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValidFor(context: Context): Long? {
|
||||||
|
val quickMap = getDataMap(context)
|
||||||
|
if (quickMap.size == 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val sfm = secondsFromMidnight()
|
||||||
|
var validTill = 24 * 60 * 60
|
||||||
|
|
||||||
|
for (quick in quickMap) {
|
||||||
|
val validFrom = quick.getInt("from", 0)
|
||||||
|
val validTo = quick.getInt("to", 0)
|
||||||
|
val isActive = sfm in validFrom..validTo
|
||||||
|
val guid = quick.getString("guid", "")
|
||||||
|
Log.i(TAG, "valid: " + validFrom + "-" + validTo)
|
||||||
|
if (guid != "") {
|
||||||
|
if (isActive && validTill > validTo) {
|
||||||
|
validTill = validTo
|
||||||
|
}
|
||||||
|
if (validFrom > sfm && validTill > validFrom) {
|
||||||
|
validTill = validFrom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val validWithin = 60
|
||||||
|
val delta = (validTill - sfm + validWithin) * 1000L
|
||||||
|
Log.i(TAG, "getValidTill: sfm" + sfm + " till" + validTill + " d=" + delta)
|
||||||
|
return delta
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDataMap(context: Context): ArrayList<DataMap> {
|
||||||
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val key = context.resources.getString(R.string.key_quick_wizard_data_map)
|
||||||
|
if (sharedPrefs.contains(key)) {
|
||||||
|
val rawB64Data: String? = sharedPrefs.getString(key, null)
|
||||||
|
val rawData: ByteArray = Base64.decode(rawB64Data, Base64.DEFAULT)
|
||||||
|
try {
|
||||||
|
val map = DataMap.fromByteArray(rawData)
|
||||||
|
return map.getDataMapArrayList("quick_wizard")
|
||||||
|
|
||||||
|
} catch (ex: IllegalArgumentException) {
|
||||||
|
Log.e(TAG, "getSelectedActions: IllegalArgumentException ", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrayListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun secondsFromMidnight(): Int {
|
||||||
|
val c = Calendar.getInstance()
|
||||||
|
c.set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
c.set(Calendar.MINUTE, 0)
|
||||||
|
c.set(Calendar.SECOND, 0)
|
||||||
|
c.set(Calendar.MILLISECOND, 0)
|
||||||
|
val passed: Long = System.currentTimeMillis() - c.timeInMillis
|
||||||
|
|
||||||
|
return (passed / 1000).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResourceReferences(resources: Resources): List<Int> {
|
||||||
|
return listOf(R.drawable.ic_quick_wizard)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
const val TAG = "QuickWizard"
|
||||||
|
|
||||||
|
class QuickWizardTileService : TileBase() {
|
||||||
|
override val resourceVersion = "QuickWizardTileService"
|
||||||
|
override val source = QuickWizardSource
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.content.res.Resources
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
|
||||||
|
class StaticAction(
|
||||||
|
val settingName: String,
|
||||||
|
buttonText: String,
|
||||||
|
buttonTextSub: String? = null,
|
||||||
|
activityClass: String,
|
||||||
|
@DrawableRes iconRes: Int,
|
||||||
|
actionString: String? = null,
|
||||||
|
message: String? = null,
|
||||||
|
) : Action(buttonText, buttonTextSub, activityClass, iconRes, actionString, message)
|
||||||
|
|
||||||
|
abstract class StaticTileSource : TileSource {
|
||||||
|
|
||||||
|
abstract fun getActions(resources: Resources): List<StaticAction>
|
||||||
|
|
||||||
|
abstract val preferencePrefix: String
|
||||||
|
abstract fun getDefaultConfig(): Map<String, String>
|
||||||
|
|
||||||
|
override fun getSelectedActions(context: Context): List<Action> {
|
||||||
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
setDefaultSettings(sharedPrefs)
|
||||||
|
|
||||||
|
val actionList: MutableList<Action> = mutableListOf()
|
||||||
|
for (i in 1..4) {
|
||||||
|
val action = getActionFromPreference(context.resources, sharedPrefs, i)
|
||||||
|
if (action != null) {
|
||||||
|
actionList.add(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (actionList.isEmpty()) {
|
||||||
|
return getActions(context.resources).take(4)
|
||||||
|
}
|
||||||
|
return actionList
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValidFor(context: Context): Long? = null
|
||||||
|
|
||||||
|
private fun getActionFromPreference(resources: Resources, sharedPrefs: SharedPreferences, index: Int): Action? {
|
||||||
|
val actionPref = sharedPrefs.getString(preferencePrefix + index, "none")
|
||||||
|
return getActions(resources).find { action -> action.settingName == actionPref }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDefaultSettings(sharedPrefs: SharedPreferences) {
|
||||||
|
val defaults = getDefaultConfig()
|
||||||
|
val firstKey = defaults.firstNotNullOf { settings -> settings.key }
|
||||||
|
if (!sharedPrefs.contains(firstKey)) {
|
||||||
|
val editor = sharedPrefs.edit()
|
||||||
|
for ((key, value) in defaults) {
|
||||||
|
editor.putString(key, value)
|
||||||
|
}
|
||||||
|
editor.apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||||
|
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
|
||||||
|
|
||||||
|
object TempTargetSource : StaticTileSource() {
|
||||||
|
|
||||||
|
override val preferencePrefix = "tile_tempt_"
|
||||||
|
|
||||||
|
override fun getActions(resources: Resources): List<StaticAction> {
|
||||||
|
val message = resources.getString(R.string.action_tempt_confirmation)
|
||||||
|
return listOf(
|
||||||
|
StaticAction(
|
||||||
|
settingName = "activity",
|
||||||
|
buttonText = resources.getString(R.string.temp_target_activity),
|
||||||
|
iconRes = R.drawable.ic_target_activity,
|
||||||
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
|
message = message,
|
||||||
|
// actionString = "temptarget false 90 8.0 8.0",
|
||||||
|
actionString = "temptarget preset activity",
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "eating_soon",
|
||||||
|
buttonText = resources.getString(R.string.temp_target_eating_soon),
|
||||||
|
iconRes = R.drawable.ic_target_eatingsoon,
|
||||||
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
|
message = message,
|
||||||
|
// actionString = "temptarget false 45 4.5 4.5",
|
||||||
|
actionString = "temptarget preset eating",
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "hypo",
|
||||||
|
buttonText = resources.getString(R.string.temp_target_hypo),
|
||||||
|
iconRes = R.drawable.ic_target_hypo,
|
||||||
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
|
message = message,
|
||||||
|
// actionString = "temptarget false 45 7.0 7.0",
|
||||||
|
actionString = "temptarget preset hypo",
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "manual",
|
||||||
|
buttonText = resources.getString(R.string.temp_target_manual),
|
||||||
|
iconRes = R.drawable.ic_target_manual,
|
||||||
|
activityClass = TempTargetActivity::class.java.name,
|
||||||
|
),
|
||||||
|
StaticAction(
|
||||||
|
settingName = "cancel",
|
||||||
|
buttonText = resources.getString(R.string.generic_cancel),
|
||||||
|
iconRes = R.drawable.ic_target_cancel,
|
||||||
|
activityClass = BackgroundActionActivity::class.java.name,
|
||||||
|
message = message,
|
||||||
|
actionString = "temptarget cancel",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResourceReferences(resources: Resources): List<Int> {
|
||||||
|
return getActions(resources).map { it.iconRes }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDefaultConfig(): Map<String, String> {
|
||||||
|
return mapOf(
|
||||||
|
"tile_tempt_1" to "activity",
|
||||||
|
"tile_tempt_2" to "eating_soon",
|
||||||
|
"tile_tempt_3" to "hypo",
|
||||||
|
"tile_tempt_4" to "manual"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
class TempTargetTileService : TileBase() {
|
||||||
|
|
||||||
|
override val resourceVersion = "TempTargetTileService"
|
||||||
|
override val source = TempTargetSource;
|
||||||
|
|
||||||
|
}
|
297
wear/src/main/java/info/nightscout/androidaps/tile/TileBase.kt
Normal file
297
wear/src/main/java/info/nightscout/androidaps/tile/TileBase.kt
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
package info.nightscout.androidaps.tile
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.wear.tiles.ActionBuilders
|
||||||
|
import androidx.wear.tiles.ColorBuilders.argb
|
||||||
|
import androidx.wear.tiles.DeviceParametersBuilders.SCREEN_SHAPE_ROUND
|
||||||
|
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
|
||||||
|
import androidx.wear.tiles.DimensionBuilders.SpProp
|
||||||
|
import androidx.wear.tiles.DimensionBuilders.dp
|
||||||
|
import androidx.wear.tiles.DimensionBuilders.sp
|
||||||
|
import androidx.wear.tiles.LayoutElementBuilders.*
|
||||||
|
import androidx.wear.tiles.ModifiersBuilders.Background
|
||||||
|
import androidx.wear.tiles.ModifiersBuilders.Clickable
|
||||||
|
import androidx.wear.tiles.ModifiersBuilders.Corner
|
||||||
|
import androidx.wear.tiles.ModifiersBuilders.Modifiers
|
||||||
|
import androidx.wear.tiles.ModifiersBuilders.Semantics
|
||||||
|
import androidx.wear.tiles.RequestBuilders
|
||||||
|
import androidx.wear.tiles.RequestBuilders.ResourcesRequest
|
||||||
|
import androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId
|
||||||
|
import androidx.wear.tiles.ResourceBuilders.ImageResource
|
||||||
|
import androidx.wear.tiles.ResourceBuilders.Resources
|
||||||
|
import androidx.wear.tiles.TileBuilders.Tile
|
||||||
|
import androidx.wear.tiles.TileService
|
||||||
|
import androidx.wear.tiles.TimelineBuilders.Timeline
|
||||||
|
import androidx.wear.tiles.TimelineBuilders.TimelineEntry
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.guava.future
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
private const val SPACING_ACTIONS = 3f
|
||||||
|
private const val ICON_SIZE_FRACTION = 0.4f // Percentage of button diameter
|
||||||
|
private const val BUTTON_COLOR = R.color.gray_850
|
||||||
|
private const val LARGE_SCREEN_WIDTH_DP = 210
|
||||||
|
|
||||||
|
interface TileSource {
|
||||||
|
|
||||||
|
fun getResourceReferences(resources: android.content.res.Resources): List<Int>
|
||||||
|
fun getSelectedActions(context: Context): List<Action>
|
||||||
|
fun getValidFor(context: Context): Long?
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Action(
|
||||||
|
val buttonText: String,
|
||||||
|
val buttonTextSub: String? = null,
|
||||||
|
val activityClass: String,
|
||||||
|
@DrawableRes val iconRes: Int,
|
||||||
|
val actionString: String? = null,
|
||||||
|
val message: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class WearControl {
|
||||||
|
NO_DATA, ENABLED, DISABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TileBase : TileService() {
|
||||||
|
|
||||||
|
abstract val resourceVersion: String
|
||||||
|
abstract val source: TileSource
|
||||||
|
|
||||||
|
private val serviceJob = Job()
|
||||||
|
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
||||||
|
|
||||||
|
override fun onTileRequest(
|
||||||
|
requestParams: RequestBuilders.TileRequest
|
||||||
|
): ListenableFuture<Tile> = serviceScope.future {
|
||||||
|
val actionsSelected = getSelectedActions()
|
||||||
|
val wearControl = getWearControl()
|
||||||
|
val tile = Tile.Builder()
|
||||||
|
.setResourcesVersion(resourceVersion)
|
||||||
|
.setTimeline(
|
||||||
|
Timeline.Builder().addTimelineEntry(
|
||||||
|
TimelineEntry.Builder().setLayout(
|
||||||
|
Layout.Builder().setRoot(layout(wearControl, actionsSelected, requestParams.deviceParameters!!)).build()
|
||||||
|
).build()
|
||||||
|
).build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val validFor = validFor()
|
||||||
|
if (validFor != null) {
|
||||||
|
tile.setFreshnessIntervalMillis(validFor)
|
||||||
|
}
|
||||||
|
tile.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSelectedActions(): List<Action> {
|
||||||
|
// TODO check why thi scan not be don in scope of the coroutine
|
||||||
|
return source.getSelectedActions(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validFor(): Long? {
|
||||||
|
return source.getValidFor(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
|
override fun onResourcesRequest(
|
||||||
|
requestParams: ResourcesRequest
|
||||||
|
): ListenableFuture<Resources> = serviceScope.future {
|
||||||
|
Resources.Builder()
|
||||||
|
.setVersion(resourceVersion)
|
||||||
|
.apply {
|
||||||
|
source.getResourceReferences(resources).forEach { resourceId ->
|
||||||
|
addIdToImageMapping(
|
||||||
|
resourceId.toString(),
|
||||||
|
ImageResource.Builder()
|
||||||
|
.setAndroidResourceByResId(
|
||||||
|
AndroidImageResourceByResId.Builder()
|
||||||
|
.setResourceId(resourceId)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun layout(wearControl: WearControl, actions: List<Action>, deviceParameters: DeviceParameters): LayoutElement {
|
||||||
|
if (wearControl == WearControl.DISABLED) {
|
||||||
|
return Text.Builder()
|
||||||
|
.setText(resources.getString(R.string.wear_control_not_enabled))
|
||||||
|
.build()
|
||||||
|
} else if (wearControl == WearControl.NO_DATA) {
|
||||||
|
return Text.Builder()
|
||||||
|
.setText(resources.getString(R.string.wear_control_no_data))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
if (actions.isNotEmpty()) {
|
||||||
|
with(Column.Builder()) {
|
||||||
|
if (actions.size == 1 || actions.size == 3) {
|
||||||
|
addContent(addRowSingle(actions[0], deviceParameters))
|
||||||
|
}
|
||||||
|
if (actions.size == 4 || actions.size == 2) {
|
||||||
|
addContent(addRowDouble(actions[0], actions[1], deviceParameters))
|
||||||
|
}
|
||||||
|
if (actions.size == 3) {
|
||||||
|
addContent(addRowDouble(actions[1], actions[2], deviceParameters))
|
||||||
|
}
|
||||||
|
if (actions.size == 4) {
|
||||||
|
addContent(Spacer.Builder().setHeight(dp(SPACING_ACTIONS)).build())
|
||||||
|
addContent(addRowDouble(actions[2], actions[3], deviceParameters))
|
||||||
|
}
|
||||||
|
return build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Text.Builder()
|
||||||
|
.setText(resources.getString(R.string.tile_no_config))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRowSingle(action: Action, deviceParameters: DeviceParameters): LayoutElement =
|
||||||
|
Row.Builder()
|
||||||
|
.addContent(action(action, deviceParameters))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private fun addRowDouble(action1: Action, action2: Action, deviceParameters: DeviceParameters): LayoutElement =
|
||||||
|
Row.Builder()
|
||||||
|
.addContent(action(action1, deviceParameters))
|
||||||
|
.addContent(Spacer.Builder().setWidth(dp(SPACING_ACTIONS)).build())
|
||||||
|
.addContent(action(action2, deviceParameters))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private fun doAction(action: Action): ActionBuilders.Action {
|
||||||
|
val builder = ActionBuilders.AndroidActivity.Builder()
|
||||||
|
.setClassName(action.activityClass)
|
||||||
|
.setPackageName(this.packageName)
|
||||||
|
if (action.actionString != null) {
|
||||||
|
val actionString = ActionBuilders.AndroidStringExtra.Builder().setValue(action.actionString).build()
|
||||||
|
builder.addKeyToExtraMapping("actionString", actionString)
|
||||||
|
}
|
||||||
|
if (action.message != null) {
|
||||||
|
val message = ActionBuilders.AndroidStringExtra.Builder().setValue(action.message).build()
|
||||||
|
builder.addKeyToExtraMapping("message", message)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionBuilders.LaunchAction.Builder()
|
||||||
|
.setAndroidActivity(builder.build())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun action(action: Action, deviceParameters: DeviceParameters): LayoutElement {
|
||||||
|
val circleDiameter = circleDiameter(deviceParameters)
|
||||||
|
val text = action.buttonText
|
||||||
|
val textSub = action.buttonTextSub
|
||||||
|
return Box.Builder()
|
||||||
|
.setWidth(dp(circleDiameter))
|
||||||
|
.setHeight(dp(circleDiameter))
|
||||||
|
.setModifiers(
|
||||||
|
Modifiers.Builder()
|
||||||
|
.setBackground(
|
||||||
|
Background.Builder()
|
||||||
|
.setColor(
|
||||||
|
argb(ContextCompat.getColor(baseContext, BUTTON_COLOR))
|
||||||
|
)
|
||||||
|
.setCorner(
|
||||||
|
Corner.Builder().setRadius(dp(circleDiameter / 2)).build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.setSemantics(
|
||||||
|
Semantics.Builder()
|
||||||
|
.setContentDescription("$text $textSub")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.setClickable(
|
||||||
|
Clickable.Builder()
|
||||||
|
.setOnClick(doAction(action))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.addContent(addTextContent(action, deviceParameters))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addTextContent(action: Action, deviceParameters: DeviceParameters): LayoutElement {
|
||||||
|
val circleDiameter = circleDiameter(deviceParameters)
|
||||||
|
val iconSize = dp(circleDiameter * ICON_SIZE_FRACTION)
|
||||||
|
val text = action.buttonText
|
||||||
|
val textSub = action.buttonTextSub
|
||||||
|
val col = Column.Builder()
|
||||||
|
.addContent(
|
||||||
|
Image.Builder()
|
||||||
|
.setWidth(iconSize)
|
||||||
|
.setHeight(iconSize)
|
||||||
|
.setResourceId(action.iconRes.toString())
|
||||||
|
.build()
|
||||||
|
).addContent(
|
||||||
|
Text.Builder()
|
||||||
|
.setText(text)
|
||||||
|
.setFontStyle(
|
||||||
|
FontStyle.Builder()
|
||||||
|
.setWeight(FONT_WEIGHT_BOLD)
|
||||||
|
.setColor(
|
||||||
|
argb(ContextCompat.getColor(baseContext, R.color.white))
|
||||||
|
)
|
||||||
|
.setSize(buttonTextSize(deviceParameters, text))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
if (textSub != null) {
|
||||||
|
col.addContent(
|
||||||
|
Text.Builder()
|
||||||
|
.setText(textSub)
|
||||||
|
.setFontStyle(
|
||||||
|
FontStyle.Builder()
|
||||||
|
.setColor(
|
||||||
|
argb(ContextCompat.getColor(baseContext, R.color.white))
|
||||||
|
)
|
||||||
|
.setSize(buttonTextSize(deviceParameters, textSub))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return col.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun circleDiameter(deviceParameters: DeviceParameters) = when (deviceParameters.screenShape) {
|
||||||
|
SCREEN_SHAPE_ROUND -> ((sqrt(2f) - 1) * deviceParameters.screenHeightDp) - (2 * SPACING_ACTIONS)
|
||||||
|
else -> 0.5f * deviceParameters.screenHeightDp - SPACING_ACTIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buttonTextSize(deviceParameters: DeviceParameters, text: String): SpProp {
|
||||||
|
if (text.length > 6) {
|
||||||
|
return sp(if (isLargeScreen(deviceParameters)) 14f else 12f)
|
||||||
|
}
|
||||||
|
return sp(if (isLargeScreen(deviceParameters)) 16f else 14f)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isLargeScreen(deviceParameters: DeviceParameters): Boolean {
|
||||||
|
return deviceParameters.screenWidthDp >= LARGE_SCREEN_WIDTH_DP
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getWearControl(): WearControl {
|
||||||
|
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
if (!sharedPrefs.contains("wearcontrol")) {
|
||||||
|
return WearControl.NO_DATA
|
||||||
|
}
|
||||||
|
val wearControlPref = sharedPrefs.getBoolean("wearcontrol", false)
|
||||||
|
if (wearControlPref) {
|
||||||
|
return WearControl.ENABLED
|
||||||
|
}
|
||||||
|
return WearControl.DISABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -71,6 +71,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
|
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
|
||||||
public final Point displaySize = new Point();
|
public final Point displaySize = new Point();
|
||||||
public TextView mTime, mHour, mMinute, mTimePeriod, mSgv, mDirection, mTimestamp, mUploaderBattery, mRigBattery, mDelta, mAvgDelta, mStatus, mBasalRate, mIOB1, mIOB2, mCOB1, mCOB2, mBgi, mLoop, mDay, mDayName, mMonth, isAAPSv2, mHighLight, mLowLight;
|
public TextView mTime, mHour, mMinute, mTimePeriod, mSgv, mDirection, mTimestamp, mUploaderBattery, mRigBattery, mDelta, mAvgDelta, mStatus, mBasalRate, mIOB1, mIOB2, mCOB1, mCOB2, mBgi, mLoop, mDay, mDayName, mMonth, isAAPSv2, mHighLight, mLowLight;
|
||||||
public ImageView mGlucoseDial, mDeltaGauge, mHourHand, mMinuteHand;
|
public ImageView mGlucoseDial, mDeltaGauge, mHourHand, mMinuteHand;
|
||||||
|
@ -111,7 +113,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
private Date mDateTime;
|
private Date mDateTime;
|
||||||
private String mLastSvg = "", mLastDirection = "";
|
private String mLastSvg = "", mLastDirection = "";
|
||||||
private float mYOffset = 0;
|
private float mYOffset = 0;
|
||||||
private Intent mBatteryStatus;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
|
@ -145,10 +146,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBatteryReceiver() {
|
private void setupBatteryReceiver() {
|
||||||
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
mBatteryStatus = this.registerReceiver(null, iFilter);
|
|
||||||
String setting = sharedPrefs.getString("simplify_ui", "off");
|
String setting = sharedPrefs.getString("simplify_ui", "off");
|
||||||
if (setting.equals("charging") || setting.equals("ambient_charging") && batteryReceiver == null) {
|
if ((setting.equals("charging") || setting.equals("ambient_charging")) && batteryReceiver == null) {
|
||||||
IntentFilter intentBatteryFilter = new IntentFilter();
|
IntentFilter intentBatteryFilter = new IntentFilter();
|
||||||
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
|
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
|
||||||
intentBatteryFilter.addAction(BatteryManager.ACTION_DISCHARGING);
|
intentBatteryFilter.addAction(BatteryManager.ACTION_DISCHARGING);
|
||||||
|
@ -374,6 +373,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCharging() {
|
private boolean isCharging() {
|
||||||
|
Intent mBatteryStatus = this.registerReceiver(null, iFilter);
|
||||||
int status = mBatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
int status = mBatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
||||||
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||||
status == BatteryManager.BATTERY_STATUS_FULL;
|
status == BatteryManager.BATTERY_STATUS_FULL;
|
||||||
|
@ -658,7 +658,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLowRes(WatchMode watchMode) {
|
private boolean isLowRes(WatchMode watchMode) {
|
||||||
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN); // || (watchMode == WatchMode.LOW_BIT_BURN_IN);
|
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSimpleUi() {
|
private boolean isSimpleUi() {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue