notify about wrong profiles from NS

This commit is contained in:
Milos Kozak 2021-11-01 22:29:02 +01:00
parent ba95b75da0
commit 7442774ab7
10 changed files with 67 additions and 35 deletions

View file

@ -114,9 +114,9 @@ class OpenAPSAMAPlugin @Inject constructor(
val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint -> val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint ->
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.value() }.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 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_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], 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].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) 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) {

View file

@ -119,9 +119,9 @@ class OpenAPSSMBPlugin @Inject constructor(
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.value() }.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 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_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], 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].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) 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) {

View file

@ -183,6 +183,7 @@ class NotificationStore @Inject constructor(
binding.dismiss.setOnClickListener { binding.dismiss.setOnClickListener {
val notification = it.tag as Notification val notification = it.tag as Notification
rxBus.send(EventDismissNotification(notification.id)) rxBus.send(EventDismissNotification(notification.id))
notification.contextForAction = itemView.context
notification.action?.run() notification.action?.run()
} }
} }

View file

@ -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) 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) { 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.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 { } 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.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 // Spinner

View file

@ -18,6 +18,9 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus 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.plugins.profile.local.events.EventLocalProfileChanged
import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
@ -48,7 +51,8 @@ class LocalProfilePlugin @Inject constructor(
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val dateUtil: DateUtil private val dateUtil: DateUtil,
private val config: Config
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.PROFILE) .mainType(PluginType.PROFILE)
.fragmentClass(LocalProfileFragment::class.java.name) .fragmentClass(LocalProfileFragment::class.java.name)
@ -131,11 +135,11 @@ class LocalProfilePlugin @Inject constructor(
ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values)) ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values))
return false 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) { 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)) ToastUtils.errorToast(activity, resourceHelper.gs(R.string.error_in_target_values))
return false 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)) ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values))
return false return false
} }
@ -148,18 +152,22 @@ class LocalProfilePlugin @Inject constructor(
ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values)) ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_basal_values))
return false 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) { 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)) ToastUtils.errorToast(activity, resourceHelper.gs(R.string.error_in_target_values))
return false 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)) ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values))
return false return false
} }
} }
for (i in low.indices) if (low[i].amount > high[i].amount) { low?.let {
ToastUtils.errorToast(activity,resourceHelper.gs(R.string.error_in_target_values)) high?.let {
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
}
}
} }
} }
return true return true
@ -251,10 +259,25 @@ class LocalProfilePlugin @Inject constructor(
try { try {
val newProfiles: ArrayList<SingleProfile> = ArrayList() val newProfiles: ArrayList<SingleProfile> = ArrayList()
for (p in store.getProfileList()) { for (p in store.getProfileList()) {
store.getSpecificProfile(p.toString())?.let { val profile = store.getSpecificProfile(p.toString())
val sp = copyFrom(it, 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() sp.name = p.toString()
newProfiles.add(sp) 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) { if (newProfiles.size > 0) {

View file

@ -1125,5 +1125,8 @@
<string name="error_in_target_values">Error in target values</string> <string name="error_in_target_values">Error in target values</string>
<string name="error_in_isf_values">Error in ISF values</string> <string name="error_in_isf_values">Error in ISF values</string>
<string name="run_question">Run %s?</string> <string name="run_question">Run %s?</string>
<string name="invalid_profile_not_accepted">Invalid profile %1$s not accepted from NS</string>
<string name="view">View</string>
<string name="errors">Errors</string>
</resources> </resources>

View file

@ -122,6 +122,11 @@ sealed class ProfileSealed(
break 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 // Check for minimal basal value
if (basalAmount < description.basalMinimumRate) { if (basalAmount < description.basalMinimumRate) {
basal.amount = description.basalMinimumRate basal.amount = description.basalMinimumRate
@ -136,11 +141,6 @@ sealed class ProfileSealed(
validityCheck.reasons.add(resourceHelper.gs(R.string.maximumbasalvaluereplaced, from)) validityCheck.reasons.add(resourceHelper.gs(R.string.maximumbasalvaluereplaced, from))
break 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())) { if (!hardLimits.isInRange(dia, hardLimits.minDia(), hardLimits.maxDia())) {
validityCheck.isValid = false validityCheck.isValid = false
@ -160,9 +160,9 @@ sealed class ProfileSealed(
} }
for (target in targetBlocks) { for (target in targetBlocks) {
if (!hardLimits.isInRange( if (!hardLimits.isInRange(
Profile.toMgdl(target.lowTarget, units), toMgdl(target.lowTarget, units),
HardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MIN_BG[0],
HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble() HardLimits.VERY_HARD_LIMIT_MIN_BG[1]
) )
) { ) {
validityCheck.isValid = false validityCheck.isValid = false
@ -170,9 +170,9 @@ sealed class ProfileSealed(
break break
} }
if (!hardLimits.isInRange( if (!hardLimits.isInRange(
Profile.toMgdl(target.highTarget, units), toMgdl(target.highTarget, units),
HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[0],
HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble() HardLimits.VERY_HARD_LIMIT_MAX_BG[1]
) )
) { ) {
validityCheck.isValid = false validityCheck.isValid = false

View file

@ -68,7 +68,7 @@ class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val d
if (profile == null) { if (profile == null) {
JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject -> JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject ->
profile = pureProfileFromJson(profileObject, dateUtil, defaultUnits) profile = pureProfileFromJson(profileObject, dateUtil, defaultUnits)
cachedObjects[profileName] = profile profile?.let { cachedObjects[profileName] = profile }
} }
} }
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.overview.notifications package info.nightscout.androidaps.plugins.general.overview.notifications
import android.content.Context
import androidx.annotation.RawRes import androidx.annotation.RawRes
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
@ -14,6 +15,8 @@ open class Notification {
var action: Runnable? = null var action: Runnable? = null
var buttonText = 0 var buttonText = 0
var contextForAction: Context? = null
constructor() constructor()
constructor(id: Int, date: Long, text: String, level: Int, validTo: Long) { constructor(id: Int, date: Long, text: String, level: Int, validTo: Long) {
this.id = id this.id = id
@ -55,6 +58,7 @@ open class Notification {
const val LOW = 2 const val LOW = 2
const val INFO = 3 const val INFO = 3
const val ANNOUNCEMENT = 4 const val ANNOUNCEMENT = 4
const val PROFILE_SET_FAILED = 0 const val PROFILE_SET_FAILED = 0
const val PROFILE_SET_OK = 1 const val PROFILE_SET_OK = 1
const val EASY_MODE_ENABLED = 2 const val EASY_MODE_ENABLED = 2
@ -122,6 +126,7 @@ open class Notification {
const val WRONG_PUMP_DATA = 72 const val WRONG_PUMP_DATA = 72
const val NSCLIENT_VERSION_DOES_NOT_MATCH = 73 const val NSCLIENT_VERSION_DOES_NOT_MATCH = 73
const val VERSION_EXPIRE = 74 const val VERSION_EXPIRE = 74
const val INVALID_PROFILE_NOT_ACCEPTED = 75
const val USER_MESSAGE = 1000 const val USER_MESSAGE = 1000

View file

@ -40,9 +40,9 @@ class HardLimits @Inject constructor(
// Very Hard Limits Ranges // Very Hard Limits Ranges
// First value is the Lowest and second value is the Highest a Limit can define // 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_MIN_BG = doubleArrayOf(80.0, 180.0)
val VERY_HARD_LIMIT_MAX_BG = intArrayOf(90, 270) val VERY_HARD_LIMIT_MAX_BG = doubleArrayOf(90.0, 200.0)
val VERY_HARD_LIMIT_TARGET_BG = intArrayOf(80, 200) val VERY_HARD_LIMIT_TARGET_BG = doubleArrayOf(80.0, 200.0)
// Very Hard Limits Ranges for Temp Targets // Very Hard Limits Ranges for Temp Targets
val VERY_HARD_LIMIT_TEMP_MIN_BG = intArrayOf(72, 180) val VERY_HARD_LIMIT_TEMP_MIN_BG = intArrayOf(72, 180)