Merge branch 'dev2_dana_combo_only' into meallink-mdt

This commit is contained in:
Andy Rozman 2021-05-01 12:11:29 +01:00
commit 67a2c0dca3
231 changed files with 9007 additions and 2152 deletions

View file

@ -14,7 +14,7 @@ import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSPlugin
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase

View file

@ -7,14 +7,16 @@ import android.text.TextWatcher
import android.view.Menu import android.view.Menu
import android.widget.PopupMenu import android.widget.PopupMenu
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.data.PureProfile
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
import info.nightscout.androidaps.data.defaultProfile.DefaultProfileDPV import info.nightscout.androidaps.data.defaultProfile.DefaultProfileDPV
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.databinding.ActivityProfilehelperBinding import info.nightscout.androidaps.databinding.ActivityProfilehelperBinding
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -24,7 +26,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.stats.TddCalculator import info.nightscout.androidaps.utils.stats.TddCalculator
import java.text.DecimalFormat import java.text.DecimalFormat
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +41,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var repository: AppRepository
enum class ProfileType { enum class ProfileType {
MOTOL_DEFAULT, MOTOL_DEFAULT,
@ -61,7 +62,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
private lateinit var profileList: ArrayList<CharSequence> private lateinit var profileList: ArrayList<CharSequence>
private val profileUsed = arrayOf(0, 0) private val profileUsed = arrayOf(0, 0)
private lateinit var profileSwitch: List<ProfileSwitch> private lateinit var profileSwitch: List<EffectiveProfileSwitch>
private val profileSwitchUsed = arrayOf(0, 0) private val profileSwitchUsed = arrayOf(0, 0)
private lateinit var binding: ActivityProfilehelperBinding private lateinit var binding: ActivityProfilehelperBinding
@ -114,12 +115,12 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
} }
// Profile switch // Profile switch
profileSwitch = databaseHelper.getProfileSwitchData(dateUtil.now() - T.months(2).msecs(), true) profileSwitch = repository.getEffectiveProfileSwitchDataFromTime(dateUtil.now() - T.months(2).msecs(), true).blockingGet()
binding.profileswitchList.setOnClickListener { binding.profileswitchList.setOnClickListener {
PopupMenu(this, binding.profileswitchList).apply { PopupMenu(this, binding.profileswitchList).apply {
var order = 0 var order = 0
for (name in profileSwitch) menu.add(Menu.NONE, order, order++, name.customizedName) for (name in profileSwitch) menu.add(Menu.NONE, order, order++, name.originalCustomizedName)
setOnMenuItemClickListener { item -> setOnMenuItemClickListener { item ->
binding.profileswitchList.setText(item.title) binding.profileswitchList.setText(item.title)
profileSwitchUsed[tabSelected] = item.itemId profileSwitchUsed[tabSelected] = item.itemId
@ -212,9 +213,8 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", dateUtil.now()) it.putLong("time", dateUtil.now())
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal) it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
it.putString("customProfile", profile0.data.toString()) it.putString("customProfile", profile0.jsonObject.toString())
it.putString("customProfile2", profile1.data.toString()) it.putString("customProfile2", profile1.jsonObject.toString())
it.putString("customProfileUnits", profileFunction.getUnits())
it.putString("customProfileName", getProfileName(ageUsed[0], tddUsed[0], weightUsed[0], pctUsed[0] / 100.0, 0) + "\n" + getProfileName(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1)) it.putString("customProfileName", getProfileName(ageUsed[0], tddUsed[0], weightUsed[0], pctUsed[0] / 100.0, 0) + "\n" + getProfileName(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1))
} }
}.show(supportFragmentManager, "ProfileViewDialog") }.show(supportFragmentManager, "ProfileViewDialog")
@ -227,14 +227,14 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
switchTab(0, typeSelected[0], false) switchTab(0, typeSelected[0], false)
} }
private fun getProfile(age: Double, tdd: Double, weight: Double, basalPct: Double, tab: Int): Profile? = private fun getProfile(age: Double, tdd: Double, weight: Double, basalPct: Double, tab: Int): PureProfile? =
try { // profile must not exist try { // profile must not exist
when (typeSelected[tab]) { when (typeSelected[tab]) {
ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits()) ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits()) ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits())
ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile() ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile(dateUtil)
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileSource.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString()) ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileSource.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile() ProfileType.PROFILE_SWITCH -> ProfileSealed.EPS(profileSwitch[profileSwitchUsed[tab]]).convertToNonCustomizedProfile(dateUtil)
} }
} catch (e: Exception) { } catch (e: Exception) {
null null
@ -246,7 +246,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.formatwittddandpct, age, tdd, (basalSumPct * 100).toInt()) ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.formatwittddandpct, age, tdd, (basalSumPct * 100).toInt())
ProfileType.CURRENT -> profileFunction.getProfileName() ProfileType.CURRENT -> profileFunction.getProfileName()
ProfileType.AVAILABLE_PROFILE -> profileList[profileUsed[tab]].toString() ProfileType.AVAILABLE_PROFILE -> profileList[profileUsed[tab]].toString()
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].customizedName ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].originalCustomizedName
} }
private fun storeValues() { private fun storeValues() {
@ -289,7 +289,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
if (profileList.isNotEmpty()) if (profileList.isNotEmpty())
binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString()) binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString())
if (profileSwitch.isNotEmpty()) if (profileSwitch.isNotEmpty())
binding.profileswitchList.setText(profileSwitch[profileSwitchUsed[tabSelected]].customizedName) binding.profileswitchList.setText(profileSwitch[profileSwitchUsed[tabSelected]].originalCustomizedName)
} }
private fun setBackgroundColorOnSelected(tab: Int) { private fun setBackgroundColorOnSelected(tab: Int) {

View file

@ -71,9 +71,8 @@ class SurveyActivity : NoSplashAppCompatActivity() {
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", dateUtil.now()) it.putLong("time", dateUtil.now())
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal) it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
it.putString("customProfile", runningProfile.data.toString()) it.putString("customProfile", runningProfile.toPureNsJson(dateUtil).toString())
it.putString("customProfile2", profile.data.toString()) it.putString("customProfile2", profile.jsonObject.toString())
it.putString("customProfileUnits", profile.units)
it.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight") it.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
} }
}.show(supportFragmentManager, "ProfileViewDialog") }.show(supportFragmentManager, "ProfileViewDialog")

View file

@ -1,7 +1,12 @@
package info.nightscout.androidaps.data.defaultProfile package info.nightscout.androidaps.data.defaultProfile
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileImplOld
import info.nightscout.androidaps.data.PureProfile
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
@ -10,14 +15,14 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class DefaultProfile @Inject constructor(val injector: HasAndroidInjector) { class DefaultProfile @Inject constructor(val dateUtil: DateUtil) {
var oneToFive: TreeMap<Double, Array<Double>> = TreeMap() var oneToFive: TreeMap<Double, Array<Double>> = TreeMap()
var sixToEleven: TreeMap<Double, Array<Double>> = TreeMap() var sixToEleven: TreeMap<Double, Array<Double>> = TreeMap()
var twelveToSeventeen: TreeMap<Double, Array<Double>> = TreeMap() var twelveToSeventeen: TreeMap<Double, Array<Double>> = TreeMap()
var eighteenToTwentyfor: TreeMap<Double, Array<Double>> = TreeMap() var eighteenToTwentyFour: TreeMap<Double, Array<Double>> = TreeMap()
fun profile(age: Double, tdd: Double, weight: Double, units: String): Profile? { fun profile(age: Double, tdd: Double, weight: Double, units: GlucoseUnit): PureProfile? {
val profile = JSONObject() val profile = JSONObject()
if (age >= 1 && age < 6) { if (age >= 1 && age < 6) {
val _tdd = if (tdd == 0.0) 0.6 * weight else tdd val _tdd = if (tdd == 0.0) 0.6 * weight else tdd
@ -49,8 +54,8 @@ class DefaultProfile @Inject constructor(val injector: HasAndroidInjector) {
profile.put("timezone", TimeZone.getDefault().id) profile.put("timezone", TimeZone.getDefault().id)
profile.put("target_high", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units)))) profile.put("target_high", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units))))
profile.put("target_low", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units)))) profile.put("target_low", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units))))
profile.put("units", units) profile.put("units", units.asText)
return Profile(injector, profile, units) return pureProfileFromJson(profile, dateUtil)
} }
init { init {
@ -148,7 +153,7 @@ class DefaultProfile @Inject constructor(val injector: HasAndroidInjector) {
return array return array
} }
private fun singleValueArrayFromMmolToUnits(value: Double, sample: Array<Double>, units: String): JSONArray { private fun singleValueArrayFromMmolToUnits(value: Double, sample: Array<Double>, units: GlucoseUnit): JSONArray {
val array = JSONArray() val array = JSONArray()
array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value + sample[0],units)).put("timeAsSeconds", 0 * 3600)) array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value + sample[0],units)).put("timeAsSeconds", 0 * 3600))
array.put(JSONObject().put("time", "06:00").put("value", Profile.fromMmolToUnits(value + sample[1],units)).put("timeAsSeconds", 6 * 3600)) array.put(JSONObject().put("time", "06:00").put("value", Profile.fromMmolToUnits(value + sample[1],units)).put("timeAsSeconds", 6 * 3600))

View file

@ -1,8 +1,12 @@
package info.nightscout.androidaps.data.defaultProfile package info.nightscout.androidaps.data.defaultProfile
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileImplOld
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.data.PureProfile
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.util.* import java.util.*
@ -10,13 +14,13 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector) { class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector, val dateUtil: DateUtil) {
var oneToFive = arrayOf(3.97, 3.61, 3.46, 3.70, 3.76, 3.87, 4.18, 4.01, 3.76, 3.54, 3.15, 2.80, 2.86, 3.21, 3.61, 3.97, 4.43, 4.96, 5.10, 5.50, 5.81, 6.14, 5.52, 5.10) var oneToFive = arrayOf(3.97, 3.61, 3.46, 3.70, 3.76, 3.87, 4.18, 4.01, 3.76, 3.54, 3.15, 2.80, 2.86, 3.21, 3.61, 3.97, 4.43, 4.96, 5.10, 5.50, 5.81, 6.14, 5.52, 5.10)
var sixToEleven = arrayOf(4.20, 4.27, 4.41, 4.62, 4.92, 5.09, 5.01, 4.47, 3.89, 3.33, 3.10, 2.91, 2.97, 3.08, 3.36, 3.93, 4.52, 4.76, 4.69, 4.63, 4.63, 4.47, 4.47, 4.31) var sixToEleven = arrayOf(4.20, 4.27, 4.41, 4.62, 4.92, 5.09, 5.01, 4.47, 3.89, 3.33, 3.10, 2.91, 2.97, 3.08, 3.36, 3.93, 4.52, 4.76, 4.69, 4.63, 4.63, 4.47, 4.47, 4.31)
var twelveToEighteen = arrayOf(3.47, 3.80, 4.31, 4.95, 5.59, 6.11, 5.89, 5.11, 4.31, 3.78, 3.55, 3.39, 3.35, 3.39, 3.64, 3.97, 4.53, 4.59, 4.50, 4.00, 3.69, 3.39, 3.35, 3.35) var twelveToEighteen = arrayOf(3.47, 3.80, 4.31, 4.95, 5.59, 6.11, 5.89, 5.11, 4.31, 3.78, 3.55, 3.39, 3.35, 3.39, 3.64, 3.97, 4.53, 4.59, 4.50, 4.00, 3.69, 3.39, 3.35, 3.35)
fun profile(age: Double, tdd: Double, basalSumPct: Double, units: String): Profile? { fun profile(age: Double, tdd: Double, basalSumPct: Double, units: GlucoseUnit): PureProfile? {
val basalSum = tdd * basalSumPct val basalSum = tdd * basalSumPct
val profile = JSONObject() val profile = JSONObject()
if (age >= 1 && age < 6) { if (age >= 1 && age < 6) {
@ -40,8 +44,8 @@ class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector) {
profile.put("timezone", TimeZone.getDefault().id) profile.put("timezone", TimeZone.getDefault().id)
profile.put("target_high", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units)))) profile.put("target_high", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units))))
profile.put("target_low", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units)))) profile.put("target_low", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units))))
profile.put("units", units) profile.put("units", units.asText)
return Profile(injector, profile, units) return pureProfileFromJson(profile, dateUtil)
} }
private fun arrayToJson(b: Array<Double>, basalSum: Double): JSONArray { private fun arrayToJson(b: Array<Double>, basalSum: Double): JSONArray {
@ -59,7 +63,7 @@ class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector) {
return array return array
} }
private fun singleValueArrayFromMmolToUnits(value: Double, units: String): JSONArray { private fun singleValueArrayFromMmolToUnits(value: Double, units: GlucoseUnit): JSONArray {
val array = JSONArray() val array = JSONArray()
array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value, units)).put("timeAsSeconds", 0 * 3600)) array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value, units)).put("timeAsSeconds", 0 * 3600))
return array return array

View file

@ -74,5 +74,13 @@ class CompatDBHelper @Inject constructor(
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged") aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventFoodDatabaseChanged()) rxBus.send(EventFoodDatabaseChanged())
} }
it.filterIsInstance<ProfileSwitch>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventProfileNeedsUpdate")
rxBus.send(EventProfileSwitchChanged())
}
it.filterIsInstance<EffectiveProfileSwitch>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventProfileNeedsUpdate")
rxBus.send(EventProfileSwitchChanged())
}
} }
} }

View file

@ -16,31 +16,19 @@ import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils; import com.j256.ormlite.table.TableUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import info.nightscout.androidaps.dana.comm.RecordTypes;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventProfileNeedsUpdate;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.interfaces.ActivePlugin;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.ProfileSource;
import info.nightscout.androidaps.interfaces.ProfileStore;
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.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
@ -48,7 +36,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.PercentageSplitter;
/** /**
* This Helper contains all resource to provide a central DB management functionality. Only methods handling * This Helper contains all resource to provide a central DB management functionality. Only methods handling
@ -75,9 +62,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static Long earliestDataChange = null; public static Long earliestDataChange = null;
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
private int oldVersion = 0; private int oldVersion = 0;
private int newVersion = 0; private int newVersion = 0;
@ -96,7 +80,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
@ -124,7 +107,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
onCreate(database, connectionSource); onCreate(database, connectionSource);
} else if (oldVersion < 10) { } else if (oldVersion < 10) {
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
@ -171,20 +153,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true); TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class);
updateEarliestDataChange(0); updateEarliestDataChange(0);
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
virtualPumpPlugin.setFakingStatus(true); virtualPumpPlugin.setFakingStatus(true);
scheduleProfileSwitchChange();
new java.util.Timer().schedule( new java.util.Timer().schedule(
new java.util.TimerTask() { new java.util.TimerTask() {
@Override @Override
@ -196,16 +175,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
); );
} }
public void resetProfileSwitch() {
try {
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
scheduleProfileSwitchChange();
}
// ------------------ getDao ------------------------------------------- // ------------------ getDao -------------------------------------------
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException { private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
@ -224,10 +193,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(ExtendedBolus.class); return getDao(ExtendedBolus.class);
} }
private Dao<ProfileSwitch, Long> getDaoProfileSwitch() throws SQLException {
return getDao(ProfileSwitch.class);
}
private Dao<InsightPumpID, Long> getDaoInsightPumpID() throws SQLException { private Dao<InsightPumpID, Long> getDaoInsightPumpID() throws SQLException {
return getDao(InsightPumpID.class); return getDao(InsightPumpID.class);
} }
@ -580,104 +545,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// ---------------- ProfileSwitch handling --------------- // ---------------- ProfileSwitch handling ---------------
public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) { /*
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(100L);
Where where = queryBuilder.where();
where.ge("date", from);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
//add last one without duration
ProfileSwitch last = getLastProfileSwitchWithoutDuration();
if (last != null) {
if (!isInList(profileSwitches, last))
profileSwitches.add(last);
}
return profileSwitches;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<>();
}
boolean isInList(List<ProfileSwitch> profileSwitches, ProfileSwitch last) {
for (ProfileSwitch ps : profileSwitches) {
if (ps.isEqual(last)) return true;
}
return false;
}
public List<ProfileSwitch> getAllProfileSwitches() {
try {
return getDaoProfileSwitch().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return Collections.emptyList();
}
@Nullable
private ProfileSwitch getLastProfileSwitchWithoutDuration() {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(1L);
Where where = queryBuilder.where();
where.eq("durationInMinutes", 0);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
if (profileSwitches.size() > 0)
return profileSwitches.get(0);
else
return null;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
}
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long mills, boolean ascending) {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(100L);
Where where = queryBuilder.where();
where.ge("date", mills);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
return profileSwitches;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long from, long to, boolean ascending) {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(100L);
Where where = queryBuilder.where();
where.between("date", from, to);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
return profileSwitches;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdate(ProfileSwitch profileSwitch) { public boolean createOrUpdate(ProfileSwitch profileSwitch) {
try { try {
ProfileSwitch old; ProfileSwitch old;
@ -767,7 +635,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduledProfileSwitchEventPost = profileSwitchEventWorker.schedule(task, sec, TimeUnit.SECONDS); scheduledProfileSwitchEventPost = profileSwitchEventWorker.schedule(task, sec, TimeUnit.SECONDS);
} }
*/
/* /*
{ {
"_id":"592fa43ed97496a80da913d2", "_id":"592fa43ed97496a80da913d2",
@ -779,6 +647,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
"NSCLIENT_ID":1496294454309, "NSCLIENT_ID":1496294454309,
} }
*/ */
/*
public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) { public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) {
try { try {
@ -800,9 +669,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
ProfileSource profileSource = activePlugin.getActiveProfileSource(); ProfileSource profileSource = activePlugin.getActiveProfileSource();
ProfileStore store = profileSource.getProfile(); ProfileStore store = profileSource.getProfile();
if (store != null) { if (store != null) {
Profile profile = store.getSpecificProfile(profileSwitch.profileName); PureProfile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) { if (profile != null) {
profileSwitch.profileJson = profile.getData().toString(); profileSwitch.profileJson = profile.getJsonObject().toString();
aapsLogger.debug(LTag.DATABASE, "Profile switch prefilled with JSON from local store"); aapsLogger.debug(LTag.DATABASE, "Profile switch prefilled with JSON from local store");
// Update data in NS // Update data in NS
nsUpload.updateProfileSwitch(profileSwitch, dateUtil); nsUpload.updateProfileSwitch(profileSwitch, dateUtil);
@ -850,7 +719,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
return null; return null;
} }
*/
// ---------------- Insight history handling --------------- // ---------------- Insight history handling ---------------
public void createOrUpdate(InsightHistoryOffset offset) { public void createOrUpdate(InsightHistoryOffset offset) {
@ -1059,7 +928,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public long getCountOfAllRows() { public long getCountOfAllRows() {
try { try {
return getDaoExtendedBolus().countOf() return getDaoExtendedBolus().countOf()
+ getDaoProfileSwitch().countOf()
+ getDaoTemporaryBasal().countOf(); + getDaoTemporaryBasal().countOf();
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);

View file

@ -88,10 +88,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().findOmnipodHistoryRecordByPumpId(pumpId); return MainApp.Companion.getDbHelper().findOmnipodHistoryRecordByPumpId(pumpId);
} }
@NonNull @Override public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) {
return MainApp.Companion.getDbHelper().getProfileSwitchData(from, ascending);
}
@Override public void createOrUpdate(@NonNull InsightBolusID record) { @Override public void createOrUpdate(@NonNull InsightBolusID record) {
MainApp.Companion.getDbHelper().createOrUpdate(record); MainApp.Companion.getDbHelper().createOrUpdate(record);
} }
@ -124,18 +120,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getPumpStoppedEvent(pumpSerial, before); return MainApp.Companion.getDbHelper().getPumpStoppedEvent(pumpSerial, before);
} }
@Override public void createOrUpdate(@NonNull ProfileSwitch profileSwitch) {
MainApp.Companion.getDbHelper().createOrUpdate(profileSwitch);
}
@Override public void deleteProfileSwitchById(@NonNull String _id) {
MainApp.Companion.getDbHelper().deleteProfileSwitchById(_id);
}
@Override public void createProfileSwitchFromJsonIfNotExists(@NonNull JSONObject trJson) {
MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson);
}
@Override public void resetDatabases() { @Override public void resetDatabases() {
MainApp.Companion.getDbHelper().resetDatabases(); MainApp.Companion.getDbHelper().resetDatabases();
} }
@ -144,30 +128,10 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
MainApp.Companion.getDbHelper().createOrUpdate(record); MainApp.Companion.getDbHelper().createOrUpdate(record);
} }
@Override public void delete(@NonNull ProfileSwitch profileSwitch) {
MainApp.Companion.getDbHelper().delete(profileSwitch);
}
@NonNull @Override public List<ProfileSwitch> getProfileSwitchEventsFromTime(long from, long to, boolean ascending) {
return MainApp.Companion.getDbHelper().getProfileSwitchEventsFromTime(from, to, ascending);
}
@NonNull @Override public List<ProfileSwitch> getProfileSwitchEventsFromTime(long mills, boolean ascending) {
return MainApp.Companion.getDbHelper().getProfileSwitchEventsFromTime(mills, ascending);
}
@NonNull @Override public List<ProfileSwitch> getAllProfileSwitches() {
return MainApp.Companion.getDbHelper().getAllProfileSwitches();
}
@NonNull @Override public List<OHQueueItem> getAllOHQueueItems(long maxEntries) { @NonNull @Override public List<OHQueueItem> getAllOHQueueItems(long maxEntries) {
return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries); return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries);
} }
@Override public void resetProfileSwitch() {
MainApp.Companion.getDbHelper().resetProfileSwitch();
}
@Override public long getOHQueueSize() { @Override public long getOHQueueSize() {
return MainApp.Companion.getDbHelper().getOHQueueSize(); return MainApp.Companion.getDbHelper().getOHQueueSize();
} }

View file

@ -7,7 +7,7 @@ import dagger.android.AndroidInjector
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.automation.di.AutomationModule import info.nightscout.androidaps.automation.di.AutomationModule
import info.nightscout.androidaps.combo.di.ComboModule import info.nightscout.androidaps.combo.di.ComboModule
import info.nightscout.androidaps.core.di.CoreModule import info.nightscout.androidaps.di.CoreModule
import info.nightscout.androidaps.dana.di.DanaModule import info.nightscout.androidaps.dana.di.DanaModule
import info.nightscout.androidaps.danar.di.DanaRModule import info.nightscout.androidaps.danar.di.DanaRModule
import info.nightscout.androidaps.danars.di.DanaRSModule import info.nightscout.androidaps.danars.di.DanaRSModule

View file

@ -6,13 +6,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogCalibrationBinding import info.nightscout.androidaps.databinding.DialogCalibrationBinding
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
@ -57,13 +57,13 @@ class CalibrationDialog : DialogFragmentWithDate() {
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val bg = Profile.fromMgdlToUnits(glucoseStatusProvider.glucoseStatusData?.glucose val bg = Profile.fromMgdlToUnits(glucoseStatusProvider.glucoseStatusData?.glucose
?: 0.0, units) ?: 0.0, units)
if (units == Constants.MMOL) if (units == GlucoseUnit.MMOL)
binding.bg.setParams(savedInstanceState?.getDouble("bg") binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok) ?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok)
else else
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 == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) binding.units.text = if (units == GlucoseUnit.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
} }
override fun onDestroyView() { override fun onDestroyView() {
@ -74,14 +74,14 @@ class CalibrationDialog : DialogFragmentWithDate() {
override fun submit(): Boolean { override fun submit(): Boolean {
if (_binding == null) return false if (_binding == null) return false
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) val unitLabel = if (units == GlucoseUnit.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val bg = binding.bg.value ?: return false val bg = binding.bg.value ?: return false
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, bg) + " " + unitLabel) actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, bg) + " " + unitLabel)
if (bg > 0) { if (bg > 0) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.CALIBRATION, Sources.CalibrationDialog, ValueWithUnit.fromGlucoseUnit(bg, units)) uel.log(Action.CALIBRATION, Sources.CalibrationDialog, ValueWithUnit.fromGlucoseUnit(bg, units.asText))
xdripCalibrations.sendIntent(bg) xdripCalibrations.sendIntent(bg)
}) })
} }

View file

@ -8,11 +8,10 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
@ -22,6 +21,7 @@ import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAnd
import info.nightscout.androidaps.databinding.DialogCarbsBinding import info.nightscout.androidaps.databinding.DialogCarbsBinding
import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -184,7 +184,7 @@ class CarbsDialog : DialogFragmentWithDate() {
val hypoTTDuration = defaultValueHelper.determineHypoTTDuration() val hypoTTDuration = defaultValueHelper.determineHypoTTDuration()
val hypoTT = defaultValueHelper.determineHypoTT() val hypoTT = defaultValueHelper.determineHypoTT()
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) val unitLabel = if (units == GlucoseUnit.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val useAlarm = binding.alarmCheckBox.isChecked val useAlarm = binding.alarmCheckBox.isChecked
val activitySelected = binding.activityTt.isChecked val activitySelected = binding.activityTt.isChecked
@ -226,7 +226,7 @@ class CarbsDialog : DialogFragmentWithDate() {
activitySelected -> { activitySelected -> {
uel.log(Action.TT, Sources.CarbDialog, uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY),
ValueWithUnit.fromGlucoseUnit(activityTT, units), ValueWithUnit.fromGlucoseUnit(activityTT, units.asText),
ValueWithUnit.Minute(activityTTDuration)) ValueWithUnit.Minute(activityTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
@ -245,7 +245,7 @@ class CarbsDialog : DialogFragmentWithDate() {
eatingSoonSelected -> { eatingSoonSelected -> {
uel.log(Action.TT, Sources.CarbDialog, uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON),
ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units), ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units.asText),
ValueWithUnit.Minute(eatingSoonTTDuration)) ValueWithUnit.Minute(eatingSoonTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
@ -264,7 +264,7 @@ class CarbsDialog : DialogFragmentWithDate() {
hypoSelected -> { hypoSelected -> {
uel.log(Action.TT, Sources.CarbDialog, uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA),
ValueWithUnit.fromGlucoseUnit(hypoTT, units), ValueWithUnit.fromGlucoseUnit(hypoTT, units.asText),
ValueWithUnit.Minute(hypoTTDuration)) ValueWithUnit.Minute(hypoTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),

View file

@ -12,7 +12,7 @@ import com.google.common.base.Joiner
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
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
@ -29,6 +29,7 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.fromConstant import info.nightscout.androidaps.extensions.fromConstant
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -151,7 +152,7 @@ class CareDialog : DialogFragmentWithDate() {
} }
} }
if (profileFunction.getUnits() == Constants.MMOL) { if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
binding.bgunits.text = resourceHelper.gs(R.string.mmol) binding.bgunits.text = resourceHelper.gs(R.string.mmol)
binding.bg.setParams(savedInstanceState?.getDouble("bg") binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, bgTextWatcher) ?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, bgTextWatcher)
@ -173,7 +174,7 @@ class CareDialog : DialogFragmentWithDate() {
override fun submit(): Boolean { override fun submit(): Boolean {
val enteredBy = sp.getString("careportal_enteredby", "AndroidAPS") val enteredBy = sp.getString("careportal_enteredby", "AndroidAPS")
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol val unitResId = if (profileFunction.getUnits() == GlucoseUnit.MGDL) R.string.mgdl else R.string.mmol
eventTime -= eventTime % 1000 eventTime -= eventTime % 1000
@ -203,7 +204,7 @@ class CareDialog : DialogFragmentWithDate() {
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId)) actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId))
therapyEvent.glucoseType = meterType therapyEvent.glucoseType = meterType
therapyEvent.glucose = binding.bg.value therapyEvent.glucose = binding.bg.value
valuesWithUnit.add(ValueWithUnit.fromGlucoseUnit(binding.bg.value.toDouble(), profileFunction.getUnits())) valuesWithUnit.add(ValueWithUnit.fromGlucoseUnit(binding.bg.value.toDouble(), profileFunction.getUnits().asText))
valuesWithUnit.add(ValueWithUnit.TherapyEventMeterType(meterType)) valuesWithUnit.add(ValueWithUnit.TherapyEventMeterType(meterType))
} }
if (options == EventType.NOTE || options == EventType.EXERCISE) { if (options == EventType.NOTE || options == EventType.EXERCISE) {

View file

@ -8,12 +8,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -21,10 +18,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -34,6 +27,7 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.extensions.toSignedString import info.nightscout.androidaps.utils.extensions.toSignedString
import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -158,7 +152,7 @@ class InsulinDialog : DialogFragmentWithDate() {
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) val unitLabel = if (units == GlucoseUnit.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val recordOnlyChecked = binding.recordOnly.isChecked val recordOnlyChecked = binding.recordOnly.isChecked
val eatingSoonChecked = binding.startEatingSoonTt.isChecked val eatingSoonChecked = binding.startEatingSoonTt.isChecked
@ -190,7 +184,7 @@ class InsulinDialog : DialogFragmentWithDate() {
uel.log(Action.TT, Sources.InsulinDialog, uel.log(Action.TT, Sources.InsulinDialog,
notes, notes,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON),
ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units), ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units.asText),
ValueWithUnit.Minute(eatingSoonTTDuration)) ValueWithUnit.Minute(eatingSoonTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),

View file

@ -8,17 +8,18 @@ import android.widget.ArrayAdapter
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources 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.databinding.DialogProfileswitchBinding
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -27,12 +28,14 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private var profileIndex: Int? = null private var profileIndex: Int? = null
private val disposable = CompositeDisposable()
private var _binding: DialogProfileswitchBinding? = null private var _binding: DialogProfileswitchBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
@ -78,17 +81,17 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
binding.profile.setSelection(profileIndex as Int) binding.profile.setSelection(profileIndex as Int)
else else
for (p in profileList.indices) for (p in profileList.indices)
if (profileList[p] == profileFunction.getProfileName(false)) if (profileList[p] == profileFunction.getOriginalProfileName())
binding.profile.setSelection(p) binding.profile.setSelection(p)
} ?: return } ?: return
treatmentsPlugin.getProfileSwitchFromHistory(dateUtil.now())?.let { ps -> profileFunction.getProfile()?.let { profile ->
if (ps.isCPP) { if (profile.percentage != 100 || profile.timeshift != 0) {
binding.reuselayout.visibility = View.VISIBLE binding.reuselayout.visibility = View.VISIBLE
binding.reusebutton.text = resourceHelper.gs(R.string.reuse_profile_pct_hours, ps.percentage, ps.timeshift) binding.reusebutton.text = resourceHelper.gs(R.string.reuse_profile_pct_hours, profile.percentage, profile.timeshift)
binding.reusebutton.setOnClickListener { binding.reusebutton.setOnClickListener {
binding.percentage.value = ps.percentage.toDouble() binding.percentage.value = profile.percentage.toDouble()
binding.timeshift.value = ps.timeshift.toDouble() binding.timeshift.value = profile.timeshift.toDouble()
} }
} else { } else {
binding.reuselayout.visibility = View.GONE binding.reuselayout.visibility = View.GONE
@ -98,6 +101,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
disposable.clear()
_binding = null _binding = null
} }
@ -108,10 +112,10 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
val duration = binding.duration.value?.toInt() ?: return false val duration = binding.duration.value?.toInt() ?: return false
if (duration > 0) if (duration > 0L)
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
val profile = binding.profile.selectedItem.toString() val profileName = binding.profile.selectedItem.toString()
actions.add(resourceHelper.gs(R.string.profile) + ": " + profile) actions.add(resourceHelper.gs(R.string.profile) + ": " + profileName)
val percent = binding.percentage.value.toInt() val percent = binding.percentage.value.toInt()
if (percent != 100) if (percent != 100)
actions.add(resourceHelper.gs(R.string.percent) + ": " + percent + "%") actions.add(resourceHelper.gs(R.string.percent) + ": " + percent + "%")
@ -126,15 +130,20 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
profileFunction.createProfileSwitch(profileStore,
profileName = profileName,
durationInMinutes = duration,
percentage = percent,
timeShiftInHours = timeShift,
timestamp = eventTime)
uel.log(Action.PROFILE_SWITCH, uel.log(Action.PROFILE_SWITCH,
Sources.ProfileSwitchDialog, Sources.ProfileSwitchDialog,
notes, notes,
ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
ValueWithUnit.SimpleString(profile), ValueWithUnit.SimpleString(profileName),
ValueWithUnit.Percent(percent), ValueWithUnit.Percent(percent),
ValueWithUnit.Hour(timeShift).takeIf { timeShift != 0 }, ValueWithUnit.Hour(timeShift).takeIf { timeShift != 0 },
ValueWithUnit.Minute(duration).takeIf { duration != 0 }) ValueWithUnit.Minute(duration).takeIf { duration != 0 })
treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
}) })
} }
return true return true

View file

@ -71,7 +71,7 @@ class TempBasalDialog : DialogFragmentWithDate() {
?: 100.0, 0.0, maxTempPercent, tempPercentStep, DecimalFormat("0"), true, binding.okcancel.ok) ?: 100.0, 0.0, maxTempPercent, tempPercentStep, DecimalFormat("0"), true, binding.okcancel.ok)
binding.basalabsoluteinput.setParams(savedInstanceState?.getDouble("basalabsoluteinput") binding.basalabsoluteinput.setParams(savedInstanceState?.getDouble("basalabsoluteinput")
?: profile.basal, 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, binding.okcancel.ok) ?: profile.getBasal(), 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, binding.okcancel.ok)
val tempDurationStep = pumpDescription.tempDurationStep.toDouble() val tempDurationStep = pumpDescription.tempDurationStep.toDouble()
val tempMaxDuration = pumpDescription.tempMaxDuration.toDouble() val tempMaxDuration = pumpDescription.tempMaxDuration.toDouble()

View file

@ -9,7 +9,7 @@ import com.google.common.base.Joiner
import com.google.common.collect.Lists import com.google.common.collect.Lists
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
@ -19,6 +19,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogTemptargetBinding import info.nightscout.androidaps.databinding.DialogTemptargetBinding
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -72,7 +73,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
binding.duration.setParams(savedInstanceState?.getDouble("duration") binding.duration.setParams(savedInstanceState?.getDouble("duration")
?: 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 (profileFunction.getUnits() == Constants.MMOL) if (profileFunction.getUnits() == GlucoseUnit.MMOL)
binding.temptarget.setParams( binding.temptarget.setParams(
savedInstanceState?.getDouble("tempTarget") savedInstanceState?.getDouble("tempTarget")
?: 8.0, ?: 8.0,
@ -84,7 +85,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, binding.okcancel.ok) Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
binding.units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) binding.units.text = if (units == GlucoseUnit.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
// temp target // temp target
context?.let { context -> context?.let { context ->
@ -163,7 +164,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
if (_binding == null) return false if (_binding == null) return false
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
var reason = binding.reason.selectedItem?.toString() ?: return false var reason = binding.reason.selectedItem?.toString() ?: return false
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol val unitResId = if (profileFunction.getUnits() == GlucoseUnit.MGDL) R.string.mgdl else R.string.mmol
val target = binding.temptarget.value val target = binding.temptarget.value
val duration = binding.duration.value.toInt() val duration = binding.duration.value.toInt()
if (target != 0.0 && duration != 0) { if (target != 0.0 && duration != 0) {
@ -181,10 +182,10 @@ class TempTargetDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
when(reason) { when(reason) {
resourceHelper.gs(R.string.eatingsoon) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration)) resourceHelper.gs(R.string.eatingsoon) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON), ValueWithUnit.fromGlucoseUnit(target, units.asText), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.activity) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration)) resourceHelper.gs(R.string.activity) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY), ValueWithUnit.fromGlucoseUnit(target, units.asText), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.hypo) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration)) resourceHelper.gs(R.string.hypo) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA), ValueWithUnit.fromGlucoseUnit(target, units.asText), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.manual) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.CUSTOM), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration)) resourceHelper.gs(R.string.manual) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.CUSTOM), ValueWithUnit.fromGlucoseUnit(target, units.asText), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }) resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged })
} }
if (target == 0.0 || duration == 0) { if (target == 0.0 || duration == 0) {

View file

@ -18,15 +18,11 @@ import dagger.android.HasAndroidInjector
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.databinding.DialogWizardBinding import info.nightscout.androidaps.databinding.DialogWizardBinding
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
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.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -38,6 +34,7 @@ import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnits import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.interfaces.*
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.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -128,7 +125,7 @@ class WizardDialog : DaggerDialogFragment() {
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value() val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
val maxCorrection = constraintChecker.getMaxBolusAllowed().value() val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
if (profileFunction.getUnits() == Constants.MGDL) if (profileFunction.getUnits() == GlucoseUnit.MGDL)
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input")
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher)
else else
@ -260,8 +257,8 @@ class WizardDialog : DaggerDialogFragment() {
} ?: return } ?: return
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
binding.bgunits.text = units binding.bgunits.text = units.asText
if (units == Constants.MGDL) if (units == GlucoseUnit.MGDL)
binding.bgInput.setStep(1.0) binding.bgInput.setStep(1.0)
else else
binding.bgInput.setStep(0.1) binding.bgInput.setStep(0.1)
@ -292,7 +289,7 @@ class WizardDialog : DaggerDialogFragment() {
specificProfile = profileFunction.getProfile() specificProfile = profileFunction.getProfile()
profileName = profileFunction.getProfileName() profileName = profileFunction.getProfileName()
} else } else
specificProfile = profileStore.getSpecificProfile(profileName) specificProfile = profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(it) }
if (specificProfile == null) return if (specificProfile == null) return
@ -333,7 +330,7 @@ class WizardDialog : DaggerDialogFragment() {
binding.notes.text.toString(), carbTime) binding.notes.text.toString(), carbTime)
wizard?.let { wizard -> wizard?.let { wizard ->
binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits()), wizard.sens) binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits().asText), wizard.sens)
binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG) binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)

View file

@ -9,7 +9,7 @@ import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.entities.BolusCalculatorResult import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.databinding.DialogWizardinfoBinding import info.nightscout.androidaps.databinding.DialogWizardinfoBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction

View file

@ -14,8 +14,10 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventCustomCalculationFinished import info.nightscout.androidaps.events.EventCustomCalculationFinished
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -23,14 +25,12 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -50,7 +50,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory @Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory
@Inject lateinit var treatmentsPluginHistory: TreatmentsPluginHistory
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -255,7 +254,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
private fun runCalculation(from: String) { private fun runCalculation(from: String) {
lifecycleScope.launch(Dispatchers.Default) { lifecycleScope.launch(Dispatchers.Default) {
treatmentsPluginHistory.initializeData(start - T.hours(8).msecs())
val end = start + T.hours(rangeToDisplay.toLong()).msecs() val end = start + T.hours(rangeToDisplay.toLong()).msecs()
iobCobCalculatorPluginHistory.stopCalculation(from) iobCobCalculatorPluginHistory.stopCalculation(from)
iobCobCalculatorPluginHistory.clearCache() iobCobCalculatorPluginHistory.clearCache()
@ -281,7 +279,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
if (destroyed) return@launch if (destroyed) return@launch
binding.date.text = dateUtil.dateAndTimeString(start) binding.date.text = dateUtil.dateAndTimeString(start)
binding.zoom.text = rangeToDisplay.toString() binding.zoom.text = rangeToDisplay.toString()
val graphData = GraphData(injector, binding.bggraph, iobCobCalculatorPluginHistory, treatmentsPluginHistory) val graphData = GraphData(injector, binding.bggraph, iobCobCalculatorPluginHistory)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList() val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
// do preparation in different thread // do preparation in different thread
@ -317,7 +315,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
// ------------------ 2nd graph // ------------------ 2nd graph
synchronized(graphLock) { synchronized(graphLock) {
for (g in 0 until secondaryGraphs.size) { for (g in 0 until secondaryGraphs.size) {
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory) val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory)
var useIobForScale = false var useIobForScale = false
var useCobForScale = false var useCobForScale = false
var useDevForScale = false var useDevForScale = false

View file

@ -1,48 +0,0 @@
package info.nightscout.androidaps.historyBrowser
import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.treatments.TreatmentService
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TreatmentsPluginHistory @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
aapsSchedulers: AapsSchedulers,
rxBus: RxBusWrapper,
resourceHelper: ResourceHelper,
context: Context,
sp: SP,
profileFunction: ProfileFunction,
activePlugin: ActivePlugin,
nsUpload: NSUpload,
fabricPrivacy: FabricPrivacy,
dateUtil: DateUtil,
databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, databaseHelper, repository) {
init {
onStart()
}
override fun onStart() {
service = TreatmentService(injector)
initializeData(range())
}
}

View file

@ -13,7 +13,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.* import info.nightscout.androidaps.*
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
@ -292,7 +292,7 @@ open class LoopPlugin @Inject constructor(
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) {
apsResult.usePercent = true apsResult.usePercent = true
} }
apsResult.percent = (apsResult.rate / profile.basal * 100).toInt() apsResult.percent = (apsResult.rate / profile.getBasal() * 100).toInt()
// check rate for constraints // check rate for constraints
val resultAfterConstraints = apsResult.newAndClone(injector) val resultAfterConstraints = apsResult.newAndClone(injector)

View file

@ -1,15 +1,15 @@
package info.nightscout.androidaps.plugins.aps.openAPSAMA package info.nightscout.androidaps.plugins.aps.openAPSAMA
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.data.Profile
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.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -162,13 +162,13 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
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))
this.profile.put("type", "current") this.profile.put("type", "current")
this.profile.put("max_daily_basal", profile.maxDailyBasal) this.profile.put("max_daily_basal", profile.getMaxDailyBasal())
this.profile.put("max_basal", maxBasal) this.profile.put("max_basal", maxBasal)
this.profile.put("min_bg", minBg) this.profile.put("min_bg", minBg)
this.profile.put("max_bg", maxBg) this.profile.put("max_bg", maxBg)
this.profile.put("target_bg", targetBg) this.profile.put("target_bg", targetBg)
this.profile.put("carb_ratio", profile.ic) this.profile.put("carb_ratio", profile.getIc())
this.profile.put("sens", profile.isfMgdl) 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("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)) this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
this.profile.put("skip_neutral_temps", true) this.profile.put("skip_neutral_temps", true)
@ -181,7 +181,7 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
} else { } else {
this.profile.put("min_5m_carbimpact", sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact)) this.profile.put("min_5m_carbimpact", sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact))
} }
if (profileFunction.getUnits() == Constants.MMOL) { if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
this.profile.put("out_units", "mmol/L") this.profile.put("out_units", "mmol/L")
} }
val now = System.currentTimeMillis() val now = System.currentTimeMillis()

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.aps.openAPSAMA
import android.content.Context import android.content.Context
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -112,9 +112,9 @@ open 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.targetLowMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
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) {
@ -125,8 +125,8 @@ open class OpenAPSAMAPlugin @Inject constructor(
} }
if (!hardLimits.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return 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.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) 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.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {

View file

@ -1,13 +1,16 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMB package info.nightscout.androidaps.plugins.aps.openAPSSMB
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.data.Profile 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.ActivePlugin
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.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -17,9 +20,6 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray import org.json.JSONArray
@ -180,13 +180,13 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
this.profile.put("max_iob", maxIob) this.profile.put("max_iob", maxIob)
//mProfile.put("dia", profile.getDia()); //mProfile.put("dia", profile.getDia());
this.profile.put("type", "current") this.profile.put("type", "current")
this.profile.put("max_daily_basal", profile.maxDailyBasal) this.profile.put("max_daily_basal", profile.getMaxDailyBasal())
this.profile.put("max_basal", maxBasal) this.profile.put("max_basal", maxBasal)
this.profile.put("min_bg", minBg) this.profile.put("min_bg", minBg)
this.profile.put("max_bg", maxBg) this.profile.put("max_bg", maxBg)
this.profile.put("target_bg", targetBg) this.profile.put("target_bg", targetBg)
this.profile.put("carb_ratio", profile.ic) this.profile.put("carb_ratio", profile.getIc())
this.profile.put("sens", profile.isfMgdl) 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("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)) this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
@ -225,7 +225,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
this.profile.put("current_basal", basalRate) this.profile.put("current_basal", basalRate)
this.profile.put("temptargetSet", tempTargetSet) this.profile.put("temptargetSet", tempTargetSet)
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2"))) this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
if (profileFunction.getUnits() == Constants.MMOL) { if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
this.profile.put("out_units", "mmol/L") this.profile.put("out_units", "mmol/L")
} }
val now = System.currentTimeMillis() val now = System.currentTimeMillis()

View file

@ -5,9 +5,9 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository 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.interfaces.* 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
@ -22,7 +22,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits 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.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -118,9 +117,9 @@ open class OpenAPSSMBPlugin @Inject constructor(
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
}.value() }.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, 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].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
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) {
@ -131,8 +130,8 @@ open class OpenAPSSMBPlugin @Inject constructor(
} }
if (!hardLimits.checkOnlyHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return 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.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), R.string.profile_sensitivity_value, HardLimits.MIN_ISF, HardLimits.MAX_ISF)) return
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, R.string.profile_max_daily_basal_value, 0.02, hardLimits.maxBasal())) 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.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {

View file

@ -14,7 +14,6 @@ import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.* import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.* import java.util.*
@ -28,7 +27,7 @@ class ObjectivesPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val sp: SP, private val sp: SP,
config: ConfigImpl, config: Config,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val uel: UserEntryLogger private val uel: UserEntryLogger
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()

View file

@ -2,6 +2,8 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
@ -9,14 +11,13 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import javax.inject.Inject import javax.inject.Inject
class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate) { class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate) {
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin @Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var repository: AppRepository
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var nsClientPlugin: NSClientPlugin @Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var iobCobCalculator: IobCobCalculator
@ -64,7 +65,7 @@ class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R
}) })
tasks.add(object : Task(this, R.string.activate_profile) { tasks.add(object : Task(this, R.string.activate_profile) {
override fun isCompleted(): Boolean { override fun isCompleted(): Boolean {
return treatmentsPlugin.getProfileSwitchFromHistory(dateUtil.now()) != null return repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
} }
}) })
} }

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.constraints.safety
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
@ -108,18 +108,18 @@ class SafetyPlugin @Inject constructor(
absoluteRate.setIfGreater(aapsLogger, 0.0, String.format(resourceHelper.gs(R.string.limitingbasalratio), 0.0, resourceHelper.gs(R.string.itmustbepositivevalue)), this) absoluteRate.setIfGreater(aapsLogger, 0.0, String.format(resourceHelper.gs(R.string.limitingbasalratio), 0.0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
if (config.APS) { if (config.APS) {
var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0) var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0)
if (maxBasal < profile.maxDailyBasal) { if (maxBasal < profile.getMaxDailyBasal()) {
maxBasal = profile.maxDailyBasal maxBasal = profile.getMaxDailyBasal()
absoluteRate.addReason(resourceHelper.gs(R.string.increasingmaxbasal), this) absoluteRate.addReason(resourceHelper.gs(R.string.increasingmaxbasal), this)
} }
absoluteRate.setIfSmaller(aapsLogger, maxBasal, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxBasal, resourceHelper.gs(R.string.maxvalueinpreferences)), this) absoluteRate.setIfSmaller(aapsLogger, maxBasal, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxBasal, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
// Check percentRate but absolute rate too, because we know real current basal in pump // Check percentRate but absolute rate too, because we know real current basal in pump
val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0) val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)
val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.basal * 100) / 100 val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.getBasal() * 100) / 100
absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromBasalMultiplier, resourceHelper.gs(R.string.maxbasalmultiplier)), this) absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromBasalMultiplier, resourceHelper.gs(R.string.maxbasalmultiplier)), this)
val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0) val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0)
val maxFromDaily = floor(profile.maxDailyBasal * maxBasalFromDaily * 100) / 100 val maxFromDaily = floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100
absoluteRate.setIfSmaller(aapsLogger, maxFromDaily, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromDaily, resourceHelper.gs(R.string.maxdailybasalmultiplier)), this) absoluteRate.setIfSmaller(aapsLogger, maxFromDaily, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromDaily, resourceHelper.gs(R.string.maxdailybasalmultiplier)), this)
} }
absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(), String.format(resourceHelper.gs(R.string.limitingbasalratio), hardLimits.maxBasal(), resourceHelper.gs(R.string.hardlimit)), this) absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(), String.format(resourceHelper.gs(R.string.limitingbasalratio), hardLimits.maxBasal(), resourceHelper.gs(R.string.hardlimit)), this)
@ -138,7 +138,7 @@ class SafetyPlugin @Inject constructor(
} }
override fun applyBasalPercentConstraints(percentRate: Constraint<Int>, profile: Profile): Constraint<Int> { override fun applyBasalPercentConstraints(percentRate: Constraint<Int>, profile: Profile): Constraint<Int> {
val currentBasal = profile.basal val currentBasal = profile.getBasal()
val absoluteRate = currentBasal * (percentRate.originalValue().toDouble() / 100) val absoluteRate = currentBasal * (percentRate.originalValue().toDouble() / 100)
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this) percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this)
val absoluteConstraint = Constraint(absoluteRate) val absoluteConstraint = Constraint(absoluteRate)

View file

@ -124,7 +124,7 @@ class DataBroadcastPlugin @Inject constructor(
bundle.putDouble("glucoseMgdl", lastBG.value) // last BG in mgdl bundle.putDouble("glucoseMgdl", lastBG.value) // last BG in mgdl
bundle.putLong("glucoseTimeStamp", lastBG.timestamp) // timestamp bundle.putLong("glucoseTimeStamp", lastBG.timestamp) // timestamp
bundle.putString("units", profileFunction.getUnits()) // units used in AAPS "mg/dl" or "mmol" bundle.putString("units", profileFunction.getUnits().asText) // units used in AAPS "mg/dl" or "mmol"
bundle.putString("slopeArrow", lastBG.trendArrow.text) // direction arrow as string bundle.putString("slopeArrow", lastBG.trendArrow.text) // direction arrow as string
bundle.putDouble("deltaMgdl", glucoseStatus.delta) // bg delta in mgdl bundle.putDouble("deltaMgdl", glucoseStatus.delta) // bg delta in mgdl
bundle.putDouble("avgDeltaMgdl", glucoseStatus.shortAvgDelta) // average bg delta bundle.putDouble("avgDeltaMgdl", glucoseStatus.shortAvgDelta) // average bg delta
@ -175,7 +175,7 @@ class DataBroadcastPlugin @Inject constructor(
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val profile = profileFunction.getProfile() ?: return val profile = profileFunction.getProfile() ?: return
bundle.putLong("basalTimeStamp", now) bundle.putLong("basalTimeStamp", now)
bundle.putDouble("baseBasal", profile.basal) bundle.putDouble("baseBasal", profile.getBasal())
bundle.putString("profile", profileFunction.getProfileName()) bundle.putString("profile", profileFunction.getProfileName())
iobCobCalculator.getTempBasalIncludingConvertedExtended(now)?.let { iobCobCalculator.getTempBasalIncludingConvertedExtended(now)?.let {
bundle.putLong("tempBasalStart", it.timestamp) bundle.putLong("tempBasalStart", it.timestamp)

View file

@ -35,6 +35,7 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.remove(R.string.key_ns_temporary_basal_last_synced_id) sp.remove(R.string.key_ns_temporary_basal_last_synced_id)
sp.remove(R.string.key_ns_extended_bolus_last_synced_id) sp.remove(R.string.key_ns_extended_bolus_last_synced_id)
sp.remove(R.string.key_ns_therapy_event_last_synced_id) sp.remove(R.string.key_ns_therapy_event_last_synced_id)
sp.remove(R.string.key_ns_profile_switch_last_synced_id)
} }
override fun confirmLastBolusIdIfGreater(lastSynced: Long) { override fun confirmLastBolusIdIfGreater(lastSynced: Long) {
@ -408,4 +409,40 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
return false return false
} }
override fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting ProfileSwitch data sync from $lastSynced")
sp.putLong(R.string.key_ns_profile_switch_last_synced_id, lastSynced)
}
}
override fun changedProfileSwitch(): List<ProfileSwitch> {
val startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)
return appRepository.getModifiedProfileSwitchDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading ProfileSwitch data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedProfileSwitchesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)
appRepository.getNextSyncElementProfileSwitch(startId).blockingGet()?.let { eb ->
aapsLogger.info(LTag.DATABASE, "Loading ProfileSwitch data Start: $startId ID: ${eb.first.id} HistoryID: ${eb.second} ")
when {
// removed and not uploaded yet = ignore
!eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", eb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairProfileSwitch(eb.first, eb.second))
// existing without nsId = create new
eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(dateUtil), DataSyncSelector.PairProfileSwitch(eb.first, eb.second))
// existing with nsId = update
eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", eb.first.interfaceIDs.nightscoutId, eb.first.toJson(dateUtil), DataSyncSelector.PairProfileSwitch(eb.first, eb.second))
}
return true
}
return false
}
} }

View file

@ -209,6 +209,25 @@ class NSClientAddAckWorker(
dataSyncSelector.processChangedTemporaryBasalsCompat() dataSyncSelector.processChangedTemporaryBasalsCompat()
} }
is PairProfileSwitch -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdProfileSwitchTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of ProfileSwitch failed", error)
ret = Result.failure((workDataOf("Error" to error.toString())))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of ProfileSwitch " + pair.value)
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileSwitch" + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedTemporaryBasalsCompat()
}
is DeviceStatus -> { is DeviceStatus -> {
val deviceStatus = ack.originalObject val deviceStatus = ack.originalObject
deviceStatus.interfaceIDs.nightscoutId = ack.id deviceStatus.interfaceIDs.nightscoutId = ack.id

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.* import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
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.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -44,7 +43,6 @@ class NSClientAddUpdateWorker(
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@ -306,7 +304,29 @@ class NSClientAddUpdateWorker(
} }
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json") } ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> eventType == TherapyEvent.Type.PROFILE_SWITCH.text ->
databaseHelper.createProfileSwitchFromJsonIfNotExists(json) profileSwitchFromJson(json, dateUtil)?.let { profileSwitch ->
repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch, invalidateByNsOnly = false))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving ProfileSwitch", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.PROFILE_SWITCH, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp))
aapsLogger.debug(LTag.DATABASE, "Inserted ProfileSwitch $it")
}
result.invalidated.forEach {
uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp))
aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId ProfileSwitch $it")
}
}
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
} }
if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) { if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) {
val date = safeGetLong(json, "mills") val date = safeGetLong(json, "mills")

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.* import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.extensions.* import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
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.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -39,7 +38,6 @@ class NSClientRemoveWorker(
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@ -158,8 +156,20 @@ class NSClientRemoveWorker(
} }
} }
// old DB model // room ProfileSwitch
databaseHelper.deleteProfileSwitchById(nsId) repository.runTransactionForResult(InvalidateNsIdProfileSwitchTransaction(nsId))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp))
}
}
} }
return ret return ret

View file

@ -116,6 +116,15 @@ class NSClientUpdateRemoveAckWorker(
dataSyncSelector.processChangedExtendedBolusesCompat() dataSyncSelector.processChangedExtendedBolusesCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString())) ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
} }
is PairProfileSwitch -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked ProfileSwitch " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedProfileSwitchesCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
} }
return ret return ret
} }

View file

@ -86,28 +86,6 @@ public class UploadQueue implements UploadQueueAdminInterface {
} }
} }
@Override
public void removeByNsClientIdIfExists(final JSONObject record) {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(() -> {
try {
String id;
if (record.has("NSCLIENT_ID")) {
id = record.getString("NSCLIENT_ID");
} else {
return;
}
if (databaseHelper.deleteDbRequest(id) == 1) {
aapsLogger.debug(LTag.NSCLIENT, "Removed item from UploadQueue. " + status());
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
});
}
}
@Override @Override
public void removeByMongoId(final String action, final String _id) { public void removeByMongoId(final String action, final String _id) {
if (_id == null || _id.equals("")) if (_id == null || _id.equals(""))

View file

@ -220,36 +220,18 @@ public class NSClientService extends DaggerService {
public void processAddAck(NSAddAck ack) { public void processAddAck(NSAddAck ack) {
lastAckTime = dateUtil.now(); lastAckTime = dateUtil.now();
// new room way
dataWorker.enqueue( dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientAddAckWorker.class) new OneTimeWorkRequest.Builder(NSClientAddAckWorker.class)
.setInputData(dataWorker.storeInputData(ack, null)) .setInputData(dataWorker.storeInputData(ack, null))
.build()); .build());
// old way
if (ack.nsClientID != null) {
uploadQueue.removeByNsClientIdIfExists(ack.json);
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
} else {
rxBus.send(new EventNSClientNewLog("ERROR", "DBADD Unknown response"));
}
} }
public void processUpdateAck(NSUpdateAck ack) { public void processUpdateAck(NSUpdateAck ack) {
lastAckTime = dateUtil.now(); lastAckTime = dateUtil.now();
// new room way
dataWorker.enqueue( dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker.class) new OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker.class)
.setInputData(dataWorker.storeInputData(ack, null)) .setInputData(dataWorker.storeInputData(ack, null))
.build()); .build());
// old way
if (ack.getResult()) {
uploadQueue.removeByMongoId(ack.getAction(), ack.get_id());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
} else {
rxBus.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
}
} }
public void processAuthAck(NSAuthAck ack) { public void processAuthAck(NSAuthAck ack) {
@ -811,6 +793,7 @@ public class NSClientService extends DaggerService {
dataSyncSelector.processChangedBolusCalculatorResultsCompat(); dataSyncSelector.processChangedBolusCalculatorResultsCompat();
dataSyncSelector.processChangedTemporaryBasalsCompat(); dataSyncSelector.processChangedTemporaryBasalsCompat();
dataSyncSelector.processChangedExtendedBolusesCompat(); dataSyncSelector.processChangedExtendedBolusesCompat();
dataSyncSelector.processChangedProfileSwitchesCompat();
dataSyncSelector.processChangedGlucoseValuesCompat(); dataSyncSelector.processChangedGlucoseValuesCompat();
dataSyncSelector.processChangedTempTargetsCompat(); dataSyncSelector.processChangedTempTargetsCompat();
dataSyncSelector.processChangedFoodsCompat(); dataSyncSelector.processChangedFoodsCompat();

View file

@ -222,20 +222,20 @@ class OpenHumansUploader @Inject constructor(
put("isDeletion", deleted) put("isDeletion", deleted)
} }
@JvmOverloads // @JvmOverloads
fun enqueueProfileSwitch(profileSwitch: ProfileSwitch, deleted: Boolean = false) = insertQueueItem("ProfileSwitches") { // fun enqueueProfileSwitch(profileSwitch: ProfileSwitch, deleted: Boolean = false) = insertQueueItem("ProfileSwitches") {
put("date", profileSwitch.date) // put("date", profileSwitch.date)
put("isValid", profileSwitch.isValid) // put("isValid", profileSwitch.isValid)
put("source", profileSwitch.source) // put("source", profileSwitch.source)
put("nsId", profileSwitch._id) // put("nsId", profileSwitch._id)
put("isCPP", profileSwitch.isCPP) // put("isCPP", profileSwitch.isCPP)
put("timeshift", profileSwitch.timeshift) // put("timeshift", profileSwitch.timeshift)
put("percentage", profileSwitch.percentage) // put("percentage", profileSwitch.percentage)
put("profile", JSONObject(profileSwitch.profileJson)) // put("profile", JSONObject(profileSwitch.profileJson))
put("profilePlugin", profileSwitch.profilePlugin) // put("profilePlugin", profileSwitch.profilePlugin)
put("durationInMinutes", profileSwitch.durationInMinutes) // put("durationInMinutes", profileSwitch.durationInMinutes)
put("isDeletion", deleted) // put("isDeletion", deleted)
} // }
// fun enqueueTotalDailyDose(tdd: TDD) = insertQueueItem("TotalDailyDoses") { // fun enqueueTotalDailyDose(tdd: TDD) = insertQueueItem("TotalDailyDoses") {
// put("double", tdd.date) // put("double", tdd.date)
@ -368,9 +368,9 @@ class OpenHumansUploader @Inject constructor(
// .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) }) // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) })
// .map { enqueueExtendedBolus(it); increaseCounter() } // .map { enqueueExtendedBolus(it); increaseCounter() }
// .ignoreElements() // .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) }) // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) })
.map { enqueueProfileSwitch(it); increaseCounter() } // .map { enqueueProfileSwitch(it); increaseCounter() }
.ignoreElements() // .ignoreElements()
// .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) }) // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) })
// .map { enqueueTotalDailyDose(it); increaseCounter() } // .map { enqueueTotalDailyDose(it); increaseCounter() }
// .ignoreElements() // .ignoreElements()

View file

@ -27,7 +27,7 @@ import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -256,7 +256,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ scheduleUpdateGUI("EventAutosensCalculationFinished") }, fabricPrivacy::logException)) .subscribe({ scheduleUpdateGUI("EventAutosensCalculationFinished") }, fabricPrivacy::logException))
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventProfileNeedsUpdate::class.java) .toObservable(EventProfileSwitchChanged::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ scheduleUpdateGUI("EventProfileNeedsUpdate") }, fabricPrivacy::logException)) .subscribe({ scheduleUpdateGUI("EventProfileNeedsUpdate") }, fabricPrivacy::logException))
disposable.add(rxBus disposable.add(rxBus
@ -682,29 +682,29 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.highTarget, Constants.MGDL, units) + " " + dateUtil.untilString(tempTarget.value.end, resourceHelper) binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.value.end, resourceHelper)
} else { } else {
// If the target is not the same as set in the profile then oref has overridden it // If the target is not the same as set in the profile then oref has overridden it
val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0 val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0
if (targetUsed != 0.0 && abs(profile.targetMgdl - targetUsed) > 0.01) { if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.targetMgdl} APS: $targetUsed") aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, Constants.MGDL, units) binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.tempTargetBackground)) binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.tempTargetBackground))
} else { } else {
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault)) binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault))
binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault)) binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault))
binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(profile.targetLowMgdl, profile.targetHighMgdl, Constants.MGDL, units) binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
} }
} }
// Basal, TBR // Basal, TBR
val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())
binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringShort() } binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringShort() }
?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal) ?: resourceHelper.gs(R.string.pump_basebasalrate, profile.getBasal())
binding.infoLayout.basalLayout.setOnClickListener { binding.infoLayout.basalLayout.setOnClickListener {
var fullText = "${resourceHelper.gs(R.string.basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}" var fullText = "${resourceHelper.gs(R.string.basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.getBasal())}"
if (activeTemp != null) if (activeTemp != null)
fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull(profile, dateUtil) fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull(profile, dateUtil)
activity?.let { activity?.let {
@ -734,7 +734,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.extendedLayout.visibility = (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses).toVisibility() binding.infoLayout.extendedLayout.visibility = (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses).toVisibility()
// Active profile // Active profile
binding.loopPumpStatusLayout.activeProfile.text = profileFunction.getProfileNameWithDuration() binding.loopPumpStatusLayout.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
if (profile.percentage != 100 || profile.timeshift != 0) { if (profile.percentage != 100 || profile.timeshift != 0) {
binding.loopPumpStatusLayout.activeProfile.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) binding.loopPumpStatusLayout.activeProfile.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
binding.loopPumpStatusLayout.activeProfile.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) binding.loopPumpStatusLayout.activeProfile.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
@ -820,7 +820,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (_binding == null) return@launch if (_binding == null) return@launch
val menuChartSettings = overviewMenus.setting val menuChartSettings = overviewMenus.setting
prepareGraphsIfNeeded(menuChartSettings.size) prepareGraphsIfNeeded(menuChartSettings.size)
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculator, treatmentsPlugin) val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculator)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList() val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
// do preparation in different thread // do preparation in different thread
@ -888,7 +888,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// ------------------ 2nd graph // ------------------ 2nd graph
synchronized(graphLock) { synchronized(graphLock) {
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) { for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculator, treatmentsPlugin) val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculator)
var useABSForScale = false var useABSForScale = false
var useIobForScale = false var useIobForScale = false
var useCobForScale = false var useCobForScale = false

View file

@ -9,14 +9,13 @@ import com.jjoe64.graphview.series.DataPoint
import com.jjoe64.graphview.series.LineGraphSeries import com.jjoe64.graphview.series.LineGraphSeries
import com.jjoe64.graphview.series.Series import com.jjoe64.graphview.series.Series
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.interfaces.* 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
@ -24,7 +23,6 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.* import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -35,8 +33,7 @@ import kotlin.math.min
class GraphData( class GraphData(
injector: HasAndroidInjector, injector: HasAndroidInjector,
private val graph: GraphView, private val graph: GraphView,
private val iobCobCalculator: IobCobCalculator, private val iobCobCalculator: IobCobCalculator
private val treatmentsPlugin: TreatmentsInterface
) { ) {
// IobCobCalculatorPlugin Cannot be injected: HistoryBrowser // IobCobCalculatorPlugin Cannot be injected: HistoryBrowser
@ -53,7 +50,7 @@ class GraphData(
var maxY = Double.MIN_VALUE var maxY = Double.MIN_VALUE
private var minY = Double.MAX_VALUE private var minY = Double.MAX_VALUE
private var bgReadingsArray: List<GlucoseValue>? = null private var bgReadingsArray: List<GlucoseValue>? = null
private val units: String private val units: GlucoseUnit
private val series: MutableList<Series<*>> = ArrayList() private val series: MutableList<Series<*>> = ArrayList()
init { init {
@ -80,7 +77,7 @@ class GraphData(
bgReadingsArray = repository.compatGetBgReadingsDataFromTime(fromTime, toTime, false).blockingGet() bgReadingsArray = repository.compatGetBgReadingsDataFromTime(fromTime, toTime, false).blockingGet()
if (bgReadingsArray?.isEmpty() != false) { if (bgReadingsArray?.isEmpty() != false) {
aapsLogger.debug("No BG data.") aapsLogger.debug("No BG data.")
maxY = if (units == Constants.MGDL) 180.0 else 10.0 maxY = if (units == GlucoseUnit.MGDL) 180.0 else 10.0
minY = 0.0 minY = 0.0
return return
} }
@ -102,12 +99,8 @@ class GraphData(
addSeries(PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })) addSeries(PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] }))
} }
internal fun setNumVerticalLabels() {
graph.gridLabelRenderer.numVerticalLabels = if (units == Constants.MGDL) (maxY / 40 + 1).toInt() else (maxY / 2 + 1).toInt()
}
private fun addUpperChartMargin(maxBgValue: Double) = private fun addUpperChartMargin(maxBgValue: Double) =
if (units == Constants.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4 if (units == GlucoseUnit.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4
fun addInRangeArea(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double) { fun addInRangeArea(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double) {
val inRangeAreaSeries: AreaGraphSeries<DoubleDataPoint> val inRangeAreaSeries: AreaGraphSeries<DoubleDataPoint>
@ -266,8 +259,8 @@ class GraphData(
} }
// ProfileSwitch // ProfileSwitch
treatmentsPlugin.profileSwitchesFromHistory.list repository.getEffectiveProfileSwitchDataFromTimeToTime(fromTime, endTime, true).blockingGet()
.filterTimeframe(fromTime, endTime) .map { EffectiveProfileSwitchDataPoint(it) }
.forEach(filteredTreatments::add) .forEach(filteredTreatments::add)
// Extended bolus // Extended bolus
@ -282,7 +275,6 @@ class GraphData(
} }
// Careportal // Careportal
// databaseHelper.getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true)
repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet() repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet()
.map { TherapyEventDataPoint(it, resourceHelper, profileFunction, translator) } .map { TherapyEventDataPoint(it, resourceHelper, profileFunction, translator) }
.filterTimeframe(fromTime, endTime) .filterTimeframe(fromTime, endTime)
@ -404,12 +396,14 @@ class GraphData(
var time = fromTime var time = fromTime
while (time <= toTime) { while (time <= toTime) {
val profile = profileFunction.getProfile(time) val profile = profileFunction.getProfile(time)
if (profile == null) {
time += 5 * 60 * 1000L
continue
}
var iob = 0.0 var iob = 0.0
var absIob = 0.0 var absIob = 0.0
if (profile != null) {
iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile).iob iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile).iob
if (absScale) absIob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob if (absScale) absIob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob
}
if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.02) {
if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
iobArray.add(ScaledDataPoint(time, iob, iobScale)) iobArray.add(ScaledDataPoint(time, iob, iobScale))
@ -463,8 +457,12 @@ class GraphData(
var time = fromTime var time = fromTime
while (time <= toTime) { while (time <= toTime) {
val profile = profileFunction.getProfile(time) val profile = profileFunction.getProfile(time)
if (profile == null) {
time += 5 * 60 * 1000L
continue
}
var iob = 0.0 var iob = 0.0
if (profile != null) iob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob iob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob
if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.02) {
if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
iobArray.add(ScaledDataPoint(time, iob, iobScale)) iobArray.add(ScaledDataPoint(time, iob, iobScale))
@ -541,7 +539,11 @@ class GraphData(
while (time <= toTime) { while (time <= toTime) {
// if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0 // if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0
val bgi: Double = if (devBgiScale) { val bgi: Double = if (devBgiScale) {
val profile = profileFunction.getProfile(time) ?: continue val profile = profileFunction.getProfile(time)
if (profile == null) {
time += 5 * 60 * 1000L
continue
}
total = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile) total = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
total.activity * profile.getIsfMgdl(time) * 5.0 total.activity * profile.getIsfMgdl(time) * 5.0
} else 0.0 } else 0.0
@ -657,6 +659,10 @@ class GraphData(
}) })
} }
fun setNumVerticalLabels() {
graph.gridLabelRenderer.numVerticalLabels = if (units == GlucoseUnit.MGDL) (maxY / 40 + 1).toInt() else (maxY / 2 + 1).toInt()
}
fun formatAxis(fromTime: Long, endTime: Long) { fun formatAxis(fromTime: Long, endTime: Long) {
graph.viewport.setMaxX(endTime.toDouble()) graph.viewport.setMaxX(endTime.toDouble())
graph.viewport.setMinX(fromTime.toDouble()) graph.viewport.setMinX(fromTime.toDouble())

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.graphics.Color
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import javax.inject.Inject
class EffectiveProfileSwitchDataPoint @Inject constructor(
val data: EffectiveProfileSwitch
) : DataPointWithLabelInterface {
private var yValue = 0.0
override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = yValue
override fun setY(y: Double) {
yValue = y
}
override fun getLabel(): String = data.originalCustomizedName
override fun getDuration(): Long = 0
override fun getShape(): PointsWithLabelGraphSeries.Shape = PointsWithLabelGraphSeries.Shape.PROFILE
override fun getSize(): Float = 10f
override fun getColor(): Int = Color.CYAN
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -15,8 +16,8 @@ class GlucoseValueDataPoint @Inject constructor(
private val resourceHelper: ResourceHelper private val resourceHelper: ResourceHelper
) : DataPointWithLabelInterface { ) : DataPointWithLabelInterface {
fun valueToUnits(units: String): Double = fun valueToUnits(units: GlucoseUnit): Double =
if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL if (units == GlucoseUnit.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
override fun getX(): Double { override fun getX(): Double {
return data.timestamp.toDouble() return data.timestamp.toDouble()

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.InMemoryGlucoseValue import info.nightscout.androidaps.data.InMemoryGlucoseValue
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -13,8 +14,8 @@ class InMemoryGlucoseValueDataPoint @Inject constructor(
private val resourceHelper: ResourceHelper private val resourceHelper: ResourceHelper
) : DataPointWithLabelInterface { ) : DataPointWithLabelInterface {
fun valueToUnits(units: String): Double = fun valueToUnits(units: GlucoseUnit): Double =
if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL if (units == GlucoseUnit.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
override fun getX(): Double = data.timestamp.toDouble() override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = valueToUnits(profileFunction.getUnits()) override fun getY(): Double = valueToUnits(profileFunction.getUnits())

View file

@ -3,8 +3,9 @@ package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.graphics.Color import android.graphics.Color
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Interval import info.nightscout.androidaps.interfaces.Interval
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.Translator
@ -30,11 +31,11 @@ class TherapyEventDataPoint @Inject constructor(
if (data.glucose != null && data.glucose != 0.0) { if (data.glucose != null && data.glucose != 0.0) {
var mmol = 0.0 var mmol = 0.0
var mgdl = 0.0 var mgdl = 0.0
if (units == Constants.MGDL) { if (units == GlucoseUnit.MGDL) {
mgdl = data.glucose!! mgdl = data.glucose!!
mmol = data.glucose!! * Constants.MGDL_TO_MMOLL mmol = data.glucose!! * Constants.MGDL_TO_MMOLL
} }
if (units == Constants.MMOL) { if (units == GlucoseUnit.MMOL) {
mmol = data.glucose!! mmol = data.glucose!!
mgdl = data.glucose!! * Constants.MMOLL_TO_MGDL mgdl = data.glucose!! * Constants.MMOLL_TO_MGDL
} }

View file

@ -10,7 +10,7 @@ import androidx.core.app.RemoteInput
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
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger

View file

@ -15,7 +15,7 @@ import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -584,7 +584,7 @@ class SmsCommunicatorPlugin @Inject constructor(
val finalPercentage = percentage val finalPercentage = percentage
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(list[pIndex - 1] as String, finalPercentage) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(list[pIndex - 1] as String, finalPercentage) {
override fun run() { override fun run() {
activePlugin.activeTreatments.doProfileSwitch(store, list[pIndex - 1] as String, 0, finalPercentage, 0, dateUtil.now()) profileFunction.createProfileSwitch(store, list[pIndex - 1] as String, 0, finalPercentage, 0, dateUtil.now())
val replyText = resourceHelper.gs(R.string.profileswitchcreated) val replyText = resourceHelper.gs(R.string.profileswitchcreated)
sendSMS(Sms(receivedSms.phoneNumber, replyText)) sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.PROFILE_SWITCH, Sources.SMS, resourceHelper.gs(R.string.profileswitchcreated), uel.log(Action.PROFILE_SWITCH, Sources.SMS, resourceHelper.gs(R.string.profileswitchcreated),
@ -817,11 +817,11 @@ class SmsCommunicatorPlugin @Inject constructor(
eatingSoonTTDuration = eatingSoonTTDuration =
if (eatingSoonTTDuration > 0) eatingSoonTTDuration if (eatingSoonTTDuration > 0) eatingSoonTTDuration
else Constants.defaultEatingSoonTTDuration else Constants.defaultEatingSoonTTDuration
var eatingSoonTT = sp.getDouble(R.string.key_eatingsoon_target, if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl) var eatingSoonTT = sp.getDouble(R.string.key_eatingsoon_target, if (currentProfile.units == GlucoseUnit.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl)
eatingSoonTT = eatingSoonTT =
when { when {
eatingSoonTT > 0 -> eatingSoonTT eatingSoonTT > 0 -> eatingSoonTT
currentProfile.units == Constants.MMOL -> Constants.defaultEatingSoonTTmmol currentProfile.units == GlucoseUnit.MMOL -> Constants.defaultEatingSoonTTmmol
else -> Constants.defaultEatingSoonTTmgdl else -> Constants.defaultEatingSoonTTmgdl
} }
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
@ -836,7 +836,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}, { }, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
val tt = if (currentProfile.units == Constants.MMOL) { val tt = if (currentProfile.units == GlucoseUnit.MMOL) {
DecimalFormatter.to1Decimal(eatingSoonTT) DecimalFormatter.to1Decimal(eatingSoonTT)
} else DecimalFormatter.to0Decimal(eatingSoonTT) } else DecimalFormatter.to0Decimal(eatingSoonTT)
replyText += "\n" + String.format(resourceHelper.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration) replyText += "\n" + String.format(resourceHelper.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration)
@ -863,7 +863,7 @@ class SmsCommunicatorPlugin @Inject constructor(
private fun toTodayTime(hh_colon_mm: String): Long { private fun toTodayTime(hh_colon_mm: String): Long {
val p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)") val p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)")
val m = p.matcher(hh_colon_mm) val m = p.matcher(hh_colon_mm)
var retval: Long = 0 var retVal: Long = 0
if (m.find()) { if (m.find()) {
var hours = SafeParse.stringToInt(m.group(1)) var hours = SafeParse.stringToInt(m.group(1))
val minutes = SafeParse.stringToInt(m.group(2)) val minutes = SafeParse.stringToInt(m.group(2))
@ -874,9 +874,9 @@ class SmsCommunicatorPlugin @Inject constructor(
.withMinuteOfHour(minutes) .withMinuteOfHour(minutes)
.withSecondOfMinute(0) .withSecondOfMinute(0)
.withMillisOfSecond(0) .withMillisOfSecond(0)
retval = t.millis retVal = t.millis
} }
return retval return retVal
} }
private fun processCARBS(divided: Array<String>, receivedSms: Sms) { private fun processCARBS(divided: Array<String>, receivedSms: Sms) {
@ -966,9 +966,9 @@ class SmsCommunicatorPlugin @Inject constructor(
} }
var ttDuration = sp.getInt(keyDuration, defaultTargetDuration) var ttDuration = sp.getInt(keyDuration, defaultTargetDuration)
ttDuration = if (ttDuration > 0) ttDuration else defaultTargetDuration ttDuration = if (ttDuration > 0) ttDuration else defaultTargetDuration
var tt = sp.getDouble(keyTarget, if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL) var tt = sp.getDouble(keyTarget, if (units == GlucoseUnit.MMOL) defaultTargetMMOL else defaultTargetMGDL)
tt = Profile.toCurrentUnits(profileFunction, tt) tt = Profile.toCurrentUnits(profileFunction, tt)
tt = if (tt > 0) tt else if (units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL tt = if (tt > 0) tt else if (units == GlucoseUnit.MMOL) defaultTargetMMOL else defaultTargetMGDL
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = dateUtil.now(), timestamp = dateUtil.now(),
duration = TimeUnit.MINUTES.toMillis(ttDuration.toLong()), duration = TimeUnit.MINUTES.toMillis(ttDuration.toLong()),
@ -981,11 +981,11 @@ class SmsCommunicatorPlugin @Inject constructor(
}, { }, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
val ttString = if (units == Constants.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt) val ttString = if (units == GlucoseUnit.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_set), ttString, ttDuration) val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_set), ttString, ttDuration)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.TT, Sources.SMS, uel.log(Action.TT, Sources.SMS,
ValueWithUnit.fromGlucoseUnit(tt, units), ValueWithUnit.fromGlucoseUnit(tt, units.asText),
ValueWithUnit.Minute(ttDuration)) ValueWithUnit.Minute(ttDuration))
} }
}) })

View file

@ -2,10 +2,9 @@ package info.nightscout.androidaps.plugins.general.tidepool.comm
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -29,7 +28,6 @@ class UploadChunk @Inject constructor(
private val aapsLogger: AAPSLogger, private val aapsLogger: AAPSLogger,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val databaseHelper: DatabaseHelperInterface,
private val repository: AppRepository, private val repository: AppRepository,
private val dateUtil: DateUtil private val dateUtil: DateUtil
) { ) {
@ -162,14 +160,14 @@ class UploadChunk @Inject constructor(
return selection return selection
} }
private fun newInstanceOrNull(ps: ProfileSwitch): ProfileElement? = try { private fun newInstanceOrNull(ps: EffectiveProfileSwitch): ProfileElement? = try {
ProfileElement(ps, activePlugin.activePump.serialNumber(), dateUtil) ProfileElement(ps, activePlugin.activePump.serialNumber(), dateUtil)
} catch (e: Throwable) { } catch (e: Throwable) {
null null
} }
private fun getProfiles(start: Long, end: Long): List<ProfileElement> { private fun getProfiles(start: Long, end: Long): List<ProfileElement> {
val pss = databaseHelper.getProfileSwitchEventsFromTime(start, end, true) val pss = repository.getEffectiveProfileSwitchDataFromTimeToTime(start, end, true).blockingGet()
val selection = LinkedList<ProfileElement>() val selection = LinkedList<ProfileElement>()
for (ps in pss) { for (ps in pss) {
newInstanceOrNull(ps)?.let { selection.add(it) } newInstanceOrNull(ps)?.let { selection.add(it) }

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.general.tidepool.elements package info.nightscout.androidaps.plugins.general.tidepool.elements
import com.google.gson.annotations.Expose import com.google.gson.annotations.Expose
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.entities.TemporaryBasal import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil

View file

@ -1,9 +1,10 @@
package info.nightscout.androidaps.plugins.general.tidepool.elements package info.nightscout.androidaps.plugins.general.tidepool.elements
import com.google.gson.annotations.Expose import com.google.gson.annotations.Expose
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.extensions.toConstant import info.nightscout.androidaps.extensions.toConstant
import info.nightscout.androidaps.extensions.toMainUnit
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import java.util.* import java.util.*
@ -23,7 +24,7 @@ class BloodGlucoseElement(therapyEvent: TherapyEvent, dateUtil: DateUtil)
type = "cbg" type = "cbg"
subType = "manual" // TODO subType = "manual" // TODO
value = if (therapyEvent.glucose != null) value = if (therapyEvent.glucose != null)
Profile.toMgdl(therapyEvent.glucose!!, therapyEvent.glucoseUnit.toConstant()).toInt() Profile.toMgdl(therapyEvent.glucose!!, therapyEvent.glucoseUnit.toMainUnit()).toInt()
else 0 else 0
} }

View file

@ -1,15 +1,16 @@
package info.nightscout.androidaps.plugins.general.tidepool.elements package info.nightscout.androidaps.plugins.general.tidepool.elements
import com.google.gson.annotations.Expose import com.google.gson.annotations.Expose
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class ProfileElement(ps: ProfileSwitch, serialNumber: String, dateUtil: DateUtil) class ProfileElement(ps: EffectiveProfileSwitch, serialNumber: String, dateUtil: DateUtil)
: BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString(), dateUtil) { : BaseElement(ps.timestamp, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.timestamp).toByteArray()).toString(), dateUtil) {
@Expose @Expose
internal var activeSchedule = "Normal" internal var activeSchedule = "Normal"
@ -34,15 +35,15 @@ class ProfileElement(ps: ProfileSwitch, serialNumber: String, dateUtil: DateUtil
init { init {
type = "pumpSettings" type = "pumpSettings"
val profile: Profile? = ps.profileObject val profile: Profile? = ProfileSealed.EPS(ps)
checkNotNull(profile) checkNotNull(profile)
for (br in profile.basalValues) for (br in profile.getBasalValues())
basalSchedules.Normal.add(BasalRate(br.timeAsSeconds * 1000, br.value)) basalSchedules.Normal.add(BasalRate(br.timeAsSeconds * 1000, br.value))
for (target in profile.singleTargetsMgdl) for (target in profile.getSingleTargetsMgdl())
bgTargets.Normal.add(Target(target.timeAsSeconds * 1000, target.value)) bgTargets.Normal.add(Target(target.timeAsSeconds * 1000, target.value))
for (ic in profile.ics) for (ic in profile.getIcsValues())
carbRatios.Normal.add(Ratio(ic.timeAsSeconds * 1000, ic.value)) carbRatios.Normal.add(Ratio(ic.timeAsSeconds * 1000, ic.value))
for (isf in profile.isfsMgdl) for (isf in profile.getIsfsMgdlValues())
insulinSensitivities.Normal.add(Ratio(isf.timeAsSeconds * 1000, isf.value)) insulinSensitivities.Normal.add(Ratio(isf.timeAsSeconds * 1000, isf.value))
} }

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.general.wear
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.dana.DanaPump
@ -12,7 +11,6 @@ import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSPlugin
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -146,7 +144,7 @@ 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]) val isMGDL = java.lang.Boolean.parseBoolean(act[1])
if (profileFunction.getUnits() == Constants.MGDL != isMGDL) { if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
sendError("Different units used on watch and phone!") sendError("Different units used on watch and phone!")
return return
} }
@ -251,25 +249,25 @@ class ActionStringHandler @Inject constructor(
} }
lastBolusWizard = bolusWizard lastBolusWizard = bolusWizard
} else if ("opencpp" == act[0]) { } else if ("opencpp" == act[0]) {
val activeProfileSwitch = activePlugin.activeTreatments.getProfileSwitchFromHistory(System.currentTimeMillis()) val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (activeProfileSwitch == null) { if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
sendError("No active profile switch!")
return
} else { // read CPP values
rTitle = "opencpp" rTitle = "opencpp"
rMessage = "opencpp" rMessage = "opencpp"
rAction = "opencpp" + " " + activeProfileSwitch.percentage + " " + activeProfileSwitch.timeshift rAction = "opencpp" + " " + activeProfileSwitch.value.originalPercentage + " " + activeProfileSwitch.value.originalTimeshift
} } else {
} else if ("cppset" == act[0]) {
val activeProfileSwitch = activePlugin.activeTreatments.getProfileSwitchFromHistory(System.currentTimeMillis())
if (activeProfileSwitch == null) {
sendError("No active profile switch!") sendError("No active profile switch!")
return return
} else { // read CPP values }
} else if ("cppset" == act[0]) {
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (activeProfileSwitch is ValueWrapper.Existing) {
rMessage = "CPP:" + "\n\n" + rMessage = "CPP:" + "\n\n" +
"Timeshift: " + act[1] + "\n" + "Timeshift: " + act[1] + "\n" +
"Percentage: " + act[2] + "%" "Percentage: " + act[2] + "%"
rAction = actionString rAction = actionString
} else { // read CPP values
sendError("No active profile switch!")
return
} }
} else if ("tddstats" == act[0]) { } else if ("tddstats" == act[0]) {
val activePump = activePlugin.activePump val activePump = activePlugin.activePump
@ -456,13 +454,13 @@ class ActionStringHandler @Inject constructor(
//Check for Temp-Target: //Check for Temp-Target:
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.lowTarget, Constants.MGDL, profileFunction.getUnits()) ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.lowTarget, GlucoseUnit.MGDL, profileFunction.getUnits())
ret += "\nuntil: " + dateUtil.timeString(tempTarget.value.end) ret += "\nuntil: " + dateUtil.timeString(tempTarget.value.end)
ret += "\n\n" ret += "\n\n"
} }
ret += "DEFAULT RANGE: " ret += "DEFAULT RANGE: "
ret += Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits()).toString() + " - " + Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits()) ret += Profile.fromMgdlToUnits(profile.getTargetLowMgdl(), profileFunction.getUnits()).toString() + " - " + Profile.fromMgdlToUnits(profile.getTargetHighMgdl(), profileFunction.getUnits())
ret += " target: " + Profile.fromMgdlToUnits(profile.targetMgdl, profileFunction.getUnits()) ret += " target: " + Profile.fromMgdlToUnits(profile.getTargetMgdl(), profileFunction.getUnits())
return ret return ret
} }
@ -569,7 +567,7 @@ class ActionStringHandler @Inject constructor(
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 })
activePlugin.activeTreatments.doProfileSwitch(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) {
@ -588,8 +586,8 @@ class ActionStringHandler @Inject constructor(
}) })
uel.log(Action.TT, Sources.Wear, uel.log(Action.TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits()), ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits()).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()))

View file

@ -33,7 +33,8 @@ import info.nightscout.androidaps.interfaces.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.GlucoseUnit;
import info.nightscout.androidaps.interfaces.Profile;
import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.entities.Bolus; import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.database.entities.GlucoseValue;
@ -298,9 +299,9 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private DataMap dataMapSingleBG(GlucoseValue lastBG, GlucoseStatus glucoseStatus) { private DataMap dataMapSingleBG(GlucoseValue lastBG, GlucoseStatus glucoseStatus) {
String units = profileFunction.getUnits(); GlucoseUnit units = profileFunction.getUnits();
double convert2MGDL = 1.0; double convert2MGDL = 1.0;
if (units.equals(Constants.MMOL)) if (units.equals(GlucoseUnit.MMOL))
convert2MGDL = Constants.MMOLL_TO_MGDL; convert2MGDL = Constants.MMOLL_TO_MGDL;
double lowLine = defaultValueHelper.determineLowLine() * convert2MGDL; double lowLine = defaultValueHelper.determineLowLine() * convert2MGDL;
double highLine = defaultValueHelper.determineHighLine() * convert2MGDL; double highLine = defaultValueHelper.determineHighLine() * convert2MGDL;
@ -314,7 +315,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
DataMap dataMap = new DataMap(); DataMap dataMap = new DataMap();
dataMap.putString("sgvString", GlucoseValueExtensionKt.valueToUnitsString(lastBG, units)); dataMap.putString("sgvString", GlucoseValueExtensionKt.valueToUnitsString(lastBG, units));
dataMap.putString("glucoseUnits", units); dataMap.putString("glucoseUnits", units.getAsText());
dataMap.putLong("timestamp", lastBG.getTimestamp()); dataMap.putLong("timestamp", lastBG.getTimestamp());
if (glucoseStatus == null) { if (glucoseStatus == null) {
dataMap.putString("slopeArrow", ""); dataMap.putString("slopeArrow", "");
@ -332,7 +333,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
return dataMap; return dataMap;
} }
private String deltastring(double deltaMGDL, double deltaMMOL, String units) { private String deltastring(double deltaMGDL, double deltaMMOL, GlucoseUnit units) {
String deltastring = ""; String deltastring = "";
if (deltaMGDL >= 0) { if (deltaMGDL >= 0) {
deltastring += "+"; deltastring += "+";
@ -341,7 +342,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
} }
boolean detailed = sp.getBoolean(R.string.key_wear_detailed_delta, false); boolean detailed = sp.getBoolean(R.string.key_wear_detailed_delta, false);
if (units.equals(Constants.MGDL)) { if (units.equals(GlucoseUnit.MGDL)) {
if (detailed) { if (detailed) {
deltastring += DecimalFormatter.INSTANCE.to1Decimal(Math.abs(deltaMGDL)); deltastring += DecimalFormatter.INSTANCE.to1Decimal(Math.abs(deltaMGDL));
} else { } else {
@ -541,7 +542,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
.collect(Collectors.toList()); .collect(Collectors.toList());
if (!predArray.isEmpty()) { if (!predArray.isEmpty()) {
final String units = profileFunction.getUnits();
for (GlucoseValueDataPoint bg : predArray) { for (GlucoseValueDataPoint bg : predArray) {
if (bg.getData().getValue() < 40) continue; if (bg.getData().getValue() < 40) continue;
predictions.add(predictionMap(bg.getData().getTimestamp(), bg.getData().getValue(), bg.getPredictionColor())); predictions.add(predictionMap(bg.getData().getTimestamp(), bg.getData().getValue(), bg.getPredictionColor()));
@ -695,7 +695,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
currentBasal = generateBasalString(); currentBasal = generateBasalString();
//bgi //bgi
double bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits()); double bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.Companion.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits());
bgiString = "" + ((bgi >= 0) ? "+" : "") + DecimalFormatter.INSTANCE.to1Decimal(bgi); bgiString = "" + ((bgi >= 0) ? "+" : "") + DecimalFormatter.INSTANCE.to1Decimal(bgi);
status = generateStatusString(profile, currentBasal, iobSum, iobDetail, bgiString); status = generateStatusString(profile, currentBasal, iobSum, iobDetail, bgiString);

View file

@ -5,15 +5,14 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.extensions.toStringShort
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.extensions.toStringShort
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.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -31,7 +30,6 @@ class StatusLinePlugin @Inject constructor(
private val aapsSchedulers: AapsSchedulers, private val aapsSchedulers: AapsSchedulers,
private val context: Context, private val context: Context,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val activePlugin: ActivePlugin,
private val loopPlugin: LoopPlugin, private val loopPlugin: LoopPlugin,
private val iobCobCalculator: IobCobCalculator, private val iobCobCalculator: IobCobCalculator,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
@ -136,7 +134,7 @@ class StatusLinePlugin @Inject constructor(
+ DecimalFormatter.to2Decimal(basalIob.basaliob) + ")") + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")")
} }
if (sp.getBoolean(R.string.key_xdripstatus_showbgi, true)) { if (sp.getBoolean(R.string.key_xdripstatus_showbgi, true)) {
val bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.isfMgdl, profileFunction.getUnits()) val bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits())
status += " " + (if (bgi >= 0) "+" else "") + DecimalFormatter.to2Decimal(bgi) status += " " + (if (bgi >= 0) "+" else "") + DecimalFormatter.to2Decimal(bgi)
} }
// COB // COB

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.insulin
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Iob import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.Insulin import info.nightscout.androidaps.interfaces.Insulin
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
@ -13,6 +14,7 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification 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.Notification
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.exp import kotlin.math.exp
import kotlin.math.pow import kotlin.math.pow
@ -86,6 +88,9 @@ abstract class InsulinOrefBasePlugin(
return result return result
} }
override val insulinConfiguration: InsulinConfiguration
get() = InsulinConfiguration(friendlyName, (dia * 1000.0 * 3600.0).toLong(), T.mins(peak.toLong()).msecs())
override val comment override val comment
get(): String { get(): String {
var comment = commentStandardText() var comment = commentStandardText()

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
@ -150,6 +150,8 @@ open class IobCobCalculatorPlugin @Inject constructor(
if (oldestBolus != null) oldestTime = min(oldestTime, oldestBolus.timestamp) if (oldestBolus != null) oldestTime = min(oldestTime, oldestBolus.timestamp)
val oldestCarbs = repository.getOldestCarbsRecord() val oldestCarbs = repository.getOldestCarbsRecord()
if (oldestCarbs != null) oldestTime = min(oldestTime, oldestCarbs.timestamp) if (oldestCarbs != null) oldestTime = min(oldestTime, oldestCarbs.timestamp)
val oldestPs = repository.getOldestEffectiveProfileSwitchRecord()
if (oldestPs != null) oldestTime = min(oldestTime, oldestPs.timestamp)
oldestTime -= 15 * 60 * 1000L // allow 15 min before oldestTime -= 15 * 60 * 1000L // allow 15 min before
return oldestTime return oldestTime
} }

View file

@ -117,7 +117,7 @@ class IobCobOref1Thread internal constructor(
val profile = profileFunction.getProfile(bgTime) val profile = profileFunction.getProfile(bgTime)
if (profile == null) { if (profile == null) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from")
return // profile not set yet continue // profile not set yet
} }
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")") aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")")
val sens = profile.getIsfMgdl(bgTime) val sens = profile.getIsfMgdl(bgTime)

View file

@ -116,7 +116,7 @@ class IobCobThread @Inject internal constructor(
val profile = profileFunction.getProfile(bgTime) val profile = profileFunction.getProfile(bgTime)
if (profile == null) { if (profile == null) {
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from") aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from")
return // profile not set yet continue // profile not set yet
} }
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")") aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")")
val sens = profile.getIsfMgdl(bgTime) val sens = profile.getIsfMgdl(bgTime)

View file

@ -11,13 +11,15 @@ import android.widget.ArrayAdapter
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.databinding.LocalprofileFragmentBinding import info.nightscout.androidaps.databinding.LocalprofileFragmentBinding
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -66,7 +68,7 @@ class LocalProfileFragment : DaggerFragment() {
private fun sumLabel(): String { private fun sumLabel(): String {
val profile = localProfilePlugin.createProfileStore().getDefaultProfile() val profile = localProfilePlugin.createProfileStore().getDefaultProfile()
val sum = profile?.baseBasalSum() ?: 0.0 val sum = profile?.let { ProfileSealed.Pure(profile).baseBasalSum() } ?: 0.0
return "" + DecimalFormatter.to2Decimal(sum) + resourceHelper.gs(R.string.insulin_unit_shortname) return "" + DecimalFormatter.to2Decimal(sum) + resourceHelper.gs(R.string.insulin_unit_shortname)
} }
@ -127,8 +129,8 @@ class LocalProfileFragment : DaggerFragment() {
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].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), 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, Constants.MMOL), Profile.fromMgdlToUnits(HardLimits.MAX_ISF, Constants.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(), Constants.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), Constants.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)
} }
// Spinner // Spinner
@ -175,7 +177,8 @@ class LocalProfileFragment : DaggerFragment() {
if (localProfilePlugin.isEdited) { if (localProfilePlugin.isEdited) {
activity?.let { OKDialog.show(it, "", resourceHelper.gs(R.string.saveorresetchangesfirst)) } activity?.let { OKDialog.show(it, "", resourceHelper.gs(R.string.saveorresetchangesfirst)) }
} else { } else {
uel.log(Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name ?: "")) uel.log(Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
localProfilePlugin.cloneProfile() localProfilePlugin.cloneProfile()
build() build()
} }
@ -184,7 +187,8 @@ class LocalProfileFragment : DaggerFragment() {
binding.profileRemove.setOnClickListener { binding.profileRemove.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.deletecurrentprofile), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.deletecurrentprofile), {
uel.log(Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name ?: "")) uel.log(Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
localProfilePlugin.removeCurrentProfile() localProfilePlugin.removeCurrentProfile()
build() build()
}, null) }, null)
@ -212,7 +216,8 @@ class LocalProfileFragment : DaggerFragment() {
if (!localProfilePlugin.isValidEditState()) { if (!localProfilePlugin.isValidEditState()) {
return@setOnClickListener //Should not happen as saveButton should not be visible if not valid return@setOnClickListener //Should not happen as saveButton should not be visible if not valid
} }
uel.log(Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name ?: "")) uel.log(Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
localProfilePlugin.storeSettings(activity) localProfilePlugin.storeSettings(activity)
build() build()
} }

View file

@ -4,8 +4,10 @@ import androidx.fragment.app.FragmentActivity
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
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.data.PureProfile
import info.nightscout.androidaps.events.EventProfileStoreChanged import info.nightscout.androidaps.events.EventProfileStoreChanged
import info.nightscout.androidaps.extensions.blockFromJsonArray
import info.nightscout.androidaps.interfaces.* 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
@ -13,6 +15,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -33,6 +36,8 @@ class LocalProfilePlugin @Inject constructor(
private val sp: SP, private val sp: SP,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val nsUpload: NSUpload, private val nsUpload: NSUpload,
private val activePlugin: ActivePlugin,
private val hardLimits: HardLimits,
private val dateUtil: DateUtil private val dateUtil: DateUtil
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.PROFILE) .mainType(PluginType.PROFILE)
@ -91,8 +96,25 @@ class LocalProfilePlugin @Inject constructor(
@Synchronized @Synchronized
fun isValidEditState(): Boolean { fun isValidEditState(): Boolean {
return createProfileStore().getDefaultProfile()?.isValid(resourceHelper.gs(R.string.localprofile), false) val pumpDescription = activePlugin.activePump.pumpDescription
?: false with(profiles[currentProfileIndex]) {
if (dia < hardLimits.minDia() || dia > hardLimits.maxDia()) return false
if (name.isNullOrEmpty()) return false
if (blockFromJsonArray(ic, dateUtil)?.any { it.amount < hardLimits.minIC() || it.amount > hardLimits.maxIC() } != false) return false
if (blockFromJsonArray(isf, dateUtil)?.any { it.amount < HardLimits.MIN_ISF || it.amount > HardLimits.MAX_ISF } != false) return false
if (blockFromJsonArray(basal, dateUtil)?.any { it.amount < pumpDescription.basalMinimumRate || it.amount > 10.0 } != false) return false
val low = blockFromJsonArray(targetLow, dateUtil)
val high = blockFromJsonArray(targetHigh, dateUtil)
if (profileFunction.getUnits() == GlucoseUnit.MGDL) {
if (low?.any { it.amount < HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble() || it.amount > HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble() } != 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) return false
} else {
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) 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) return false
}
for (i in low.indices) if (low[i].amount > high[i].amount) return false
}
return true
} }
@Synchronized @Synchronized
@ -200,20 +222,22 @@ class LocalProfilePlugin @Inject constructor(
createAndStoreConvertedProfile() createAndStoreConvertedProfile()
} }
fun copyFrom(profile: Profile, newName: String): SingleProfile { fun copyFrom(pureProfile: PureProfile, newName: String): SingleProfile {
var verifiedName = newName var verifiedName = newName
if (rawProfile?.getSpecificProfile(newName) != null) { if (rawProfile?.getSpecificProfile(newName) != null) {
verifiedName += " " + dateUtil.now().toString() verifiedName += " " + dateUtil.now().toString()
} }
val profile = ProfileSealed.Pure(pureProfile)
val pureJson = pureProfile.jsonObject
val sp = SingleProfile() val sp = SingleProfile()
sp.name = verifiedName sp.name = verifiedName
sp.mgdl = profile.units == Constants.MGDL sp.mgdl = profile.units == GlucoseUnit.MGDL
sp.dia = profile.dia sp.dia = pureJson.getDouble("dia")
sp.ic = JSONArray(profile.data.getJSONArray("carbratio").toString()) sp.ic = pureJson.getJSONArray("carbratio")
sp.isf = JSONArray(profile.data.getJSONArray("sens").toString()) sp.isf = pureJson.getJSONArray("sens")
sp.basal = JSONArray(profile.data.getJSONArray("basal").toString()) sp.basal = pureJson.getJSONArray("basal")
sp.targetLow = JSONArray(profile.data.getJSONArray("target_low").toString()) sp.targetLow = pureJson.getJSONArray("target_low")
sp.targetHigh = JSONArray(profile.data.getJSONArray("target_high").toString()) sp.targetHigh = pureJson.getJSONArray("target_high")
return sp return sp
} }
@ -276,7 +300,7 @@ class LocalProfilePlugin @Inject constructor(
} }
val p = SingleProfile() val p = SingleProfile()
p.name = Constants.LOCAL_PROFILE + free p.name = Constants.LOCAL_PROFILE + free
p.mgdl = profileFunction.getUnits() == Constants.MGDL p.mgdl = profileFunction.getUnits() == GlucoseUnit.MGDL
p.dia = Constants.defaultDIA p.dia = Constants.defaultDIA
p.ic = JSONArray(defaultArray) p.ic = JSONArray(defaultArray)
p.isf = JSONArray(defaultArray) p.isf = JSONArray(defaultArray)
@ -346,13 +370,14 @@ class LocalProfilePlugin @Inject constructor(
aapsLogger.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
} }
return ProfileStore(injector, json) return ProfileStore(injector, json, dateUtil)
} }
override val profile: ProfileStore? override val profile: ProfileStore?
get() = rawProfile get() = rawProfile
override val profileName: String override val profileName: String
get() = DecimalFormatter.to2Decimal(rawProfile?.getDefaultProfile()?.percentageBasalSum() get() = rawProfile?.getDefaultProfile()?.let {
?: 0.0) + "U " DecimalFormatter.to2Decimal(ProfileSealed.Pure(it).percentageBasalSum()) + "U "
} ?: "INVALID"
} }

View file

@ -8,28 +8,29 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.databinding.NsprofileFragmentBinding import info.nightscout.androidaps.databinding.NsprofileFragmentBinding
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import io.reactivex.rxkotlin.plusAssign
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 io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
class NSProfileFragment : DaggerFragment() { class NSProfileFragment : DaggerFragment() {
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -38,6 +39,8 @@ class NSProfileFragment : DaggerFragment() {
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var config: Config
private var disposable: CompositeDisposable = CompositeDisposable() private var disposable: CompositeDisposable = CompositeDisposable()
@ -68,7 +71,7 @@ class NSProfileFragment : DaggerFragment() {
uel.log(Action.PROFILE_SWITCH, Sources.NSProfile, uel.log(Action.PROFILE_SWITCH, Sources.NSProfile,
ValueWithUnit.SimpleString(name), ValueWithUnit.SimpleString(name),
ValueWithUnit.Percent(100)) ValueWithUnit.Percent(100))
treatmentsPlugin.doProfileSwitch(store, name, 0, 100, 0, dateUtil.now()) profileFunction.createProfileSwitch(store, name, 0, 100, 0, dateUtil.now())
}) })
} }
} }
@ -100,16 +103,17 @@ class NSProfileFragment : DaggerFragment() {
nsProfilePlugin.profile?.let { store -> nsProfilePlugin.profile?.let { store ->
store.getSpecificProfile(name)?.let { profile -> store.getSpecificProfile(name)?.let { profile ->
if (_binding == null) return if (_binding == null) return
binding.profileviewer.units.text = profile.units val pss = ProfileSealed.Pure(profile)
binding.profileviewer.dia.text = resourceHelper.gs(R.string.format_hours, profile.dia) binding.profileviewer.units.text = pss.units.asText
binding.profileviewer.dia.text = resourceHelper.gs(R.string.format_hours, pss.dia)
binding.profileviewer.activeprofile.text = name binding.profileviewer.activeprofile.text = name
binding.profileviewer.ic.text = profile.icList binding.profileviewer.ic.text = pss.getIcList(resourceHelper, dateUtil)
binding.profileviewer.isf.text = profile.isfList binding.profileviewer.isf.text = pss.getIsfList(resourceHelper, dateUtil)
binding.profileviewer.basal.text = profile.basalList binding.profileviewer.basal.text = pss.getBasalList(resourceHelper, dateUtil)
binding.profileviewer.basaltotal.text = String.format(resourceHelper.gs(R.string.profile_total), DecimalFormatter.to2Decimal(profile.baseBasalSum())) binding.profileviewer.basaltotal.text = String.format(resourceHelper.gs(R.string.profile_total), DecimalFormatter.to2Decimal(pss.baseBasalSum()))
binding.profileviewer.target.text = profile.targetList binding.profileviewer.target.text = pss.getTargetList(resourceHelper, dateUtil)
binding.profileviewer.basalGraph.show(profile) binding.profileviewer.basalGraph.show(pss)
if (profile.isValid("NSProfileFragment")) { if (pss.isValid("NSProfileFragment", activePlugin.activePump, config, resourceHelper, rxBus)) {
binding.profileviewer.invalidprofile.visibility = View.GONE binding.profileviewer.invalidprofile.visibility = View.GONE
binding.profileswitch.visibility = View.VISIBLE binding.profileswitch.visibility = View.VISIBLE
} else { } else {

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI
import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject import org.json.JSONObject
@ -32,6 +33,7 @@ class NSProfilePlugin @Inject constructor(
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val dateUtil: DateUtil,
config: Config config: Config
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.PROFILE) .mainType(PluginType.PROFILE)
@ -66,7 +68,7 @@ class NSProfilePlugin @Inject constructor(
val profileString = sp.getStringOrNull("profile", null) val profileString = sp.getStringOrNull("profile", null)
if (profileString != null) { if (profileString != null) {
aapsLogger.debug(LTag.PROFILE, "Loaded profile: $profileString") aapsLogger.debug(LTag.PROFILE, "Loaded profile: $profileString")
profile = ProfileStore(injector, JSONObject(profileString)) profile = ProfileStore(injector, JSONObject(profileString), dateUtil)
} else { } else {
aapsLogger.debug(LTag.PROFILE, "Stored profile not found") aapsLogger.debug(LTag.PROFILE, "Stored profile not found")
// force restart of nsclient to fetch profile // force restart of nsclient to fetch profile
@ -85,6 +87,7 @@ class NSProfilePlugin @Inject constructor(
@Inject lateinit var nsProfilePlugin: NSProfilePlugin @Inject lateinit var nsProfilePlugin: NSProfilePlugin
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var dataWorker: DataWorker @Inject lateinit var dataWorker: DataWorker
init { init {
@ -94,7 +97,7 @@ class NSProfilePlugin @Inject constructor(
override fun doWork(): Result { override fun doWork(): Result {
val profileString = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1)) val profileString = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure(workDataOf("Error" to "missing input data")) ?: return Result.failure(workDataOf("Error" to "missing input data"))
nsProfilePlugin.profile = ProfileStore(injector, profileString) nsProfilePlugin.profile = ProfileStore(injector, profileString, dateUtil)
nsProfilePlugin.storeNSProfile() nsProfilePlugin.storeNSProfile()
if (nsProfilePlugin.isEnabled()) { if (nsProfilePlugin.isEnabled()) {
rxBus.send(EventProfileStoreChanged()) rxBus.send(EventProfileStoreChanged())

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.pump.mdi
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger

View file

@ -7,7 +7,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -95,7 +95,7 @@ open class VirtualPumpPlugin @Inject constructor(
it.is30minBasalRatesCapable = true it.is30minBasalRatesCapable = true
} }
fun getFakingStatus(): Boolean { private fun getFakingStatus(): Boolean {
return sp.getBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, false) return sp.getBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, false)
} }
@ -169,7 +169,7 @@ open class VirtualPumpPlugin @Inject constructor(
} }
override val baseBasalRate: Double override val baseBasalRate: Double
get() = profileFunction.getProfile()?.basal ?: 0.0 get() = profileFunction.getProfile()?.getBasal() ?: 0.0
override val reservoirLevel: Double override val reservoirLevel: Double
get() = reservoirInUnits.toDouble() get() = reservoirInUnits.toDouble()

View file

@ -3,14 +3,13 @@ package info.nightscout.androidaps.plugins.sensitivity
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
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.extensions.isEPSEvent5minBack
import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.extensions.isTherapyEventEvent5minBack
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -36,7 +35,6 @@ open class SensitivityAAPSPlugin @Inject constructor(
sp: SP, sp: SP,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val databaseHelper: DatabaseHelperInterface,
private val repository: AppRepository private val repository: AppRepository
) : AbstractSensitivityPlugin(PluginDescription() ) : AbstractSensitivityPlugin(PluginDescription()
.mainType(PluginType.SENSITIVITY) .mainType(PluginType.SENSITIVITY)
@ -70,7 +68,7 @@ open class SensitivityAAPSPlugin @Inject constructor(
return AutosensResult() return AutosensResult()
} }
val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet() val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet()
val profileSwitches = databaseHelper.getProfileSwitchEventsFromTime(fromTime, true) val profileSwitches = repository.getEffectiveProfileSwitchDataFromTime(fromTime, true).blockingGet()
val deviationsArray: MutableList<Double> = ArrayList() val deviationsArray: MutableList<Double> = ArrayList()
var pastSensitivity = "" var pastSensitivity = ""
var index = 0 var index = 0
@ -86,13 +84,13 @@ open class SensitivityAAPSPlugin @Inject constructor(
} }
// reset deviations after site change // reset deviations after site change
if (isEvent5minBack(siteChanges, autosensData.time)) { if (siteChanges.isTherapyEventEvent5minBack(autosensData.time)) {
deviationsArray.clear() deviationsArray.clear()
pastSensitivity += "(SITECHANGE)" pastSensitivity += "(SITECHANGE)"
} }
// reset deviations after profile switch // reset deviations after profile switch
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) { if (profileSwitches.isEPSEvent5minBack(autosensData.time)) {
deviationsArray.clear() deviationsArray.clear()
pastSensitivity += "(PROFILESWITCH)" pastSensitivity += "(PROFILESWITCH)"
} }
@ -110,14 +108,14 @@ open class SensitivityAAPSPlugin @Inject constructor(
index++ index++
} }
val deviations = Array(deviationsArray.size) { i -> deviationsArray[i] } val deviations = Array(deviationsArray.size) { i -> deviationsArray[i] }
val sens = profile.isfMgdl val sens = profile.getIsfMgdl()
val ratioLimit = "" val ratioLimit = ""
val sensResult: String val sensResult: String
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity") aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
Arrays.sort(deviations) Arrays.sort(deviations)
val percentile = IobCobCalculatorPlugin.percentile(deviations, 0.50) val percentile = IobCobCalculatorPlugin.percentile(deviations, 0.50)
val basalOff = percentile * (60.0 / 5.0) / sens val basalOff = percentile * (60.0 / 5.0) / sens
val ratio = 1 + basalOff / profile.maxDailyBasal val ratio = 1 + basalOff / profile.getMaxDailyBasal()
sensResult = when { sensResult = when {
percentile < 0 -> "Excess insulin sensitivity detected" percentile < 0 -> "Excess insulin sensitivity detected"
percentile > 0 -> "Excess insulin resistance detected" percentile > 0 -> "Excess insulin resistance detected"

View file

@ -3,14 +3,13 @@ package info.nightscout.androidaps.plugins.sensitivity
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
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.extensions.isEPSEvent5minBack
import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.extensions.isTherapyEventEvent5minBack
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -37,7 +36,6 @@ open class SensitivityOref1Plugin @Inject constructor(
sp: SP, sp: SP,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val databaseHelper: DatabaseHelperInterface,
private val repository: AppRepository private val repository: AppRepository
) : AbstractSensitivityPlugin(PluginDescription() ) : AbstractSensitivityPlugin(PluginDescription()
.mainType(PluginType.SENSITIVITY) .mainType(PluginType.SENSITIVITY)
@ -71,7 +69,7 @@ open class SensitivityOref1Plugin @Inject constructor(
return AutosensResult() return AutosensResult()
} }
val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet() val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet()
val profileSwitches = databaseHelper.getProfileSwitchEventsFromTime(fromTime, true) val profileSwitches = repository.getEffectiveProfileSwitchDataFromTime(fromTime, true).blockingGet()
//[0] = 8 hour //[0] = 8 hour
//[1] = 24 hour //[1] = 24 hour
@ -102,14 +100,14 @@ open class SensitivityOref1Plugin @Inject constructor(
var pastSensitivity = pastSensitivityArray[hourSegment] var pastSensitivity = pastSensitivityArray[hourSegment]
// reset deviations after site change // reset deviations after site change
if (isEvent5minBack(siteChanges, autosensData.time)) { if (siteChanges.isTherapyEventEvent5minBack(autosensData.time)) {
deviationsArray.clear() deviationsArray.clear()
pastSensitivity += "(SITECHANGE)" pastSensitivity += "(SITECHANGE)"
pastSensitivity += "(SITECHANGE)" pastSensitivity += "(SITECHANGE)"
} }
// reset deviations after profile switch // reset deviations after profile switch
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) { if (profileSwitches.isEPSEvent5minBack(autosensData.time)) {
deviationsArray.clear() deviationsArray.clear()
pastSensitivity += "(PROFILESWITCH)" pastSensitivity += "(PROFILESWITCH)"
} }
@ -159,7 +157,7 @@ open class SensitivityOref1Plugin @Inject constructor(
if (hourUsed == 1) sensResult = "(24 hours) " if (hourUsed == 1) sensResult = "(24 hours) "
val ratioLimit = "" val ratioLimit = ""
val deviations: Array<Double> = Array(deviationsArray.size) { i -> deviationsArray[i] } val deviations: Array<Double> = Array(deviationsArray.size) { i -> deviationsArray[i] }
val sens = profile.isfMgdl val sens = profile.getIsfMgdl()
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity") aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
Arrays.sort(deviations) Arrays.sort(deviations)
val pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50) val pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50)
@ -179,7 +177,7 @@ open class SensitivityOref1Plugin @Inject constructor(
else -> sensResult += "Sensitivity normal" else -> sensResult += "Sensitivity normal"
} }
aapsLogger.debug(LTag.AUTOSENS, sensResult) aapsLogger.debug(LTag.AUTOSENS, sensResult)
val ratio = 1 + basalOff / profile.maxDailyBasal val ratio = 1 + basalOff / profile.getMaxDailyBasal()
//Update the data back to the parent //Update the data back to the parent
sensResultArray[hourUsed] = sensResult sensResultArray[hourUsed] = sensResult

View file

@ -4,14 +4,13 @@ import androidx.collection.LongSparseArray
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
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.extensions.isEPSEvent5minBack
import info.nightscout.androidaps.extensions.isEvent5minBack import info.nightscout.androidaps.extensions.isTherapyEventEvent5minBack
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -35,7 +34,6 @@ open class SensitivityWeightedAveragePlugin @Inject constructor(
sp: SP, sp: SP,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val databaseHelper: DatabaseHelperInterface,
private val repository: AppRepository private val repository: AppRepository
) : AbstractSensitivityPlugin(PluginDescription() ) : AbstractSensitivityPlugin(PluginDescription()
.mainType(PluginType.SENSITIVITY) .mainType(PluginType.SENSITIVITY)
@ -69,7 +67,7 @@ open class SensitivityWeightedAveragePlugin @Inject constructor(
return AutosensResult() return AutosensResult()
} }
val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet() val siteChanges = repository.getTherapyEventDataFromTime(fromTime, TherapyEvent.Type.CANNULA_CHANGE, true).blockingGet()
val profileSwitches = databaseHelper.getProfileSwitchEventsFromTime(fromTime, true) val profileSwitches = repository.getEffectiveProfileSwitchDataFromTime(fromTime, true).blockingGet()
var pastSensitivity = "" var pastSensitivity = ""
var index = 0 var index = 0
val data = LongSparseArray<Double>() val data = LongSparseArray<Double>()
@ -89,13 +87,13 @@ open class SensitivityWeightedAveragePlugin @Inject constructor(
} }
// reset deviations after site change // reset deviations after site change
if (isEvent5minBack(siteChanges, autosensData.time)) { if (siteChanges.isTherapyEventEvent5minBack(autosensData.time)) {
data.clear() data.clear()
pastSensitivity += "(SITECHANGE)" pastSensitivity += "(SITECHANGE)"
} }
// reset deviations after profile switch // reset deviations after profile switch
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) { if (profileSwitches.isEPSEvent5minBack(autosensData.time)) {
data.clear() data.clear()
pastSensitivity += "(PROFILESWITCH)" pastSensitivity += "(PROFILESWITCH)"
} }
@ -133,13 +131,13 @@ open class SensitivityWeightedAveragePlugin @Inject constructor(
if (weights == 0.0) { if (weights == 0.0) {
return AutosensResult() return AutosensResult()
} }
val sens = profile.isfMgdl val sens = profile.getIsfMgdl()
val ratioLimit = "" val ratioLimit = ""
val sensResult: String val sensResult: String
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity") aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
val average = weightedSum / weights val average = weightedSum / weights
val basalOff = average * (60 / 5.0) / sens val basalOff = average * (60 / 5.0) / sens
val ratio = 1 + basalOff / profile.maxDailyBasal val ratio = 1 + basalOff / profile.getMaxDailyBasal()
sensResult = when { sensResult = when {
average < 0 -> "Excess insulin sensitivity detected" average < 0 -> "Excess insulin sensitivity detected"
average > 0 -> "Excess insulin resistance detected" average > 0 -> "Excess insulin resistance detected"

View file

@ -10,15 +10,19 @@ import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InvalidateGlucoseValueTransaction import info.nightscout.androidaps.database.transactions.InvalidateGlucoseValueTransaction
import info.nightscout.androidaps.databinding.BgsourceFragmentBinding import info.nightscout.androidaps.databinding.BgsourceFragmentBinding
import info.nightscout.androidaps.databinding.BgsourceItemBinding import info.nightscout.androidaps.databinding.BgsourceItemBinding
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.extensions.directionToIcon
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnitsString
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -26,11 +30,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.directionToIcon
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnitsString
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PluginBase
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 io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -45,7 +44,6 @@ class BGSourceFragment : DaggerFragment() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger

View file

@ -3,9 +3,6 @@ package info.nightscout.androidaps.plugins.treatments;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.analytics.FirebaseAnalytics;
import java.util.List; import java.util.List;
@ -19,22 +16,17 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.embedments.InterfaceIDs;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.interfaces.ActivePlugin;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; import info.nightscout.androidaps.interfaces.TreatmentServiceInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.interfaces.UpdateReturn; import info.nightscout.androidaps.interfaces.UpdateReturn;
@ -42,8 +34,6 @@ import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData;
@ -73,13 +63,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
protected TreatmentServiceInterface service; protected TreatmentServiceInterface service;
private final ProfileIntervals<ProfileSwitch> profiles = new ProfileIntervals<>();
private final boolean useNewPumpSync = false; private final boolean useNewPumpSync = false;
@Inject @Inject
public TreatmentsPlugin( public TreatmentsPlugin(
HasAndroidInjector injector, HasAndroidInjector injector,
@ -125,14 +111,13 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override @Override
protected void onStart() { protected void onStart() {
this.service = new TreatmentService(getInjector()); this.service = new TreatmentService(getInjector());
initializeData(range());
super.onStart(); super.onStart();
disposable.add(rxBus // disposable.add(rxBus
.toObservable(EventReloadProfileSwitchData.class) // .toObservable(EventReloadProfileSwitchData.class)
.observeOn(aapsSchedulers.getIo()) // .observeOn(aapsSchedulers.getIo())
.subscribe(event -> initializeProfileSwitchData(range()), // .subscribe(event -> initializeProfileSwitchData(range()),
fabricPrivacy::logException // fabricPrivacy::logException
)); // ));
} }
@Override @Override
@ -153,17 +138,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
return (long) (60 * 60 * 1000L * (24 + dia)); return (long) (60 * 60 * 1000L * (24 + dia));
} }
public void initializeData(long range) {
initializeProfileSwitchData(range);
}
private void initializeProfileSwitchData(long range) {
getAapsLogger().debug(LTag.DATATREATMENTS, "initializeProfileSwitchData");
synchronized (profiles) {
profiles.reset().add(databaseHelper.getProfileSwitchData(dateUtil.now() - range, false));
}
}
/** /**
* Returns all Treatments after specified timestamp. Also returns invalid entries (required to * Returns all Treatments after specified timestamp. Also returns invalid entries (required to
* map "Fill Cannula" entries to history (and not to add double bolus for it) * map "Fill Cannula" entries to history (and not to add double bolus for it)
@ -343,6 +317,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
getService().createOrUpdateMedtronic(carbsTreatment, false); getService().createOrUpdateMedtronic(carbsTreatment, false);
//log.debug("Adding new Treatment record" + carbsTreatment); //log.debug("Adding new Treatment record" + carbsTreatment);
} }
getAapsLogger().error("nsUpload.uploadTreatmentRecord(detailedBolusInfo) not possible.");
// if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) // if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING)
// nsUpload.uploadTreatmentRecord(detailedBolusInfo); // nsUpload.uploadTreatmentRecord(detailedBolusInfo);
@ -362,56 +338,4 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
return newRecordCreated; return newRecordCreated;
} }
@Override
@Nullable
public ProfileSwitch getProfileSwitchFromHistory(long time) {
synchronized (profiles) {
return (ProfileSwitch) profiles.getValueToTime(time);
}
}
@Override
public ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory() {
synchronized (profiles) {
return new ProfileIntervals<>(profiles);
}
}
@Override
public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) {
//log.debug("Adding new TemporaryBasal record" + profileSwitch.log());
rxBus.send(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING));
databaseHelper.createOrUpdate(profileSwitch);
nsUpload.uploadProfileSwitch(profileSwitch, profileSwitch.date, dateUtil);
}
@Override
public void doProfileSwitch(@NonNull final ProfileStore profileStore, @NonNull final String profileName, final int duration, final int percentage, final int timeShift, final long date) {
ProfileSwitch profileSwitch = profileFunction.prepareProfileSwitch(profileStore, profileName, duration, percentage, timeShift, date);
addToHistoryProfileSwitch(profileSwitch);
if (percentage == 90 && duration == 10)
sp.putBoolean(R.string.key_objectiveuseprofileswitch, true);
}
@Override
public void doProfileSwitch(final int duration, final int percentage, final int timeShift) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(System.currentTimeMillis());
if (profileSwitch != null) {
profileSwitch = new ProfileSwitch(getInjector());
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = profileFunction.getProfileName(System.currentTimeMillis(), false, false);
profileSwitch.profileJson = profileFunction.getProfile().getData().toString();
profileSwitch.profilePlugin = activePlugin.getActiveProfileSource().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeShift != 0;
profileSwitch.timeshift = timeShift;
profileSwitch.percentage = percentage;
addToHistoryProfileSwitch(profileSwitch);
} else {
getAapsLogger().error(LTag.PROFILE, "No profile switch exists");
}
}
} }

View file

@ -105,7 +105,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
onError = { aapsLogger.error("Error removing entries", it) }, onError = { aapsLogger.error("Error removing entries", it) },
onComplete = { onComplete = {
rxBus.send(EventTreatmentChange()) rxBus.send(EventTreatmentChange())
rxBus.send(EventNewHistoryData(0, false)) } rxBus.send(EventNewHistoryData(0, false))
}
) )
rxBus.send(EventNSClientRestart()) rxBus.send(EventNSClientRestart())
} }
@ -258,10 +259,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() { inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder =
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false) MealLinkLoadedViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false))
return MealLinkLoadedViewHolder(v)
}
override fun onBindViewHolder(holder: MealLinkLoadedViewHolder, position: Int) { override fun onBindViewHolder(holder: MealLinkLoadedViewHolder, position: Int) {
val profile = profileFunction.getProfile() ?: return val profile = profileFunction.getProfile() ?: return
@ -283,7 +282,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility() holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility()
val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia) val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia)
holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib) holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.iobContrib)
if (iob.iobContrib != 0.0) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.carbs.currentTextColor) holder.binding.iobLabel.visibility = (iob.iobContrib != 0.0).toVisibility()
holder.binding.iob.visibility = (iob.iobContrib != 0.0).toVisibility()
if (bolus.timestamp > dateUtil.now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor) if (bolus.timestamp > dateUtil.now()) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor)
holder.binding.mealOrCorrection.text = holder.binding.mealOrCorrection.text =
when (ml.bolus.type) { when (ml.bolus.type) {

View file

@ -9,42 +9,49 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.ValueWithUnit 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.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InvalidateProfileSwitchTransaction
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchFragmentBinding import info.nightscout.androidaps.databinding.TreatmentsProfileswitchFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.events.EventProfileNeedsUpdate import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.extensions.getCustomizedName
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.UploadQueueInterface import info.nightscout.androidaps.interfaces.UploadQueueInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsProfileSwitchFragment.RecyclerProfileViewAdapter.ProfileSwitchViewHolder import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsProfileSwitchFragment.RecyclerProfileViewAdapter.ProfileSwitchViewHolder
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.extensions.toVisibility
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.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import javax.inject.Inject import javax.inject.Inject
class TreatmentsProfileSwitchFragment : DaggerFragment() { class TreatmentsProfileSwitchFragment : DaggerFragment() {
private val disposable = CompositeDisposable()
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var localProfilePlugin: LocalProfilePlugin
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -53,11 +60,15 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private var _binding: TreatmentsProfileswitchFragmentBinding? = null private var _binding: TreatmentsProfileswitchFragmentBinding? = null
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
// onDestroyView. // onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
@ -69,29 +80,82 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.recyclerview.setHasFixedSize(true) binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context) binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.recyclerview.adapter = RecyclerProfileViewAdapter(databaseHelper.getProfileSwitchData(dateUtil.now() - T.days(30).msecs(), false))
binding.refreshFromNightscout.setOnClickListener { binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
uel.log(Action.PROFILE_SWITCH_NS_REFRESH, Sources.Treatments)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") {
databaseHelper.resetProfileSwitch() uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
disposable +=
Completable.fromAction {
repository.deleteAllEffectiveProfileSwitches()
repository.deleteAllProfileSwitches()
}
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = {
rxBus.send(EventProfileSwitchChanged())
rxBus.send(EventNewHistoryData(0, false))
}
)
rxBus.send(EventNSClientRestart()) rxBus.send(EventNSClientRestart())
} }
} }
} }
if (sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE if (sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
rxBus.send(EventTreatmentUpdateGui())
}
}
private fun profileSwitchWithInvalid(now: Long) = repository
.getProfileSwitchDataIncludingInvalidFromTime(now - millsToThePast, false)
.map { bolus -> bolus.map { ProfileSealed.PS(it) } }
private fun effectiveProfileSwitchWithInvalid(now: Long) = repository
.getEffectiveProfileSwitchDataIncludingInvalidFromTime(now - millsToThePast, false)
.map { carb -> carb.map { ProfileSealed.EPS(it) } }
private fun profileSwitches(now: Long) = repository
.getProfileSwitchDataFromTime(now - millsToThePast, false)
.map { bolus -> bolus.map { ProfileSealed.PS(it) } }
private fun effectiveProfileSwitches(now: Long) = repository
.getEffectiveProfileSwitchDataFromTime(now - millsToThePast, false)
.map { carb -> carb.map { ProfileSealed.EPS(it) } }
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
disposable += profileSwitchWithInvalid(now)
.zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
else
disposable += profileSwitches(now)
.zipWith(effectiveProfileSwitches(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
} }
@Synchronized @Synchronized
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
swapAdapter()
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventProfileNeedsUpdate::class.java) .toObservable(EventProfileSwitchChanged::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ updateGUI() }, fabricPrivacy::logException) .subscribe({ swapAdapter() }, fabricPrivacy::logException)
) )
updateGUI()
} }
@Synchronized @Synchronized
@ -103,36 +167,34 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
@Synchronized @Synchronized
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
binding.recyclerview.adapter = null // avoid leaks
_binding = null _binding = null
} }
fun updateGUI() { inner class RecyclerProfileViewAdapter(private var profileSwitchList: List<ProfileSealed>) : RecyclerView.Adapter<ProfileSwitchViewHolder>() {
if (_binding == null) return
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(databaseHelper.getProfileSwitchData(dateUtil.now() - T.days(30).msecs(), false)), false)
}
inner class RecyclerProfileViewAdapter(private var profileSwitchList: List<ProfileSwitch>) : RecyclerView.Adapter<ProfileSwitchViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ProfileSwitchViewHolder = override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ProfileSwitchViewHolder =
ProfileSwitchViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_profileswitch_item, viewGroup, false)) ProfileSwitchViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_profileswitch_item, viewGroup, false))
override fun onBindViewHolder(holder: ProfileSwitchViewHolder, position: Int) { override fun onBindViewHolder(holder: ProfileSwitchViewHolder, position: Int) {
val profileSwitch = profileSwitchList[position] val profileSwitch = profileSwitchList[position]
holder.binding.ph.visibility = (profileSwitch.source == Source.PUMP).toVisibility() holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
holder.binding.ns.visibility = NSUpload.isIdValid(profileSwitch._id).toVisibility() holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility()
holder.binding.date.text = dateUtil.dateAndTimeString(profileSwitch.date) holder.binding.date.text = dateUtil.dateAndTimeString(profileSwitch.timestamp)
if (!profileSwitch.isEndingEvent) { holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
holder.binding.duration.text = resourceHelper.gs(R.string.format_mins, profileSwitch.durationInMinutes) holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
} else { if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive))
holder.binding.duration.text = "" else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
}
holder.binding.name.text = profileSwitch.customizedName
if (profileSwitch.isInProgress) holder.binding.date.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.remove.tag = profileSwitch holder.binding.remove.tag = profileSwitch
holder.binding.clone.tag = profileSwitch holder.binding.clone.tag = profileSwitch
holder.binding.name.tag = profileSwitch holder.binding.name.tag = profileSwitch
holder.binding.date.tag = profileSwitch holder.binding.date.tag = profileSwitch
holder.binding.invalid.visibility = if (profileSwitch.isValid) View.GONE else View.VISIBLE holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility()
holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility()
holder.binding.remove.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.root.setBackgroundColor(resourceHelper.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter))
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
@ -144,38 +206,34 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
val binding = TreatmentsProfileswitchItemBinding.bind(itemView) val binding = TreatmentsProfileswitchItemBinding.bind(itemView)
init { init {
binding.remove.setOnClickListener { binding.remove.setOnClickListener { view ->
val profileSwitch = it.tag as ProfileSwitch val profileSwitch = view.tag as ProfileSealed.PS
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord),
resourceHelper.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + resourceHelper.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName +
"\n" + resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.date), Runnable { "\n" + resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable {
uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
ValueWithUnit.Timestamp(profileSwitch.date)) ValueWithUnit.Timestamp(profileSwitch.timestamp))
val id = profileSwitch._id disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id))
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id) .subscribe(
else uploadQueue.removeByMongoId("dbAdd", id) { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } },
databaseHelper.delete(profileSwitch) { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
)
}) })
} }
} }
binding.clone.setOnClickListener { binding.clone.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
val profileSwitch = it.tag as ProfileSwitch val profileSwitch = (it.tag as ProfileSealed.PS).value
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.customizedName + "\n" + dateUtil.dateAndTimeString(profileSwitch.date), Runnable { val profileSealed = it.tag as ProfileSealed
profileSwitch.profileObject?.let { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable {
uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments, uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments,
profileSwitch.customizedName + " " + dateUtil.dateAndTimeString(profileSwitch.date).replace(".", "_"), profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"),
ValueWithUnit.Timestamp(profileSwitch.date), ValueWithUnit.Timestamp(profileSwitch.timestamp),
ValueWithUnit.SimpleString(profileSwitch.profileName)) ValueWithUnit.SimpleString(profileSwitch.profileName))
val nonCustomized = it.convertToNonCustomizedProfile() val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil)
if (nonCustomized.isValid(resourceHelper.gs(R.string.careportal_profileswitch, false))) { localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_")))
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.customizedName + " " + dateUtil.dateAndTimeString(profileSwitch.date).replace(".", "_")))
rxBus.send(EventLocalProfileChanged()) rxBus.send(EventLocalProfileChanged())
} else {
OKDialog.show(activity, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile_invalid))
}
}
}) })
} }
} }
@ -184,7 +242,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
binding.name.setOnClickListener { binding.name.setOnClickListener {
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { args -> pvd.arguments = Bundle().also { args ->
args.putLong("time", (it.tag as ProfileSwitch).date) args.putLong("time", (it.tag as ProfileSealed).timestamp)
args.putInt("mode", ProfileViewerDialog.Mode.DB_PROFILE.ordinal) args.putInt("mode", ProfileViewerDialog.Mode.DB_PROFILE.ordinal)
} }
pvd.show(childFragmentManager, "ProfileViewDialog") pvd.show(childFragmentManager, "ProfileViewDialog")
@ -193,7 +251,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
binding.date.setOnClickListener { binding.date.setOnClickListener {
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { args -> pvd.arguments = Bundle().also { args ->
args.putLong("time", (it.tag as ProfileSwitch).date) args.putLong("time", (it.tag as ProfileSealed).timestamp)
args.putInt("mode", ProfileViewerDialog.Mode.DB_PROFILE.ordinal) args.putInt("mode", ProfileViewerDialog.Mode.DB_PROFILE.ordinal)
} }
pvd.show(childFragmentManager, "ProfileViewDialog") pvd.show(childFragmentManager, "ProfileViewDialog")

View file

@ -5,24 +5,24 @@ import android.content.Intent
import android.os.SystemClock import android.os.SystemClock
import android.text.Spanned import android.text.Spanned
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import dagger.Lazy
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.BolusProgressHelperActivity import info.nightscout.androidaps.activities.BolusProgressHelperActivity
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.database.entities.ProfileSwitch
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.dialogs.BolusProgressDialog import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventBolusRequested import info.nightscout.androidaps.events.EventBolusRequested
import info.nightscout.androidaps.events.EventNewBasalProfile import info.nightscout.androidaps.events.EventNewBasalProfile
import info.nightscout.androidaps.events.EventProfileNeedsUpdate import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.extensions.getCustomizedName
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync
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.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -56,7 +56,7 @@ open class CommandQueue @Inject constructor(
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val constraintChecker: ConstraintChecker, private val constraintChecker: ConstraintChecker,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val activePlugin: Lazy<ActivePlugin>, private val activePlugin: ActivePlugin,
private val context: Context, private val context: Context,
private val sp: SP, private val sp: SP,
private val buildHelper: BuildHelper, private val buildHelper: BuildHelper,
@ -74,17 +74,37 @@ open class CommandQueue @Inject constructor(
init { init {
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventProfileNeedsUpdate::class.java) .toObservable(EventProfileSwitchChanged::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ .subscribe({
aapsLogger.debug(LTag.PROFILE, "onProfileSwitch") aapsLogger.debug(LTag.PROFILE, "onProfileSwitch")
profileFunction.getProfile()?.let { profileFunction.getRequestedProfile()?.let {
setProfile(it, object : Callback() { val nonCustomized = ProfileSealed.PS(it).convertToNonCustomizedProfile(dateUtil)
setProfile(ProfileSealed.Pure(nonCustomized), it.interfaceIDs.nightscoutId != null, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.failedupdatebasalprofile), R.raw.boluserror) ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.failedupdatebasalprofile), R.raw.boluserror)
} }
if (result.enacted) rxBus.send(EventNewBasalProfile()) if (result.enacted) {
rxBus.send(EventNewBasalProfile())
repository.createEffectiveProfileSwitch(
EffectiveProfileSwitch(
timestamp = dateUtil.now(),
basalBlocks = nonCustomized.basalBlocks,
isfBlocks = nonCustomized.isfBlocks,
icBlocks = nonCustomized.icBlocks,
targetBlocks = nonCustomized.targetBlocks,
glucoseUnit = if (it.glucoseUnit == ProfileSwitch.GlucoseUnit.MGDL) EffectiveProfileSwitch.GlucoseUnit.MGDL else EffectiveProfileSwitch.GlucoseUnit.MMOL,
originalProfileName = it.profileName,
originalCustomizedName = it.getCustomizedName(),
originalTimeshift = it.timeshift,
originalPercentage = it.percentage,
originalDuration = it.duration,
originalEnd = it.end,
insulinConfiguration = it.insulinConfiguration
)
)
}
} }
}) })
} }
@ -156,7 +176,7 @@ open class CommandQueue @Inject constructor(
open fun notifyAboutNewCommand() { open fun notifyAboutNewCommand() {
waitForFinishedThread() waitForFinishedThread()
if (thread == null || thread!!.state == Thread.State.TERMINATED) { if (thread == null || thread!!.state == Thread.State.TERMINATED) {
thread = QueueThread(this, context, aapsLogger, rxBus, activePlugin.get(), resourceHelper, sp) thread = QueueThread(this, context, aapsLogger, rxBus, activePlugin, resourceHelper, sp)
thread!!.start() thread!!.start()
aapsLogger.debug(LTag.PUMPQUEUE, "Starting new thread") aapsLogger.debug(LTag.PUMPQUEUE, "Starting new thread")
} else { } else {
@ -199,7 +219,7 @@ open class CommandQueue @Inject constructor(
// If not, it's not necessary add command to the queue and initiate connection // If not, it's not necessary add command to the queue and initiate connection
// Assuming carbs in the future and carbs with duration are NOT stores anyway // Assuming carbs in the future and carbs with duration are NOT stores anyway
if ((detailedBolusInfo.carbs > 0) && if ((detailedBolusInfo.carbs > 0) &&
(!activePlugin.get().activePump.pumpDescription.storesCarbInfo || (!activePlugin.activePump.pumpDescription.storesCarbInfo ||
detailedBolusInfo.carbsDuration != 0L || detailedBolusInfo.carbsDuration != 0L ||
(detailedBolusInfo.carbsTimestamp ?: detailedBolusInfo.timestamp) > dateUtil.now()) (detailedBolusInfo.carbsTimestamp ?: detailedBolusInfo.timestamp) > dateUtil.now())
) { ) {
@ -286,7 +306,7 @@ open class CommandQueue @Inject constructor(
} }
removeAll(CommandType.BOLUS) removeAll(CommandType.BOLUS)
removeAll(CommandType.SMB_BOLUS) removeAll(CommandType.SMB_BOLUS)
Thread { activePlugin.get().activePump.stopBolusDelivering() }.run() Thread { activePlugin.activePump.stopBolusDelivering() }.run()
} }
// returns true if command is queued // returns true if command is queued
@ -363,8 +383,8 @@ open class CommandQueue @Inject constructor(
} }
// returns true if command is queued // returns true if command is queued
override fun setProfile(profile: Profile, callback: Callback?): Boolean { override fun setProfile(profile: Profile, hasNsId: Boolean, callback: Callback?): Boolean {
if (isThisProfileSet(profile)) { if (isThisProfileSet(profile) && repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing) {
aapsLogger.debug(LTag.PUMPQUEUE, "Correct profile already set") aapsLogger.debug(LTag.PUMPQUEUE, "Correct profile already set")
callback?.result(PumpEnactResult(injector).success(true).enacted(false))?.run() callback?.result(PumpEnactResult(injector).success(true).enacted(false))?.run()
return false return false
@ -378,9 +398,9 @@ open class CommandQueue @Inject constructor(
} }
*/ */
// Compare with pump limits // Compare with pump limits
val basalValues = profile.basalValues val basalValues = profile.getBasalValues()
for (basalValue in basalValues) { for (basalValue in basalValues) {
if (basalValue.value < activePlugin.get().activePump.pumpDescription.basalMinimumRate) { if (basalValue.value < activePlugin.activePump.pumpDescription.basalMinimumRate) {
val notification = Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, resourceHelper.gs(R.string.basalvaluebelowminimum), Notification.URGENT) val notification = Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, resourceHelper.gs(R.string.basalvaluebelowminimum), Notification.URGENT)
rxBus.send(EventNewNotification(notification)) rxBus.send(EventNewNotification(notification))
callback?.result(PumpEnactResult(injector).success(false).enacted(false).comment(R.string.basalvaluebelowminimum))?.run() callback?.result(PumpEnactResult(injector).success(false).enacted(false).comment(R.string.basalvaluebelowminimum))?.run()
@ -391,7 +411,7 @@ open class CommandQueue @Inject constructor(
// remove all unfinished // remove all unfinished
removeAll(CommandType.BASAL_PROFILE) removeAll(CommandType.BASAL_PROFILE)
// add new command to queue // add new command to queue
add(CommandSetProfile(injector, profile, callback)) add(CommandSetProfile(injector, profile, hasNsId, callback))
notifyAboutNewCommand() notifyAboutNewCommand()
return true return true
} }
@ -547,16 +567,12 @@ open class CommandQueue @Inject constructor(
} }
override fun isThisProfileSet(profile: Profile): Boolean { override fun isThisProfileSet(profile: Profile): Boolean {
val activePump = activePlugin.get().activePump val result = activePlugin.activePump.isThisProfileSet(profile)
val current = profileFunction.getProfile()
return if (current != null) {
val result = activePump.isThisProfileSet(profile)
if (!result) { if (!result) {
aapsLogger.debug(LTag.PUMPQUEUE, "Current profile: $current") aapsLogger.debug(LTag.PUMPQUEUE, "Current profile: ${profileFunction.getProfile()}")
aapsLogger.debug(LTag.PUMPQUEUE, "New profile: $profile") aapsLogger.debug(LTag.PUMPQUEUE, "New profile: $profile")
} }
result return result
} else true
} }
private fun showBolusProgressDialog(insulin: Double, ctx: Context?) { private fun showBolusProgressDialog(insulin: Double, ctx: Context?) {

View file

@ -2,25 +2,28 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil
import javax.inject.Inject import javax.inject.Inject
class CommandSetProfile constructor( class CommandSetProfile constructor(
injector: HasAndroidInjector, injector: HasAndroidInjector,
private val profile: Profile, private val profile: Profile,
private val hasNsId: Boolean,
callback: Callback? callback: Callback?
) : Command(injector, CommandType.BASAL_PROFILE, callback) { ) : Command(injector, CommandType.BASAL_PROFILE, callback) {
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
override fun execute() { override fun execute() {
@ -33,13 +36,12 @@ class CommandSetProfile constructor(
aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted} profile: $profile") aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted} profile: $profile")
callback?.result(r)?.run() callback?.result(r)?.run()
// Send SMS notification if ProfileSwitch is coming from NS // Send SMS notification if ProfileSwitch is coming from NS
val profileSwitch = activePlugin.activeTreatments.getProfileSwitchFromHistory(System.currentTimeMillis()) val profileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (profileSwitch != null && r.enacted && profileSwitch.source == Source.NIGHTSCOUT) { if (profileSwitch is ValueWrapper.Existing && r.enacted && hasNsId) {
if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) { if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL))
smsCommunicatorPlugin.sendNotificationToAllNumbers(resourceHelper.gs(R.string.profile_set_ok)) smsCommunicatorPlugin.sendNotificationToAllNumbers(resourceHelper.gs(R.string.profile_set_ok))
} }
} }
}
override fun status(): String = "SET PROFILE" override fun status(): String = "SET PROFILE"
} }

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.queue.commands package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.queue.commands package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag

View file

@ -14,9 +14,10 @@ import androidx.work.WorkerParameters
import dagger.android.DaggerBroadcastReceiver import dagger.android.DaggerBroadcastReceiver
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.events.EventProfileNeedsUpdate import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.extensions.buildDeviceStatus import info.nightscout.androidaps.extensions.buildDeviceStatus
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
@ -117,10 +118,11 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() {
private fun checkPump() { private fun checkPump() {
val pump = activePlugin.activePump val pump = activePlugin.activePump
val profile = profileFunction.getProfile() ?: return val ps = profileFunction.getRequestedProfile() ?: return
val profile = ProfileSealed.PS(ps)
val lastConnection = pump.lastDataTime() val lastConnection = pump.lastDataTime()
val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis() val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis()
val isBasalOutdated = abs(profile.basal - pump.baseBasalRate) > pump.pumpDescription.basalStep val isBasalOutdated = abs(profile.getBasal() - pump.baseBasalRate) > pump.pumpDescription.basalStep
aapsLogger.debug(LTag.CORE, "Last connection: " + dateUtil.dateAndTimeString(lastConnection)) aapsLogger.debug(LTag.CORE, "Last connection: " + dateUtil.dateAndTimeString(lastConnection))
// sometimes keep alive broadcast stops // sometimes keep alive broadcast stops
// as as workaround test if readStatus was requested before an alarm is generated // as as workaround test if readStatus was requested before an alarm is generated
@ -128,7 +130,7 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() {
localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loopPlugin.isDisconnected) localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loopPlugin.isDisconnected)
} }
if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) { if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) {
rxBus.send(EventProfileNeedsUpdate()) rxBus.send(EventProfileSwitchChanged())
} else if (isStatusOutdated && !pump.isBusy()) { } else if (isStatusOutdated && !pump.isBusy()) {
lastReadStatus = System.currentTimeMillis() lastReadStatus = System.currentTimeMillis()
commandQueue.readStatus("KeepAlive. Status outdated.", null) commandQueue.readStatus("KeepAlive. Status outdated.", null)

View file

@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
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
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -30,7 +31,6 @@ import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.AndroidPermission import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.CryptoUtil import info.nightscout.androidaps.utils.CryptoUtil
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.extensions.isRunningTest import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -57,7 +57,7 @@ class SWDefinition @Inject constructor(
private val importExportPrefs: ImportExportPrefs, private val importExportPrefs: ImportExportPrefs,
private val androidPermission: AndroidPermission, private val androidPermission: AndroidPermission,
private val cryptoUtil: CryptoUtil, private val cryptoUtil: CryptoUtil,
private val config: ConfigImpl private val config: Config
) { ) {
lateinit var activity: AppCompatActivity lateinit var activity: AppCompatActivity
@ -268,13 +268,13 @@ class SWDefinition @Inject constructor(
.label(R.string.adjustprofileinns)) .label(R.string.adjustprofileinns))
.add(SWFragment(injector, this) .add(SWFragment(injector, this)
.add(NSProfileFragment())) .add(NSProfileFragment()))
.validator { nsProfilePlugin.profile != null && nsProfilePlugin.profile!!.getDefaultProfile() != null && nsProfilePlugin.profile!!.getDefaultProfile()!!.isValid("StartupWizard") } .validator { nsProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) } ?: false }
.visibility { nsProfilePlugin.isEnabled() } .visibility { nsProfilePlugin.isEnabled() }
private val screenLocalProfile = SWScreen(injector, R.string.localprofile) private val screenLocalProfile = SWScreen(injector, R.string.localprofile)
.skippable(false) .skippable(false)
.add(SWFragment(injector, this) .add(SWFragment(injector, this)
.add(LocalProfileFragment())) .add(LocalProfileFragment()))
.validator { localProfilePlugin.profile?.getDefaultProfile()?.isValid("StartupWizard") == true } .validator { localProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) } ?: false }
.visibility { localProfilePlugin.isEnabled() } .visibility { localProfilePlugin.isEnabled() }
private val screenProfileSwitch = SWScreen(injector, R.string.careportal_profileswitch) private val screenProfileSwitch = SWScreen(injector, R.string.careportal_profileswitch)
.skippable(false) .skippable(false)

View file

@ -9,7 +9,7 @@ import info.nightscout.androidaps.MainActivity
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.databinding.ActivitySetupwizardBinding import info.nightscout.androidaps.databinding.ActivitySetupwizardBinding
import info.nightscout.androidaps.events.EventProfileNeedsUpdate import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.events.EventProfileStoreChanged import info.nightscout.androidaps.events.EventProfileStoreChanged
import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -94,7 +94,7 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
.subscribe({ updateButtons() }, fabricPrivacy::logException) .subscribe({ updateButtons() }, fabricPrivacy::logException)
) )
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventProfileNeedsUpdate::class.java) .toObservable(EventProfileSwitchChanged::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ updateButtons() }, fabricPrivacy::logException) .subscribe({ updateButtons() }, fabricPrivacy::logException)
) )

View file

@ -7,12 +7,12 @@ import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.setupwizard.SWNumberValidator import info.nightscout.androidaps.setupwizard.SWNumberValidator
import info.nightscout.androidaps.utils.ui.NumberPicker
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ui.NumberPicker
import java.text.DecimalFormat import java.text.DecimalFormat
import javax.inject.Inject import javax.inject.Inject
@ -43,7 +43,7 @@ class SWEditNumberWithUnits(injector: HasAndroidInjector, private val init: Doub
var initValue = sp.getDouble(preferenceId, init) var initValue = sp.getDouble(preferenceId, init)
initValue = Profile.toCurrentUnits(profileFunction.getUnits(), initValue) initValue = Profile.toCurrentUnits(profileFunction.getUnits(), initValue)
val numberPicker = NumberPicker(context) val numberPicker = NumberPicker(context)
if (profileFunction.getUnits() == Constants.MMOL) numberPicker.setParams(initValue, min, max, 0.1, DecimalFormat("0.0"), false, null, watcher) else numberPicker.setParams(initValue, min * 18, max * 18, 1.0, DecimalFormat("0"), false, null, watcher) if (profileFunction.getUnits() == GlucoseUnit.MMOL) numberPicker.setParams(initValue, min, max, 0.1, DecimalFormat("0.0"), false, null, watcher) else numberPicker.setParams(initValue, min * 18, max * 18, 1.0, DecimalFormat("0"), false, null, watcher)
layout.addView(numberPicker) layout.addView(numberPicker)
val c = TextView(context) val c = TextView(context)

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.actions.ActionAlarm import info.nightscout.androidaps.plugins.general.automation.actions.ActionAlarm
@ -37,21 +37,21 @@ class CarbTimer @Inject constructor(
// Bg under 180 mgdl and dropping by 15 mgdl // Bg under 180 mgdl and dropping by 15 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply { list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 180.0, Constants.MGDL, Comparator.Compare.IS_LESSER)) list.add(TriggerBg(injector, 180.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
}) })
// Bg under 160 mgdl and dropping by 9 mgdl // Bg under 160 mgdl and dropping by 9 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply { list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 160.0, Constants.MGDL, Comparator.Compare.IS_LESSER)) list.add(TriggerBg(injector, 160.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
}) })
// Bg under 145 mgdl and dropping // Bg under 145 mgdl and dropping
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply { list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 145.0, Constants.MGDL, Comparator.Compare.IS_LESSER)) list.add(TriggerBg(injector, 145.0, GlucoseUnit.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER)) list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), GlucoseUnit.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
}) })
} }
actions.add(ActionAlarm(injector, resourceHelper.gs(R.string.time_to_eat))) actions.add(ActionAlarm(injector, resourceHelper.gs(R.string.time_to_eat)))

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import info.nightscout.androidaps.utils.PercentageSplitter
import java.util.regex.Pattern import java.util.regex.Pattern
object PercentageSplitter { object PercentageSplitter {
@ -10,7 +9,7 @@ object PercentageSplitter {
/** /**
* Removes the suffix for percentage and timeshift from a profile name. This is the inverse of what * Removes the suffix for percentage and timeshift from a profile name. This is the inverse of what
* [info.nightscout.androidaps.db.ProfileSwitch.getCustomizedName] does. * [ProfileSwitch.getCustomizedName()] does.
* Since the customized name is used for the PS upload to NS, this is needed get the original profile name * Since the customized name is used for the PS upload to NS, this is needed get the original profile name
* when retrieving the PS from NS again. * when retrieving the PS from NS again.
*/ */

View file

@ -3,10 +3,10 @@ package info.nightscout.androidaps.utils
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -23,7 +23,7 @@ class XdripCalibrations @Inject constructor(
fun sendIntent(bg: Double): Boolean { fun sendIntent(bg: Double): Boolean {
val bundle = Bundle() val bundle = Bundle()
bundle.putDouble("glucose_number", bg) bundle.putDouble("glucose_number", bg)
bundle.putString("units", if (profileFunction.getUnits() == Constants.MGDL) "mgdl" else "mmol") bundle.putString("units", if (profileFunction.getUnits() == GlucoseUnit.MGDL) "mgdl" else "mmol")
bundle.putLong("timestamp", System.currentTimeMillis()) bundle.putLong("timestamp", System.currentTimeMillis())
val intent = Intent(Intents.ACTION_REMOTE_CALIBRATION) val intent = Intent(Intents.ACTION_REMOTE_CALIBRATION)
intent.putExtras(bundle) intent.putExtras(bundle)

View file

@ -4,7 +4,7 @@ import android.text.Spanned
import android.util.LongSparseArray import android.util.LongSparseArray
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil

View file

@ -9,7 +9,7 @@ import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.BolusCalculatorResult import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
@ -175,9 +175,9 @@ class BolusWizard @Inject constructor(
this.quickWizard = quickWizard this.quickWizard = quickWizard
// Insulin from BG // Insulin from BG
sens = Profile.fromMgdlToUnits(profile.isfMgdl, profileFunction.getUnits()) sens = Profile.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits())
targetBGLow = Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits()) targetBGLow = Profile.fromMgdlToUnits(profile.getTargetLowMgdl(), profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits()) targetBGHigh = Profile.fromMgdlToUnits(profile.getTargetHighMgdl(), profileFunction.getUnits())
if (useTT && tempTarget != null) { if (useTT && tempTarget != null) {
targetBGLow = Profile.fromMgdlToUnits(tempTarget.lowTarget, profileFunction.getUnits()) targetBGLow = Profile.fromMgdlToUnits(tempTarget.lowTarget, profileFunction.getUnits())
targetBGHigh = Profile.fromMgdlToUnits(tempTarget.highTarget, profileFunction.getUnits()) targetBGHigh = Profile.fromMgdlToUnits(tempTarget.highTarget, profileFunction.getUnits())
@ -201,7 +201,7 @@ class BolusWizard @Inject constructor(
} }
// Insulin from carbs // Insulin from carbs
ic = profile.ic ic = profile.getIc()
insulinFromCarbs = carbs / ic insulinFromCarbs = carbs / ic
insulinFromCOB = if (useCob) (cob / ic) else 0.0 insulinFromCOB = if (useCob) (cob / ic) else 0.0
@ -218,7 +218,7 @@ class BolusWizard @Inject constructor(
// Insulin from superbolus for 2h. Get basal rate now and after 1h // Insulin from superbolus for 2h. Get basal rate now and after 1h
if (useSuperBolus) { if (useSuperBolus) {
insulinFromSuperBolus = profile.basal insulinFromSuperBolus = profile.getBasal()
var timeAfter1h = System.currentTimeMillis() var timeAfter1h = System.currentTimeMillis()
timeAfter1h += T.hours(1).msecs() timeAfter1h += T.hours(1).msecs()
insulinFromSuperBolus += profile.getBasal(timeAfter1h) insulinFromSuperBolus += profile.getBasal(timeAfter1h)

View file

@ -2,11 +2,12 @@ package info.nightscout.androidaps.utils.wizard
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
@ -14,7 +15,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper.safeGetInt import info.nightscout.androidaps.utils.JsonHelper.safeGetInt
import info.nightscout.androidaps.utils.JsonHelper.safeGetString import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
@ -73,7 +73,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
return this return this
} }
fun isActive(): Boolean = Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo() fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo()
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()

View file

@ -89,6 +89,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/iob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"

View file

@ -1,19 +1,44 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsProfileSwitchFragment"> tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsProfileSwitchFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<info.nightscout.androidaps.utils.ui.SingleClickButton <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/refresh_from_nightscout" android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"
android:layout_width="match_parent" 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"
android:layout_weight="1"
android:drawableStart="@drawable/ic_refresh" android:drawableStart="@drawable/ic_refresh"
android:text="@string/refresheventsfromnightscout" /> android:text="@string/refresheventsfromnightscout" />
<CheckBox
android:id="@+id/show_invalidated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:paddingEnd="5dp"
tools:ignore="RtlSymmetry" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="@string/show_removed"
app:srcCompat="@drawable/ic_visibility" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview" android:id="@+id/recyclerview"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -24,8 +24,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:gravity="center_vertical|end" android:gravity="center_vertical|end"
android:paddingEnd="5dp"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="{fa-clock-o}" android:text="{fa-clock-o}"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -48,37 +48,9 @@
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">
<TextView
android:id="@+id/duration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="10dp"
android:text="60 min"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="10dp"
android:text="@string/invalid"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_red_light"
tools:ignore="RtlSymmetry" />
<TextView <TextView
android:id="@+id/ph" android:id="@+id/ph"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:text="PH" android:text="PH"
@ -95,12 +67,46 @@
android:textColor="@color/colorSetTempButton" android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="60 min"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/spacer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="10dp"
android:text="@string/invalid"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_red_light"
tools:ignore="RtlSymmetry" />
<TextView <TextView
android:id="@+id/clone" android:id="@+id/clone"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingEnd="5dp"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="@string/clone_label" android:text="@string/clone_label"
android:textAlignment="viewEnd" android:textAlignment="viewEnd"
android:textColor="@android:color/holo_blue_light" /> android:textColor="@android:color/holo_blue_light" />
@ -109,8 +115,8 @@
android:id="@+id/remove" android:id="@+id/remove"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingEnd="5dp"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="@string/remove_button" android:text="@string/remove_button"
android:textAlignment="viewEnd" android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" /> android:textColor="@android:color/holo_orange_light" />
@ -120,10 +126,10 @@
<View <View
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" /> android:background="@color/list_delimiter" />
</LinearLayout> </LinearLayout>

View file

@ -46,6 +46,7 @@
<string name="key_ns_device_status_last_synced_id" translatable="false">ns_device_status_last_synced_id</string> <string name="key_ns_device_status_last_synced_id" translatable="false">ns_device_status_last_synced_id</string>
<string name="key_ns_temporary_basal_last_synced_id" translatable="false">ns_temporary_basal_last_synced_id</string> <string name="key_ns_temporary_basal_last_synced_id" translatable="false">ns_temporary_basal_last_synced_id</string>
<string name="key_ns_extended_bolus_last_synced_id" translatable="false">ns_extended_bolus_last_synced_id</string> <string name="key_ns_extended_bolus_last_synced_id" translatable="false">ns_extended_bolus_last_synced_id</string>
<string name="key_ns_profile_switch_last_synced_id" translatable="false">profile_switch_last_synced_id</string>
<string name="treatmentssafety_title">Treatments safety</string> <string name="treatmentssafety_title">Treatments safety</string>
<string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string> <string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string>

View file

@ -3,8 +3,10 @@ package info.nightscout.androidaps
import android.content.Context import android.content.Context
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.database.embedments.InsulinConfiguration
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
@ -31,36 +33,34 @@ open class TestBaseWithProfile : TestBase() {
lateinit var dateUtil: DateUtil lateinit var dateUtil: DateUtil
val rxBus = RxBusWrapper(aapsSchedulers) val rxBus = RxBusWrapper(aapsSchedulers)
val profileInjector = HasAndroidInjector { val profileInjector = HasAndroidInjector { AndroidInjector { } }
AndroidInjector {
if (it is Profile) {
it.aapsLogger = aapsLogger
it.activePlugin = activePluginProvider
it.resourceHelper = resourceHelper
it.rxBus = rxBus
it.fabricPrivacy = fabricPrivacy
it.config = config
it.dateUtil = dateUtil
}
if (it is ProfileSwitch) {
it.treatmentsPlugin = treatmentsInterface
it.aapsLogger = aapsLogger
it.rxBus = rxBus
it.resourceHelper = resourceHelper
it.dateUtil = dateUtil
}
}
}
private lateinit var validProfileJSON: String private lateinit var validProfileJSON: String
lateinit var validProfile: Profile lateinit var validProfile: ProfileSealed.Pure
lateinit var effectiveProfileSwitch: EffectiveProfileSwitch
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile" @Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
@Before @Before
fun prepareMock() { fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
dateUtil = DateUtil(context) dateUtil = DateUtil(context)
validProfile = Profile(profileInjector, JSONObject(validProfileJSON), Constants.MGDL) validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
effectiveProfileSwitch = EffectiveProfileSwitch(
timestamp = dateUtil.now(),
basalBlocks = validProfile.basalBlocks,
isfBlocks = validProfile.isfBlocks,
icBlocks = validProfile.icBlocks,
targetBlocks = validProfile.targetBlocks,
glucoseUnit = EffectiveProfileSwitch.GlucoseUnit.MMOL,
originalProfileName = "",
originalCustomizedName = "",
originalTimeshift = 0,
originalPercentage = 100,
originalDuration = 0,
originalEnd = 0,
insulinConfiguration = InsulinConfiguration("", 0, 0)
)
} }
fun getValidProfileStore(): ProfileStore { fun getValidProfileStore(): ProfileStore {
@ -69,6 +69,6 @@ open class TestBaseWithProfile : TestBase() {
store.put(TESTPROFILENAME, JSONObject(validProfileJSON)) store.put(TESTPROFILENAME, JSONObject(validProfileJSON))
json.put("defaultProfile", TESTPROFILENAME) json.put("defaultProfile", TESTPROFILENAME)
json.put("store", store) json.put("store", store)
return ProfileStore(profileInjector, json) return ProfileStore(profileInjector, json, dateUtil)
} }
} }

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.interfaces.Pump import info.nightscout.androidaps.interfaces.Pump

View file

@ -4,10 +4,8 @@ import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
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
@ -15,20 +13,14 @@ import org.json.JSONArray
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.powermock.api.mockito.PowerMockito import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(Profile::class, IobCobCalculatorPlugin::class)
class QuickWizardTest : TestBase() { class QuickWizardTest : TestBase() {
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var treatmentsPlugin: TreatmentsPlugin
@Mock lateinit var loopPlugin: LoopPlugin @Mock lateinit var loopPlugin: LoopPlugin
private val data1 = "{\"buttonText\":\"Meal\",\"carbs\":36,\"validFrom\":0,\"validTo\":18000," + private val data1 = "{\"buttonText\":\"Meal\",\"carbs\":36,\"validFrom\":0,\"validTo\":18000," +
@ -52,8 +44,7 @@ class QuickWizardTest : TestBase() {
@Before @Before
fun mock() { fun mock() {
PowerMockito.mockStatic(Profile::class.java) PowerMockito.`when`(profileFunction.secondsFromMidnight()).thenReturn(0)
PowerMockito.`when`<Any>(Profile::class.java, "secondsFromMidnight").thenReturn(0)
`when`(sp.getString(R.string.key_quickwizard, "[]")).thenReturn("[]") `when`(sp.getString(R.string.key_quickwizard, "[]")).thenReturn("[]")
quickWizard = QuickWizard(sp, injector) quickWizard = QuickWizard(sp, injector)
} }

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.data.defaultProfile package info.nightscout.androidaps.data.defaultProfile
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
@ -9,18 +10,19 @@ class DefaultProfileTest : TestBaseWithProfile() {
@Test @Test
fun profile() { fun profile() {
var p = DefaultProfile(profileInjector).profile(5.0, 5.1 / 0.3, 0.0, Constants.MMOL) val dp = DefaultProfile(dateUtil).profile(5.0, 5.1 / 0.3, 0.0, GlucoseUnit.MMOL)
assertEquals(0.150, p!!.getBasalTimeFromMidnight(0), 0.001) var p = ProfileSealed.Pure(dp!!)
assertEquals(0.150, p.getBasalTimeFromMidnight(0), 0.001)
assertEquals(15.0, p.getIcTimeFromMidnight(0), 0.001) assertEquals(15.0, p.getIcTimeFromMidnight(0), 0.001)
assertEquals(11.8, p.getIsfTimeFromMidnight(0), 0.001) assertEquals(11.8, p.getIsfTimeFromMidnight(0), 0.001)
p = DefaultProfile(profileInjector).profile(7.0, 10.0 / 0.4, 0.0, Constants.MMOL) p = ProfileSealed.Pure(DefaultProfile(dateUtil).profile(7.0, 10.0 / 0.4, 0.0, GlucoseUnit.MMOL)!!)
assertEquals(0.350, p!!.getBasalTimeFromMidnight(0), 0.001) assertEquals(0.350, p.getBasalTimeFromMidnight(0), 0.001)
assertEquals(15.0, p.getIcTimeFromMidnight(0), 0.001) assertEquals(15.0, p.getIcTimeFromMidnight(0), 0.001)
assertEquals(6.8, p.getIsfTimeFromMidnight(0), 0.001) assertEquals(6.8, p.getIsfTimeFromMidnight(0), 0.001)
p = DefaultProfile(profileInjector).profile(12.0, 25.0 / 0.5, 0.0, Constants.MMOL) p = ProfileSealed.Pure(DefaultProfile(dateUtil).profile(12.0, 25.0 / 0.5, 0.0, GlucoseUnit.MMOL)!!)
assertEquals(0.80, p!!.getBasalTimeFromMidnight(0), 0.001) assertEquals(0.80, p.getBasalTimeFromMidnight(0), 0.001)
assertEquals(10.0, p.getIcTimeFromMidnight(0), 0.001) assertEquals(10.0, p.getIcTimeFromMidnight(0), 0.001)
assertEquals(2.2, p.getIsfTimeFromMidnight(0), 0.001) assertEquals(2.2, p.getIsfTimeFromMidnight(0), 0.001)
} }

View file

@ -14,11 +14,7 @@ import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -162,7 +158,6 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
}.`when`(commandQueue).extendedBolus(ArgumentMatchers.anyDouble(), ArgumentMatchers.anyInt(), ArgumentMatchers.any(Callback::class.java)) }.`when`(commandQueue).extendedBolus(ArgumentMatchers.anyDouble(), ArgumentMatchers.anyInt(), ArgumentMatchers.any(Callback::class.java))
`when`(activePlugin.activePump).thenReturn(virtualPumpPlugin) `when`(activePlugin.activePump).thenReturn(virtualPumpPlugin)
`when`(activePlugin.activeTreatments).thenReturn(treatmentsInterface)
`when`(virtualPumpPlugin.shortStatus(ArgumentMatchers.anyBoolean())).thenReturn("Virtual Pump") `when`(virtualPumpPlugin.shortStatus(ArgumentMatchers.anyBoolean())).thenReturn("Virtual Pump")
`when`(virtualPumpPlugin.isSuspended()).thenReturn(false) `when`(virtualPumpPlugin.isSuspended()).thenReturn(false)
@ -171,11 +166,10 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
`when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(0)) `when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(0))
`when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(0)) `when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(0))
`when`(treatmentsInterface.service).thenReturn(treatmentService)
`when`(activePlugin.activeProfileSource).thenReturn(localProfilePlugin) `when`(activePlugin.activeProfileSource).thenReturn(localProfilePlugin)
`when`(profileFunction.getUnits()).thenReturn(Constants.MGDL) `when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
`when`(otp.name()).thenReturn("User") `when`(otp.name()).thenReturn("User")
`when`(otp.checkOTP(ArgumentMatchers.anyString())).thenReturn(OneTimePasswordValidationResult.OK) `when`(otp.checkOTP(ArgumentMatchers.anyString())).thenReturn(OneTimePasswordValidationResult.OK)

View file

@ -41,7 +41,7 @@ class TreatmentsPluginTest : TestBaseWithProfile() {
} }
} }
@Test fun dumy() {} @Test fun dummy() {}
/* /*
private lateinit var insulinOrefRapidActingPlugin: InsulinOrefRapidActingPlugin private lateinit var insulinOrefRapidActingPlugin: InsulinOrefRapidActingPlugin
private lateinit var sot: TreatmentsPlugin private lateinit var sot: TreatmentsPlugin

View file

@ -2,15 +2,14 @@ package info.nightscout.androidaps.queue
import android.content.Context import android.content.Context
import android.os.PowerManager import android.os.PowerManager
import dagger.Lazy
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
@ -27,15 +26,18 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
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.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Single
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyLong
import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner import org.powermock.modules.junit4.PowerMockRunner
import java.util.* import java.util.*
@ -48,7 +50,6 @@ import java.util.*
class CommandQueueTest : TestBaseWithProfile() { class CommandQueueTest : TestBaseWithProfile() {
@Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var constraintChecker: ConstraintChecker
@Mock lateinit var lazyActivePlugin: Lazy<ActivePlugin>
@Mock lateinit var activePlugin: ActivePlugin @Mock lateinit var activePlugin: ActivePlugin
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var loggerUtils: LoggerUtils @Mock lateinit var loggerUtils: LoggerUtils
@ -63,7 +64,7 @@ class CommandQueueTest : TestBaseWithProfile() {
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
constraintChecker: ConstraintChecker, constraintChecker: ConstraintChecker,
profileFunction: ProfileFunction, profileFunction: ProfileFunction,
activePlugin: Lazy<ActivePlugin>, activePlugin: ActivePlugin,
context: Context, context: Context,
sp: SP, sp: SP,
buildHelper: BuildHelper, buildHelper: BuildHelper,
@ -106,15 +107,14 @@ class CommandQueueTest : TestBaseWithProfile() {
@Before @Before
fun prepare() { fun prepare() {
commandQueue = CommandQueueMocked(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, lazyActivePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy) commandQueue = CommandQueueMocked(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy)
testPumpPlugin = TestPumpPlugin(injector) testPumpPlugin = TestPumpPlugin(injector)
testPumpPlugin.pumpDescription.basalMinimumRate = 0.1 testPumpPlugin.pumpDescription.basalMinimumRate = 0.1
`when`(context.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager) `when`(context.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager)
`when`(lazyActivePlugin.get()).thenReturn(activePlugin)
`when`(activePlugin.activePump).thenReturn(testPumpPlugin) `when`(activePlugin.activePump).thenReturn(testPumpPlugin)
`when`(activePlugin.activeTreatments).thenReturn(treatmentsInterface) `when`(repository.getEffectiveProfileSwitchActiveAt(anyLong())).thenReturn(Single.just(ValueWrapper.Existing(effectiveProfileSwitch)))
`when`(repository.getLastBolusRecord()).thenReturn( `when`(repository.getLastBolusRecord()).thenReturn(
Bolus( Bolus(
timestamp = Calendar.getInstance().also { it.set(2000, 0, 1) }.timeInMillis, timestamp = Calendar.getInstance().also { it.set(2000, 0, 1) }.timeInMillis,
@ -138,7 +138,7 @@ class CommandQueueTest : TestBaseWithProfile() {
@Test @Test
fun commandIsPickedUp() { fun commandIsPickedUp() {
val commandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, lazyActivePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy) val commandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy)
// start with empty queue // start with empty queue
Assert.assertEquals(0, commandQueue.size()) Assert.assertEquals(0, commandQueue.size())
@ -365,7 +365,7 @@ class CommandQueueTest : TestBaseWithProfile() {
// when // when
testPumpPlugin.isProfileSet = true testPumpPlugin.isProfileSet = true
commandQueue.setProfile(validProfile, object : Callback() { commandQueue.setProfile(validProfile, false, object : Callback() {
override fun run() { override fun run() {
Assert.assertTrue(result.success) Assert.assertTrue(result.success)
Assert.assertFalse(result.enacted) Assert.assertFalse(result.enacted)
@ -377,7 +377,7 @@ class CommandQueueTest : TestBaseWithProfile() {
Assert.assertEquals(0, commandQueue.size()) Assert.assertEquals(0, commandQueue.size())
// different should be added // different should be added
testPumpPlugin.isProfileSet = false testPumpPlugin.isProfileSet = false
commandQueue.setProfile(validProfile, object : Callback() { commandQueue.setProfile(validProfile, false, object : Callback() {
override fun run() { override fun run() {
Assert.assertTrue(result.success) Assert.assertTrue(result.success)
Assert.assertTrue(result.enacted) Assert.assertTrue(result.enacted)
@ -385,7 +385,7 @@ class CommandQueueTest : TestBaseWithProfile() {
}) })
Assert.assertEquals(1, commandQueue.size()) Assert.assertEquals(1, commandQueue.size())
// next should be ignored // next should be ignored
commandQueue.setProfile(validProfile, object : Callback() { commandQueue.setProfile(validProfile, false, object : Callback() {
override fun run() { override fun run() {
Assert.assertTrue(result.success) Assert.assertTrue(result.success)
} }

View file

@ -2,10 +2,8 @@ package info.nightscout.androidaps.queue
import android.content.Context import android.content.Context
import android.os.PowerManager import android.os.PowerManager
import dagger.Lazy
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.TestPumpPlugin import info.nightscout.androidaps.TestPumpPlugin
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
@ -22,6 +20,7 @@ import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
@ -39,7 +38,6 @@ import org.powermock.modules.junit4.PowerMockRunner
class QueueThreadTest : TestBaseWithProfile() { class QueueThreadTest : TestBaseWithProfile() {
@Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var constraintChecker: ConstraintChecker
@Mock lateinit var lazyActivePlugin: Lazy<ActivePlugin>
@Mock lateinit var activePlugin: ActivePlugin @Mock lateinit var activePlugin: ActivePlugin
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var loggerUtils: LoggerUtils @Mock lateinit var loggerUtils: LoggerUtils
@ -65,16 +63,13 @@ class QueueThreadTest : TestBaseWithProfile() {
@Before @Before
fun prepare() { fun prepare() {
pumpPlugin = TestPumpPlugin(injector) pumpPlugin = TestPumpPlugin(injector)
commandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, lazyActivePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy) commandQueue = CommandQueue(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp, BuildHelper(ConfigImpl(), loggerUtils), dateUtil, repository, fabricPrivacy)
val pumpDescription = PumpDescription() val pumpDescription = PumpDescription()
pumpDescription.basalMinimumRate = 0.1 pumpDescription.basalMinimumRate = 0.1
Mockito.`when`(context.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager) Mockito.`when`(context.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager)
Mockito.`when`(lazyActivePlugin.get()).thenReturn(activePlugin)
Mockito.`when`(activePlugin.activePump).thenReturn(pumpPlugin) Mockito.`when`(activePlugin.activePump).thenReturn(pumpPlugin)
Mockito.`when`(activePlugin.activeTreatments).thenReturn(treatmentsInterface)
// Mockito.`when`(treatmentsInterface.lastBolusTime).thenReturn(Calendar.getInstance().also { it.set(2000, 0, 1) }.timeInMillis)
Mockito.`when`(profileFunction.getProfile()).thenReturn(validProfile) Mockito.`when`(profileFunction.getProfile()).thenReturn(validProfile)
val bolusConstraint = Constraint(0.0) val bolusConstraint = Constraint(0.0)

View file

@ -3,11 +3,10 @@ package info.nightscout.androidaps.utils.wizard
import android.content.Context import android.content.Context
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -66,12 +65,12 @@ class BolusWizardTest : TestBase() {
@Suppress("SameParameterValue") @Suppress("SameParameterValue")
private fun setupProfile(targetLow: Double, targetHigh: Double, insulinSensitivityFactor: Double, insulinToCarbRatio: Double): Profile { private fun setupProfile(targetLow: Double, targetHigh: Double, insulinSensitivityFactor: Double, insulinToCarbRatio: Double): Profile {
val profile = Mockito.mock(Profile::class.java) val profile = Mockito.mock(Profile::class.java)
`when`(profile.targetLowMgdl).thenReturn(targetLow) `when`(profile.getTargetLowMgdl()).thenReturn(targetLow)
`when`(profile.targetHighMgdl).thenReturn(targetHigh) `when`(profile.getTargetLowMgdl()).thenReturn(targetHigh)
`when`(profile.isfMgdl).thenReturn(insulinSensitivityFactor) `when`(profile.getIsfMgdl()).thenReturn(insulinSensitivityFactor)
`when`(profile.ic).thenReturn(insulinToCarbRatio) `when`(profile.getIc()).thenReturn(insulinToCarbRatio)
`when`(profileFunction.getUnits()).thenReturn(Constants.MGDL) `when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
`when`(activePlugin.activeTreatments).thenReturn(treatmentsPlugin) `when`(activePlugin.activeTreatments).thenReturn(treatmentsPlugin)
`when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(System.currentTimeMillis())) `when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(System.currentTimeMillis()))
`when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(System.currentTimeMillis())) `when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(System.currentTimeMillis()))

View file

@ -62,7 +62,7 @@ class ActionProfileSwitch(injector: HasAndroidInjector) : Action(injector) {
uel.log(UserEntry.Action.PROFILE_SWITCH, Sources.Automation, title, uel.log(UserEntry.Action.PROFILE_SWITCH, Sources.Automation, title,
ValueWithUnit.SimpleString(inputProfileName.value), ValueWithUnit.SimpleString(inputProfileName.value),
ValueWithUnit.Percent(100)) ValueWithUnit.Percent(100))
activePlugin.activeTreatments.doProfileSwitch(profileStore, inputProfileName.value, 0, 100, 0, dateUtil.now()) profileFunction.createProfileSwitch(profileStore, inputProfileName.value, 0, 100, 0, dateUtil.now())
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
} }

View file

@ -8,7 +8,7 @@ import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
@ -23,8 +23,9 @@ import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
class ActionProfileSwitchPercent(injector: HasAndroidInjector) : Action(injector) { class ActionProfileSwitchPercent(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
var pct = InputPercent() var pct = InputPercent()
@ -45,7 +46,7 @@ class ActionProfileSwitchPercent(injector: HasAndroidInjector) : Action(injector
uel.log(UserEntry.Action.PROFILE_SWITCH, Sources.Automation, title + ": " + resourceHelper.gs(R.string.startprofile, pct.value.toInt(), duration.value), uel.log(UserEntry.Action.PROFILE_SWITCH, Sources.Automation, title + ": " + resourceHelper.gs(R.string.startprofile, pct.value.toInt(), duration.value),
ValueWithUnit.Percent(pct.value.toInt()), ValueWithUnit.Percent(pct.value.toInt()),
ValueWithUnit.Minute(duration.value)) ValueWithUnit.Minute(duration.value))
activePlugin.activeTreatments.doProfileSwitch(duration.value, pct.value.toInt(), 0) profileFunction.createProfileSwitch(duration.value, pct.value.toInt(), 0)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
} }

View file

@ -5,7 +5,7 @@ import androidx.annotation.DrawableRes
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
@ -28,6 +28,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
import info.nightscout.androidaps.extensions.friendlyDescription import info.nightscout.androidaps.extensions.friendlyDescription
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -75,7 +76,7 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
} }
override fun generateDialog(root: LinearLayout) { override fun generateDialog(root: LinearLayout) {
val unitResId = if (value.units == Constants.MGDL) R.string.mgdl else R.string.mmol val unitResId = if (value.units == GlucoseUnit.MGDL) R.string.mgdl else R.string.mmol
LayoutBuilder() LayoutBuilder()
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.careportal_temporarytarget) + "\n[" + resourceHelper.gs(unitResId) + "]", "", value)) .add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.careportal_temporarytarget) + "\n[" + resourceHelper.gs(unitResId) + "]", "", value))
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.duration_min_label), "", duration)) .add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.duration_min_label), "", duration))
@ -89,7 +90,7 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
override fun toJSON(): String { override fun toJSON(): String {
val data = JSONObject() val data = JSONObject()
.put("value", value.value) .put("value", value.value)
.put("units", value.units) .put("units", value.units.asText)
.put("durationInMinutes", duration.getMinutes()) .put("durationInMinutes", duration.getMinutes())
return JSONObject() return JSONObject()
.put("type", this.javaClass.name) .put("type", this.javaClass.name)
@ -99,7 +100,7 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
override fun fromJSON(data: String): Action { override fun fromJSON(data: String): Action {
val o = JSONObject(data) val o = JSONObject(data)
value.units = JsonHelper.safeGetString(o, "units", Constants.MGDL) value.units = GlucoseUnit.fromText(JsonHelper.safeGetString(o, "units", Constants.MGDL))
value.value = safeGetDouble(o, "value") value.value = safeGetDouble(o, "value")
duration.setMinutes(JsonHelper.safeGetInt(o, "durationInMinutes")) duration.setMinutes(JsonHelper.safeGetInt(o, "durationInMinutes"))
return this return this
@ -114,7 +115,7 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
) )
override fun isValid(): Boolean = override fun isValid(): Boolean =
if (value.units == Constants.MMOL) { // mmol if (value.units == GlucoseUnit.MMOL) { // mmol
value.value >= Constants.MIN_TT_MMOL && value.value >= Constants.MIN_TT_MMOL &&
value.value <= Constants.MAX_TT_MMOL && value.value <= Constants.MAX_TT_MMOL &&
duration.value > 0 duration.value > 0

View file

@ -1,22 +1,22 @@
package info.nightscout.androidaps.plugins.general.automation.elements package info.nightscout.androidaps.plugins.general.automation.elements
import android.widget.LinearLayout import android.widget.LinearLayout
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.automation.R import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.ui.NumberPicker import info.nightscout.androidaps.utils.ui.NumberPicker
import java.text.DecimalFormat import java.text.DecimalFormat
class InputBg(profileFunction: ProfileFunction) : Element() { class InputBg(profileFunction: ProfileFunction) : Element() {
var units = Constants.MGDL var units = GlucoseUnit.MGDL
var value = 0.0 var value = 0.0
var minValue = 0.0 var minValue = 0.0
private var maxValue = 0.0 private var maxValue = 0.0
private var step = 0.0 private var step = 0.0
private var decimalFormat: DecimalFormat? = null private var decimalFormat: DecimalFormat? = null
constructor(profileFunction: ProfileFunction, value: Double, units: String) : this(profileFunction) { constructor(profileFunction: ProfileFunction, value: Double, units: GlucoseUnit) : this(profileFunction) {
setUnits(units) setUnits(units)
this.value = value this.value = value
} }
@ -37,8 +37,8 @@ class InputBg(profileFunction: ProfileFunction) : Element() {
return this return this
} }
fun setUnits(units: String): InputBg { fun setUnits(units: GlucoseUnit): InputBg {
if (units == Constants.MMOL) { if (units == GlucoseUnit.MMOL) {
minValue = MMOL_MIN minValue = MMOL_MIN
maxValue = MMOL_MAX maxValue = MMOL_MAX
step = 0.1 step = 0.1

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