diff --git a/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt b/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt
index e873bf5edf..f20eed392a 100644
--- a/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt
+++ b/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt
@@ -1,42 +1,7 @@
package info.nightscout.androidaps
-import android.os.SystemClock
-import android.view.View
-import android.view.ViewGroup
-import androidx.test.espresso.Espresso.onData
-import androidx.test.espresso.Espresso.onView
-import androidx.test.espresso.action.ViewActions
-import androidx.test.espresso.action.ViewActions.click
-import androidx.test.espresso.action.ViewActions.scrollTo
-import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
-import androidx.test.espresso.matcher.ViewMatchers.withClassName
-import androidx.test.espresso.matcher.ViewMatchers.withId
-import androidx.test.espresso.matcher.ViewMatchers.withTagValue
-import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
-import androidx.test.rule.GrantPermissionRule
-import info.nightscout.androidaps.interfaces.PluginType
-import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
-import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
-import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
-import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
-import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
-import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
-import info.nightscout.androidaps.plugins.source.RandomBgPlugin
-import info.nightscout.androidaps.setupwizard.SetupWizardActivity
-import info.nightscout.androidaps.utils.HardLimits
-import info.nightscout.androidaps.utils.extensions.isRunningTest
-import org.hamcrest.CoreMatchers.allOf
-import org.hamcrest.Description
-import org.hamcrest.Matcher
-import org.hamcrest.Matchers
-import org.hamcrest.TypeSafeMatcher
-import org.junit.Assert
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
import org.junit.runner.RunWith
@LargeTest
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
index d47573ef2f..00fe3c688f 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
@@ -8,14 +8,18 @@ import android.widget.ArrayAdapter
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
+import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.databinding.DialogProfileswitchBinding
import info.nightscout.androidaps.interfaces.ActivePlugin
+import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
+import info.nightscout.androidaps.plugins.bus.RxBusWrapper
+import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
@@ -31,6 +35,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger
+ @Inject lateinit var config: Config
+ @Inject lateinit var hardLimits: HardLimits
+ @Inject lateinit var rxBus: RxBusWrapper
private var profileIndex: Int? = null
@@ -129,22 +136,33 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
activity?.let { activity ->
- OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("
").join(actions)), {
- profileFunction.createProfileSwitch(profileStore,
- profileName = profileName,
- durationInMinutes = duration,
- percentage = percent,
- timeShiftInHours = timeShift,
- timestamp = eventTime)
- uel.log(Action.PROFILE_SWITCH,
- Sources.ProfileSwitchDialog,
- notes,
- ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
- ValueWithUnit.SimpleString(profileName),
- ValueWithUnit.Percent(percent),
- ValueWithUnit.Hour(timeShift).takeIf { timeShift != 0 },
- ValueWithUnit.Minute(duration).takeIf { duration != 0 })
- })
+ val ps = profileFunction.buildProfileSwitch(profileStore, profileName, duration, percent, timeShift, eventTime)
+ val validity = ProfileSealed.PS(ps).isValid(resourceHelper.gs(R.string.careportal_profileswitch), activePlugin.activePump, config, resourceHelper, rxBus, hardLimits)
+ if (validity.isValid)
+ OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("
").join(actions)), {
+ profileFunction.createProfileSwitch(profileStore,
+ profileName = profileName,
+ durationInMinutes = duration,
+ percentage = percent,
+ timeShiftInHours = timeShift,
+ timestamp = eventTime)
+ uel.log(Action.PROFILE_SWITCH,
+ Sources.ProfileSwitchDialog,
+ notes,
+ ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
+ ValueWithUnit.SimpleString(profileName),
+ ValueWithUnit.Percent(percent),
+ ValueWithUnit.Hour(timeShift).takeIf { timeShift != 0 },
+ ValueWithUnit.Minute(duration).takeIf { duration != 0 })
+ })
+ else {
+ OKDialog.show(
+ activity,
+ resourceHelper.gs(R.string.careportal_profileswitch),
+ HtmlHelper.fromHtml(Joiner.on("
").join(validity.reasons))
+ )
+ return false
+ }
}
return true
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt
index c6955fcd34..5ee8e69839 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt
@@ -46,7 +46,6 @@ import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAc
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.queue.Callback
-import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.receivers.ReceiverStatusStore
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
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 f697f23e20..479acd4da0 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
@@ -125,11 +125,11 @@ class OpenAPSAMAPlugin @Inject constructor(
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.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
- if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
- if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
- if (!hardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
- if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) 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.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
+ if (!hardLimits.checkHardLimits(profile.getMaxDailyBasal(), R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
+ if (!hardLimits.checkHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculator.getLastAutosensDataWithWaitForCalculationFinish("OpenAPSPlugin")
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 3b65f213f7..e658f2d04c 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
@@ -130,11 +130,11 @@ class OpenAPSSMBPlugin @Inject constructor(
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.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
- if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
- if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
- if (!hardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
- if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) 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.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
+ if (!hardLimits.checkHardLimits(profile.getMaxDailyBasal(), R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) return
+ if (!hardLimits.checkHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculator.getLastAutosensDataWithWaitForCalculationFinish("OpenAPSPlugin")
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt
index 3de63dbbd5..5cf7bb4371 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt
@@ -91,10 +91,10 @@ class ProfileFunctionImplementation @Inject constructor(
if (sp.getString(R.string.key_units, Constants.MGDL) == Constants.MGDL) GlucoseUnit.MGDL
else GlucoseUnit.MMOL
- override fun createProfileSwitch(profileStore: ProfileStore, profileName: String, durationInMinutes: Int, percentage: Int, timeShiftInHours: Int, timestamp: Long) {
+ override fun buildProfileSwitch(profileStore: ProfileStore, profileName: String, durationInMinutes: Int, percentage: Int, timeShiftInHours: Int, timestamp: Long) : ProfileSwitch {
val pureProfile = profileStore.getSpecificProfile(profileName)
?: throw InvalidParameterSpecException(profileName)
- val ps = ProfileSwitch(
+ return ProfileSwitch(
timestamp = timestamp,
basalBlocks = pureProfile.basalBlocks,
isfBlocks = pureProfile.isfBlocks,
@@ -105,8 +105,14 @@ class ProfileFunctionImplementation @Inject constructor(
timeshift = T.hours(timeShiftInHours.toLong()).msecs(),
percentage = percentage,
duration = T.mins(durationInMinutes.toLong()).msecs(),
- insulinConfiguration = activePlugin.activeInsulin.insulinConfiguration.also { it.insulinEndTime = (pureProfile.dia * 3600 * 1000).toLong() }
+ insulinConfiguration = activePlugin.activeInsulin.insulinConfiguration.also {
+ it.insulinEndTime = (pureProfile.dia * 3600 * 1000).toLong()
+ }
)
+ }
+
+ override fun createProfileSwitch(profileStore: ProfileStore, profileName: String, durationInMinutes: Int, percentage: Int, timeShiftInHours: Int, timestamp: Long) {
+ val ps = buildProfileSwitch(profileStore, profileName, durationInMinutes, percentage, timeShiftInHours, timestamp)
disposable += repository.runTransactionForResult(InsertOrUpdateProfileSwitch(ps))
.subscribe({ result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted ProfileSwitch $it") }
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt
index cfc0eaac7e..bddee95f50 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt
@@ -740,7 +740,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
graphData.addTreatments()
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
graphData.addActivity(0.8)
- if (pump.pumpDescription.isTempBasalCapable && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
+ if ((pump.pumpDescription.isTempBasalCapable || config.NSCLIENT) && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
graphData.addBasals()
graphData.addTargetLine()
graphData.addNowLine(dateUtil.now())
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt
index b65a284149..8d640afc75 100644
--- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt
@@ -28,6 +28,7 @@ import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.CryptoUtil
+import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
@@ -53,7 +54,8 @@ class SWDefinition @Inject constructor(
private val importExportPrefs: ImportExportPrefs,
private val androidPermission: AndroidPermission,
private val cryptoUtil: CryptoUtil,
- private val config: Config
+ private val config: Config,
+ private val hardLimits: HardLimits
) {
lateinit var activity: AppCompatActivity
@@ -255,7 +257,7 @@ class SWDefinition @Inject constructor(
.add(SWFragment(injector, this)
.add(LocalProfileFragment()))
.validator {
- localProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) }
+ localProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus, hardLimits).isValid }
?: false
}
.visibility { localProfilePlugin.isEnabled() }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8e2e35aecf..a248a82b14 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -250,8 +250,6 @@
Loop has been disabled
Loop has been enabled
Loop is enabled
- %1$.2f limited to %2$.2f
- »%1$s« is out of hard limits
To connect pump reply with code %1$s
Connection to pump failed
To disconnect pump for %1$d minutes reply with code %2$s
@@ -400,12 +398,6 @@
Adult
Insulin resistant adult
Pregnancy
- age
- child
- teenage
- adult
- resistantadult
- pregnant
Please select patient type to setup safety limits
Patient name
Please provide patient name or nickname to differentiate among multiple setups
@@ -1082,16 +1074,6 @@
Email address
Privacy setting
You can provide optional email address if you want to be notified about app crashes. This is not an automated service. You will be contacted by developers in dangerous situations.
- Profile low target
- Profile high target
- Temporary target bottom value
- Temporary target top value
- Temporary target value
- Profile DIA value
- Profile sensitivity value
- Maximal profile basal value
- Current basal value
- Profile carbs ratio value
Full sync
Prime
Synchronization
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 50b39e896b..f47f1a534f 100644
--- a/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt
+++ b/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt
@@ -19,6 +19,8 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.HardLimits
+import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONArray
@@ -94,34 +96,93 @@ sealed class ProfileSealed(
value.timeZone.rawOffset.toLong()
)
- override fun isValid(from: String, pump: Pump, config: Config, resourceHelper: ResourceHelper, rxBus: RxBusWrapper): Boolean {
+ override fun isValid(from: String, pump: Pump, config: Config, resourceHelper: ResourceHelper, rxBus: RxBusWrapper, hardLimits: HardLimits): Profile.ValidityCheck {
val notify = true
- var valid = true
+ val validityCheck = Profile.ValidityCheck()
val description = pump.pumpDescription
- if (!description.is30minBasalRatesCapable) {
- for (basal in basalBlocks) {
+ for (basal in basalBlocks) {
+ val basalAmount = basal.amount * percentage / 100.0
+ if (!description.is30minBasalRatesCapable) {
// Check for hours alignment
val duration: Long = basal.duration
if (duration % 3600000 != 0L) {
if (notify && config.APS) {
- val notification = Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, resourceHelper.gs(R.string.basalprofilenotaligned, from), Notification.NORMAL)
+ val notification = Notification(
+ Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS,
+ resourceHelper.gs(R.string.basalprofilenotaligned, from),
+ Notification.NORMAL
+ )
rxBus.send(EventNewNotification(notification))
}
- valid = false
- }
- // Check for minimal basal value
- if (basal.amount < description.basalMinimumRate) {
- basal.amount = description.basalMinimumRate
- if (notify) sendBelowMinimumNotification(from, rxBus, resourceHelper)
- valid = false
- } else if (basal.amount > description.basalMaximumRate) {
- basal.amount = description.basalMaximumRate
- if (notify) sendAboveMaximumNotification(from, rxBus, resourceHelper)
- valid = false
+ validityCheck.isValid = false
+ validityCheck.reasons.add(
+ resourceHelper.gs(
+ R.string.basalprofilenotaligned,
+ from
+ )
+ )
+ break
}
}
+ // Check for minimal basal value
+ if (basalAmount < description.basalMinimumRate) {
+ basal.amount = description.basalMinimumRate
+ if (notify) sendBelowMinimumNotification(from, rxBus, resourceHelper)
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.minimalbasalvaluereplaced, from))
+ break
+ } else if (basalAmount > description.basalMaximumRate) {
+ basal.amount = description.basalMaximumRate
+ if (notify) sendAboveMaximumNotification(from, rxBus, resourceHelper)
+ validityCheck.isValid = false
+ 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
+ }
}
- return valid
+ if (!hardLimits.isInRange(dia, hardLimits.minDia(), hardLimits.maxDia())) {
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.profile_dia), dia))
+ }
+ for (ic in icBlocks)
+ if (!hardLimits.isInRange(ic.amount * 100.0 / percentage, hardLimits.minIC(), hardLimits.maxIC())) {
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.profile_carbs_ratio_value), ic.amount * 100.0 / percentage))
+ break
+ }
+ for (isf in isfBlocks)
+ if (!hardLimits.isInRange(toMgdl(isf.amount * 100.0 / percentage, units), HardLimits.MIN_ISF, HardLimits.MAX_ISF)) {
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.profile_sensitivity_value), isf.amount * 100.0 / percentage))
+ break
+ }
+ for (target in targetBlocks) {
+ if (hardLimits.isInRange(
+ Round.roundTo(target.lowTarget, 0.1),
+ HardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(),
+ HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble()
+ )
+ ) {
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.profile_low_target), target.lowTarget))
+ break
+ }
+ if (hardLimits.isInRange(
+ Round.roundTo(target.highTarget, 0.1),
+ HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(),
+ HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()
+ )
+ ) {
+ validityCheck.isValid = false
+ validityCheck.reasons.add(resourceHelper.gs(R.string.value_out_of_hard_limits, resourceHelper.gs(R.string.profile_high_target), target.highTarget))
+ break
+ }
+ }
+ return validityCheck
}
protected open fun sendBelowMinimumNotification(from: String, rxBus: RxBusWrapper, resourceHelper: ResourceHelper) {
diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
index 1f4c88e3ab..ccb87c0704 100644
--- a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
+++ b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt
@@ -17,15 +17,18 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.extensions.getCustomizedName
import info.nightscout.androidaps.extensions.pureProfileFromJson
+import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONObject
+import java.io.File.separator
import java.text.DecimalFormat
import javax.inject.Inject
@@ -39,6 +42,7 @@ class ProfileViewerDialog : DaggerDialogFragment() {
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var config: Config
@Inject lateinit var rxBus: RxBusWrapper
+ @Inject lateinit var hardLimits: HardLimits
private var time: Long = 0
@@ -149,7 +153,9 @@ class ProfileViewerDialog : DaggerDialogFragment() {
}
binding.noprofile.visibility = View.GONE
- binding.invalidprofile.visibility = if (profile1.isValid("ProfileViewDialog", activePlugin.activePump, config, resourceHelper, rxBus)) View.GONE else View.VISIBLE
+ val validity = profile1.isValid("ProfileViewDialog", activePlugin.activePump, config, resourceHelper, rxBus, hardLimits)
+ binding.invalidprofile.text = resourceHelper.gs(R.string.invalidprofile) + "\n" + validity.reasons.joinToString(separator = "\n")
+ binding.invalidprofile.visibility = validity.isValid.not().toVisibility()
}
else
profile?.let {
@@ -164,7 +170,9 @@ class ProfileViewerDialog : DaggerDialogFragment() {
binding.basalGraph.show(it)
binding.noprofile.visibility = View.GONE
- binding.invalidprofile.visibility = if (it.isValid("ProfileViewDialog", activePlugin.activePump, config, resourceHelper, rxBus)) View.GONE else View.VISIBLE
+ val validity = it.isValid("ProfileViewDialog", activePlugin.activePump, config, resourceHelper, rxBus, hardLimits)
+ binding.invalidprofile.text = resourceHelper.gs(R.string.invalidprofile) + "\n" + validity.reasons.joinToString(separator = "\n")
+ binding.invalidprofile.visibility = validity.isValid.not().toVisibility()
}
}
diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/Profile.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/Profile.kt
index 3d43cdc60f..2cd9ac88f5 100644
--- a/core/src/main/java/info/nightscout/androidaps/interfaces/Profile.kt
+++ b/core/src/main/java/info/nightscout/androidaps/interfaces/Profile.kt
@@ -6,6 +6,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal
import info.nightscout.androidaps.utils.DecimalFormatter.to1Decimal
+import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.joda.time.DateTime
@@ -13,7 +14,9 @@ import org.json.JSONObject
interface Profile {
- fun isValid(from: String, pump: Pump, config: Config, resourceHelper: ResourceHelper, rxBus: RxBusWrapper): Boolean
+ class ValidityCheck(var isValid: Boolean = true, val reasons: ArrayList = arrayListOf())
+
+ fun isValid(from: String, pump: Pump, config: Config, resourceHelper: ResourceHelper, rxBus: RxBusWrapper, hardLimits: HardLimits): ValidityCheck
/**
* Units used for ISF & target
diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileFunction.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileFunction.kt
index 0b4829dad3..3cc7939446 100644
--- a/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileFunction.kt
+++ b/core/src/main/java/info/nightscout/androidaps/interfaces/ProfileFunction.kt
@@ -46,6 +46,18 @@ interface ProfileFunction {
*/
fun getRequestedProfile(): ProfileSwitch?
+ /**
+ * Build a new circadian profile switch request based on provided profile
+ *
+ * @param profileStore ProfileStore to use
+ * @param profileName this profile from profile store
+ * @param durationInMinutes
+ * @param percentage 100 = no modification
+ * @param timeShiftInHours 0 = no modification
+ * @param timestamp expected time
+ */
+ fun buildProfileSwitch(profileStore: ProfileStore, profileName: String, durationInMinutes: Int, percentage: Int, timeShiftInHours: Int, timestamp: Long): ProfileSwitch
+
/**
* Create a new circadian profile switch request based on provided profile
*
diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.kt
index 136e899a2c..003d8f569e 100644
--- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.kt
+++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.kt
@@ -63,7 +63,7 @@ class PumpDescription() {
is30minBasalRatesCapable = false
isRefillingCapable = true
isBatteryReplaceable = true
- storesCarbInfo = true
+ storesCarbInfo = false
supportsTDDs = false
needsManualTDDLoad = true
hasCustomUnreachableAlertCheck = false
diff --git a/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt
similarity index 92%
rename from app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt
rename to core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt
index 0389b34283..67118d0908 100644
--- a/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt
+++ b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt
@@ -1,7 +1,8 @@
package info.nightscout.androidaps.utils
import android.content.Context
-import info.nightscout.androidaps.R
+import info.nightscout.androidaps.annotations.OpenForTesting
+import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.logging.AAPSLogger
@@ -15,6 +16,7 @@ import javax.inject.Singleton
import kotlin.math.max
import kotlin.math.min
+@OpenForTesting
@Singleton
class HardLimits @Inject constructor(
private val aapsLogger: AAPSLogger,
@@ -81,9 +83,12 @@ class HardLimits @Inject constructor(
fun maxIC(): Double = MAX_IC[loadAge()]
// safety checks
- fun checkOnlyHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean =
+ fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean =
value == verifyHardLimits(value, valueName, lowLimit, highLimit)
+ fun isInRange(value: Double, lowLimit: Double, highLimit: Double): Boolean =
+ value in lowLimit..highLimit
+
fun verifyHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Double {
var newValue = value
if (newValue < lowLimit || newValue > highLimit) {
@@ -98,4 +103,4 @@ class HardLimits @Inject constructor(
}
return newValue
}
-}
+}
\ No newline at end of file
diff --git a/core/src/main/java/info/nightscout/androidaps/utils/sharedPreferences/SPImplementation.kt b/core/src/main/java/info/nightscout/androidaps/utils/sharedPreferences/SPImplementation.kt
index 5231a2e4ad..52f5c61f26 100644
--- a/core/src/main/java/info/nightscout/androidaps/utils/sharedPreferences/SPImplementation.kt
+++ b/core/src/main/java/info/nightscout/androidaps/utils/sharedPreferences/SPImplementation.kt
@@ -90,7 +90,11 @@ class SPImplementation @Inject constructor(
return try {
sharedPreferences.getLong(key, defaultValue)
} catch (e: Exception) {
- SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()))
+ try {
+ SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()))
+ } catch (e: Exception) {
+ defaultValue
+ }
}
}
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 838e4d7acf..2b813deedc 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -57,6 +57,12 @@
active_pump_change_timestamp
active_pump_type
active_pump_serial_number
+ age
+ child
+ teenage
+ adult
+ resistantadult
+ pregnant
Refresh
@@ -472,6 +478,22 @@
LOOP REMOVED
OTHER
+
+ Profile low target
+ Profile high target
+ Temporary target bottom value
+ Temporary target top value
+ Temporary target value
+ Profile DIA value
+ Profile sensitivity value
+ Maximal profile basal value
+ Current basal value
+ Profile carbs ratio value
+ %1$.2f limited to %2$.2f
+ »%1$s« is out of hard limits
+ »%1$s« %2$.2f is out of hard limits
+ Basal value
+
- %1$d day
- %1$d days
diff --git a/core/src/test/java/info/nightscout/androidaps/data/ProfileTest.kt b/core/src/test/java/info/nightscout/androidaps/data/ProfileTest.kt
index d141926a7e..3c1e6b5732 100644
--- a/core/src/test/java/info/nightscout/androidaps/data/ProfileTest.kt
+++ b/core/src/test/java/info/nightscout/androidaps/data/ProfileTest.kt
@@ -2,11 +2,10 @@ package info.nightscout.androidaps.data
import android.content.Context
import dagger.android.AndroidInjector
-import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.core.R
-import info.nightscout.androidaps.events.Event
+import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
@@ -14,18 +13,18 @@ import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DateUtil
+import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.TestAapsSchedulers
+import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
-import org.mockito.Mockito.doNothing
import java.util.*
/**
@@ -38,25 +37,29 @@ class ProfileTest : TestBase() {
@Mock lateinit var resourceHelper: ResourceHelper
@Mock lateinit var context: Context
@Mock lateinit var config: Config
+ @Mock lateinit var sp: SP
+ @Mock lateinit var repository: AppRepository
private lateinit var rxBus: RxBusWrapper
private lateinit var dateUtil: DateUtil
private lateinit var testPumpPlugin: TestPumpPlugin
+ private lateinit var hardLimits: HardLimits
- private var okProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
- private var belowLimitValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.001\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
- private var notAlignedBasalValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:30\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
- private var notStartingAtZeroValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:30\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
- private var noUnitsValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\"}"
- private var wrongProfile = "{\"dia\":\"3\",\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+ private var okProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"sens\":[{\"time\":\"00:00\",\"value\":\"6\"},{\"time\":\"2:00\",\"value\":\"6.2\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+ private var belowLimitValidProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.001\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+ private var notAlignedBasalValidProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:30\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+ private var notStartingAtZeroValidProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:30\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+ private var noUnitsValidProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\"}"
+ private var wrongProfile = "{\"dia\":\"5\",\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
//String profileStore = "{\"defaultProfile\":\"Default\",\"store\":{\"Default\":" + validProfile + "}}";
@Before
fun prepare() {
- testPumpPlugin = TestPumpPlugin(HasAndroidInjector { AndroidInjector { } })
+ testPumpPlugin = TestPumpPlugin { AndroidInjector { } }
dateUtil = DateUtil(context)
rxBus = RxBusWrapper(TestAapsSchedulers())
+ hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context, repository)
`when`(activePluginProvider.activePump).thenReturn(testPumpPlugin)
`when`(resourceHelper.gs(R.string.profile_per_unit)).thenReturn("/U")
`when`(resourceHelper.gs(R.string.profile_carbs_per_unit)).thenReturn("g/U")
@@ -69,10 +72,10 @@ class ProfileTest : TestBase() {
// Test valid profile
var p = ProfileSealed.Pure(pureProfileFromJson(JSONObject(okProfile), dateUtil)!!)
- Assert.assertEquals(true, p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus))
+ Assert.assertEquals(true, p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus, hardLimits).isValid)
// Assert.assertEquals(true, p.log().contains("NS units: mmol"))
// JSONAssert.assertEquals(JSONObject(okProfile), p.toPureNsJson(dateUtil), false)
- Assert.assertEquals(3.0, p.dia, 0.01)
+ Assert.assertEquals(5.0, p.dia, 0.01)
// Assert.assertEquals(TimeZone.getTimeZone("UTC"), p.timeZone)
Assert.assertEquals("00:30", dateUtil.format_HH_MM(30 * 60))
val c = Calendar.getInstance()
@@ -80,13 +83,13 @@ class ProfileTest : TestBase() {
c[Calendar.MINUTE] = 0
c[Calendar.SECOND] = 0
c[Calendar.MILLISECOND] = 0
- Assert.assertEquals(1800.0, p.getIsfMgdl(c.timeInMillis), 0.01)
+ Assert.assertEquals(108.0, p.getIsfMgdl(c.timeInMillis), 0.01)
c[Calendar.HOUR_OF_DAY] = 2
- Assert.assertEquals(1980.0, p.getIsfMgdl(c.timeInMillis), 0.01)
+ Assert.assertEquals(111.6, p.getIsfMgdl(c.timeInMillis), 0.01)
// Assert.assertEquals(110.0, p.getIsfTimeFromMidnight(2 * 60 * 60), 0.01)
Assert.assertEquals("""
- 00:00 100,0 mmol/U
- 02:00 110,0 mmol/U
+ 00:00 6,0 mmol/U
+ 02:00 6,2 mmol/U
""".trimIndent(), p.getIsfList(resourceHelper, dateUtil).replace(".", ","))
Assert.assertEquals(30.0, p.getIc(c.timeInMillis), 0.01)
Assert.assertEquals(30.0, p.getIcTimeFromMidnight(2 * 60 * 60), 0.01)
@@ -121,7 +124,7 @@ class ProfileTest : TestBase() {
//Test basal profile below limit
p = ProfileSealed.Pure(pureProfileFromJson(JSONObject(belowLimitValidProfile), dateUtil)!!)
- p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus)
+ p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus, hardLimits)
// Test profile w/o units
Assert.assertNull(pureProfileFromJson(JSONObject(noUnitsValidProfile), dateUtil))
@@ -139,21 +142,21 @@ class ProfileTest : TestBase() {
Assert.assertEquals(0.05, p.getBasal(c.timeInMillis), 0.01)
Assert.assertEquals(1.2, p.percentageBasalSum(), 0.01)
Assert.assertEquals(60.0, p.getIc(c.timeInMillis), 0.01)
- Assert.assertEquals(3960.0, p.getIsfMgdl(c.timeInMillis), 0.01)
+ Assert.assertEquals(223.2, p.getIsfMgdl(c.timeInMillis), 0.01)
// Test timeshift functionality
p = ProfileSealed.Pure(pureProfileFromJson(JSONObject(okProfile), dateUtil)!!)
p.ts = 1
Assert.assertEquals(
"""
- 00:00 110.0 mmol/U
- 01:00 100.0 mmol/U
- 03:00 110.0 mmol/U
+ 00:00 6.2 mmol/U
+ 01:00 6.0 mmol/U
+ 03:00 6.2 mmol/U
""".trimIndent(), p.getIsfList(resourceHelper, dateUtil))
// Test hour alignment
testPumpPlugin.pumpDescription.is30minBasalRatesCapable = false
p = ProfileSealed.Pure(pureProfileFromJson(JSONObject(notAlignedBasalValidProfile), dateUtil)!!)
- p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus)
+ p.isValid("Test", testPumpPlugin, config, resourceHelper, rxBus, hardLimits)
}
}
\ No newline at end of file