From 7442774ab7fceb39492a45fe1f62e965cebc680a Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 1 Nov 2021 22:29:02 +0100 Subject: [PATCH] notify about wrong profiles from NS --- .../aps/openAPSAMA/OpenAPSAMAPlugin.kt | 6 +-- .../aps/openAPSSMB/OpenAPSSMBPlugin.kt | 6 +-- .../notifications/NotificationStore.kt | 1 + .../profile/local/LocalProfileFragment.kt | 4 +- .../profile/local/LocalProfilePlugin.kt | 47 ++++++++++++++----- app/src/main/res/values/strings.xml | 3 ++ .../androidaps/data/ProfileSealed.kt | 22 ++++----- .../androidaps/interfaces/ProfileStore.kt | 2 +- .../overview/notifications/Notification.kt | 5 ++ .../nightscout/androidaps/utils/HardLimits.kt | 6 +-- 10 files changed, 67 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt index b11d5b8e20..162a3f63ed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt @@ -114,9 +114,9 @@ class OpenAPSAMAPlugin @Inject constructor( val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint -> inputConstraints.copyReasons(maxIOBAllowedConstraint) }.value() - var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble()) - var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) - var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) + 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 targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]) var isTempTarget = false val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() if (tempTarget is ValueWrapper.Existing) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt index 42c1700fb8..0b03ab5aca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt @@ -119,9 +119,9 @@ class OpenAPSSMBPlugin @Inject constructor( inputConstraints.copyReasons(maxIOBAllowedConstraint) }.value() - var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble()) - var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) - var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) + 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 targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]) var isTempTarget = false val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() if (tempTarget is ValueWrapper.Existing) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt index 80ee31d783..152d9c5b2a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt @@ -183,6 +183,7 @@ class NotificationStore @Inject constructor( binding.dismiss.setOnClickListener { val notification = it.tag as Notification rxBus.send(EventDismissNotification(notification.id)) + notification.contextForAction = itemView.context notification.action?.run() } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 1675d4986b..59310cb8f4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -132,10 +132,10 @@ class LocalProfileFragment : DaggerFragment() { basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", resourceHelper.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), save) if (units == Constants.MGDL) { TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf, "ISF", resourceHelper.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), 1.0, DecimalFormat("0"), save) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], 1.0, DecimalFormat("0"), save) } else { TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf, "ISF", resourceHelper.gs(R.string.isf_label), currentProfile.isf, null, Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save) } // Spinner diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt index 45ffde96b0..34aba93fea 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt @@ -18,6 +18,9 @@ import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.DateUtil @@ -48,7 +51,8 @@ class LocalProfilePlugin @Inject constructor( private val profileFunction: ProfileFunction, private val activePlugin: ActivePlugin, private val hardLimits: HardLimits, - private val dateUtil: DateUtil + private val dateUtil: DateUtil, + private val config: Config ) : PluginBase(PluginDescription() .mainType(PluginType.PROFILE) .fragmentClass(LocalProfileFragment::class.java.name) @@ -131,11 +135,11 @@ class LocalProfilePlugin @Inject constructor( ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values)) return false } - if (low?.any { it.amount < HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble() || it.amount > HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble() } != false) { - ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) + if (low?.any { hardLimits.isInRange(it.amount, HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]) } == false) { + ToastUtils.errorToast(activity, resourceHelper.gs(R.string.error_in_target_values)) return false } - if (high?.any { it.amount < HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble() || it.amount > HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble() } != false) { + if (high?.any { hardLimits.isInRange(it.amount, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]) } == false) { ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) return false } @@ -148,18 +152,22 @@ class LocalProfilePlugin @Inject constructor( ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values)) return false } - if (low?.any { it.amount < Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), GlucoseUnit.MMOL) || it.amount > Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), GlucoseUnit.MMOL) } != false) { - ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) + if (low?.any { hardLimits.isInRange(Profile.toMgdl(it.amount, GlucoseUnit.MMOL), HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]) } == false) { + ToastUtils.errorToast(activity, resourceHelper.gs(R.string.error_in_target_values)) return false } - if (high?.any { it.amount < Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), GlucoseUnit.MMOL) || it.amount > Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), GlucoseUnit.MMOL) } != false) { + if (high?.any { hardLimits.isInRange(Profile.toMgdl(it.amount, GlucoseUnit.MMOL), HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]) } == false) { ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) return false } } - for (i in low.indices) if (low[i].amount > high[i].amount) { - ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) - return false + low?.let { + high?.let { + for (i in low.indices) if (low[i].amount > high[i].amount) { + ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) + return false + } + } } } return true @@ -251,10 +259,25 @@ class LocalProfilePlugin @Inject constructor( try { val newProfiles: ArrayList = ArrayList() for (p in store.getProfileList()) { - store.getSpecificProfile(p.toString())?.let { - val sp = copyFrom(it, p.toString()) + val profile = store.getSpecificProfile(p.toString()) + val validityCheck = profile?.let { ProfileSealed.Pure(profile).isValid("NS", activePlugin.activePump, config, resourceHelper, rxBus, hardLimits, false) } ?: Profile.ValidityCheck() + if (profile != null && validityCheck.isValid) { + val sp = copyFrom(profile, p.toString()) sp.name = p.toString() newProfiles.add(sp) + } else { + val n = NotificationWithAction( + injector, + Notification.INVALID_PROFILE_NOT_ACCEPTED, + resourceHelper.gs(R.string.invalid_profile_not_accepted, p.toString()), + Notification.NORMAL + ) + n.action(R.string.view) { + n.contextForAction?.let { + OKDialog.show(it, resourceHelper.gs(R.string.errors), validityCheck.reasons.joinToString(separator = "\n"), null) + } + } + rxBus.send(EventNewNotification(n)) } } if (newProfiles.size > 0) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ee00a2eab8..2fe7985621 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1125,5 +1125,8 @@ Error in target values Error in ISF values Run %s? + Invalid profile %1$s not accepted from NS + View + Errors diff --git a/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt b/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt index 93286b5a3d..58e00a684c 100644 --- a/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt +++ b/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt @@ -122,6 +122,11 @@ sealed class ProfileSealed( break } } + if (!hardLimits.isInRange(basalAmount, 0.01, hardLimits.maxBasal())) { + validityCheck.isValid = false + validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.basal_value), basalAmount)) + break + } // Check for minimal basal value if (basalAmount < description.basalMinimumRate) { basal.amount = description.basalMinimumRate @@ -136,11 +141,6 @@ sealed class ProfileSealed( validityCheck.reasons.add(resourceHelper.gs(R.string.maximumbasalvaluereplaced, from)) break } - if (!hardLimits.isInRange(basalAmount, 0.01, hardLimits.maxBasal())) { - validityCheck.isValid = false - validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.basal_value), basalAmount)) - break - } } if (!hardLimits.isInRange(dia, hardLimits.minDia(), hardLimits.maxDia())) { validityCheck.isValid = false @@ -160,9 +160,9 @@ sealed class ProfileSealed( } for (target in targetBlocks) { if (!hardLimits.isInRange( - Profile.toMgdl(target.lowTarget, units), - HardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), - HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble() + toMgdl(target.lowTarget, units), + HardLimits.VERY_HARD_LIMIT_MIN_BG[0], + HardLimits.VERY_HARD_LIMIT_MIN_BG[1] ) ) { validityCheck.isValid = false @@ -170,9 +170,9 @@ sealed class ProfileSealed( break } if (!hardLimits.isInRange( - Profile.toMgdl(target.highTarget, units), - HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), - HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble() + toMgdl(target.highTarget, units), + HardLimits.VERY_HARD_LIMIT_MAX_BG[0], + HardLimits.VERY_HARD_LIMIT_MAX_BG[1] ) ) { validityCheck.isValid = false diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileStore.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileStore.kt index 03b0d773bf..49ad281742 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileStore.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileStore.kt @@ -68,7 +68,7 @@ class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val d if (profile == null) { JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject -> profile = pureProfileFromJson(profileObject, dateUtil, defaultUnits) - cachedObjects[profileName] = profile + profile?.let { cachedObjects[profileName] = profile } } } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt index b7325e964e..c7b55e93ae 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.kt @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.general.overview.notifications +import android.content.Context import androidx.annotation.RawRes import info.nightscout.androidaps.utils.T @@ -14,6 +15,8 @@ open class Notification { var action: Runnable? = null var buttonText = 0 + var contextForAction: Context? = null + constructor() constructor(id: Int, date: Long, text: String, level: Int, validTo: Long) { this.id = id @@ -55,6 +58,7 @@ open class Notification { const val LOW = 2 const val INFO = 3 const val ANNOUNCEMENT = 4 + const val PROFILE_SET_FAILED = 0 const val PROFILE_SET_OK = 1 const val EASY_MODE_ENABLED = 2 @@ -122,6 +126,7 @@ open class Notification { const val WRONG_PUMP_DATA = 72 const val NSCLIENT_VERSION_DOES_NOT_MATCH = 73 const val VERSION_EXPIRE = 74 + const val INVALID_PROFILE_NOT_ACCEPTED = 75 const val USER_MESSAGE = 1000 diff --git a/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt index aecb0ff2b4..c71691462b 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt @@ -40,9 +40,9 @@ class HardLimits @Inject constructor( // Very Hard Limits Ranges // First value is the Lowest and second value is the Highest a Limit can define - val VERY_HARD_LIMIT_MIN_BG = intArrayOf(80, 180) - val VERY_HARD_LIMIT_MAX_BG = intArrayOf(90, 270) - val VERY_HARD_LIMIT_TARGET_BG = intArrayOf(80, 200) + val VERY_HARD_LIMIT_MIN_BG = doubleArrayOf(80.0, 180.0) + val VERY_HARD_LIMIT_MAX_BG = doubleArrayOf(90.0, 200.0) + val VERY_HARD_LIMIT_TARGET_BG = doubleArrayOf(80.0, 200.0) // Very Hard Limits Ranges for Temp Targets val VERY_HARD_LIMIT_TEMP_MIN_BG = intArrayOf(72, 180)