- changed code to use dagger

This commit is contained in:
Andy Rozman 2020-04-24 11:00:31 +01:00
parent 37590338ff
commit a3b0c8ce3b
1785 changed files with 55330 additions and 60097 deletions

View file

@ -7,6 +7,10 @@
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" /> <option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
</JetCodeStyleSettings> </JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="METHOD_ANNOTATION_WRAP" value="0" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
</codeStyleSettings>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
@ -126,6 +130,8 @@
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> <option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" /> <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" /> <option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
<option name="METHOD_ANNOTATION_WRAP" value="5" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions> </indentOptions>

View file

@ -13,6 +13,7 @@ buildscript {
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
apply plugin: 'io.fabric' apply plugin: 'io.fabric'
apply plugin: 'jacoco-android' apply plugin: 'jacoco-android'
@ -24,10 +25,12 @@ jacoco {
} }
ext { ext {
supportLibraryVersion = "28.0.0"
ormLiteVersion = "4.46" ormLiteVersion = "4.46"
powermockVersion = "1.7.3" powermockVersion = "1.7.3"
dexmakerVersion = "1.2" dexmakerVersion = "1.2"
retrofit2Version = '2.8.1'
okhttp3Version = '4.5.0'
coroutinesVersion = '1.3.5'
} }
@ -79,6 +82,23 @@ def isMaster = { ->
return !version.contains('-') return !version.contains('-')
} }
def gitAvailable = { ->
StringBuilder stringBuilder = new StringBuilder()
try {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', '--version'
standardOutput = stdout
}
String commitObject = stdout.toString().trim()
stringBuilder.append(commitObject)
} catch (ignored) {
return false // NoGitSystemAvailable
}
return !stringBuilder.toString().isEmpty()
}
def allCommited = { -> def allCommited = { ->
StringBuilder stringBuilder = new StringBuilder() StringBuilder stringBuilder = new StringBuilder()
try { try {
@ -118,9 +138,9 @@ android {
// if you change minSdkVersion to less than 11, you need to change executeTask for wear // if you change minSdkVersion to less than 11, you need to change executeTask for wear
// OMNIPOD: Keep track of what commit from the main repository we're on, these fields aren't actually used anywhere // OMNIPOD: Keep track of what commit from the main repository we're on, these fields aren't actually used anywhere
buildConfigField "String", "DEV_VERSION", '"2.6.1-dev"' buildConfigField "String", "DEV_VERSION", '"2.6.5-dev"'
buildConfigField "String", "DEV_VERSION_COMMIT", '"447c05f05f3bc707549cd776caf7221bfcc47d0a"' buildConfigField "String", "DEV_VERSION_COMMIT", '"1481755bc8e63a741f05507579846340dbd49cd6"'
buildConfigField "String", "DEV_VERSION_COMMIT_DATE", '"1.4.2020"' // 1st April buildConfigField "String", "DEV_VERSION_COMMIT_DATE", '"21.4.2020"' // 21st April
ndk { ndk {
moduleName "BleCommandUtil" moduleName "BleCommandUtil"
@ -130,12 +150,6 @@ android {
jvmTarget = '1.8' jvmTarget = '1.8'
} }
lintOptions { lintOptions {
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
// has been upgraded (requiring significant code changes), which currently fails release
// build with a deprecation warning
// abortOnError false
// (disabled entirely to avoid reports on the error, which would still be displayed
// and it's easy to overlook that it's ignored)
checkReleaseBuilds false checkReleaseBuilds false
disable 'MissingTranslation' disable 'MissingTranslation'
disable 'ExtraTranslation' disable 'ExtraTranslation'
@ -213,6 +227,10 @@ android {
} }
useLibrary "org.apache.http.legacy" useLibrary "org.apache.http.legacy"
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
} }
allprojects { allprojects {
@ -230,9 +248,10 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.google.android.gms:play-services-wearable:17.0.0' implementation 'com.google.android.gms:play-services-wearable:17.0.0'
implementation 'com.google.firebase:firebase-core:17.2.1' implementation "com.google.android.gms:play-services-location:17.0.0"
implementation 'com.google.firebase:firebase-auth:19.2.0' implementation 'com.google.firebase:firebase-core:17.3.0'
implementation 'com.google.firebase:firebase-database:19.2.0' implementation 'com.google.firebase:firebase-auth:19.3.0'
implementation 'com.google.firebase:firebase-database:19.2.1'
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') { implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
transitive = true; transitive = true;
} }
@ -241,10 +260,12 @@ dependencies {
implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.biometric:biometric:1.0.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation "androidx.preference:preference-ktx:1.1.0"
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.wdullaer:materialdatetimepicker:4.2.3' implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
implementation "io.reactivex.rxjava2:rxandroid:2.1.1" implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
@ -255,15 +276,13 @@ dependencies {
exclude group: "com.google.android", module: "android" exclude group: "com.google.android", module: "android"
} }
implementation "org.apache.commons:commons-lang3:3.9" implementation "org.apache.commons:commons-lang3:3.9"
implementation "org.slf4j:slf4j-api:1.7.29" implementation 'org.slf4j:slf4j-api:1.7.30'
// Graphview cannot be upgraded // Graphview cannot be upgraded
implementation "com.jjoe64:graphview:4.0.1" implementation "com.jjoe64:graphview:4.0.1"
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2" implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
implementation(name: "com.atech-software.android.library.wizardpager-1.1.1", ext: "aar")
implementation 'com.madgag.spongycastle:core:1.58.0.0' implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation(name: "com.atech-software.android.library.wizardpager-1.1.1", ext: "aar")
implementation("com.google.android:flexbox:0.3.0") { implementation("com.google.android:flexbox:0.3.0") {
exclude group: "com.android.support" exclude group: "com.android.support"
@ -284,6 +303,9 @@ dependencies {
implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0' implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0'
implementation 'com.github.kenglxn.QRGen:android:2.6.0'
implementation 'com.eatthepath:java-otp:0.2.0'
testImplementation "junit:junit:4.12" testImplementation "junit:junit:4.12"
testImplementation "org.json:json:20190722" testImplementation "org.json:json:20190722"
testImplementation "org.mockito:mockito-core:2.8.47" testImplementation "org.mockito:mockito-core:2.8.47"
@ -292,7 +314,7 @@ dependencies {
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
testImplementation "joda-time:joda-time:2.10.5" testImplementation "joda-time:joda-time:2.10.5"
testImplementation("com.google.truth:truth:0.39") { testImplementation('com.google.truth:truth:1.0.1') {
exclude group: "com.google.guava", module: "guava" exclude group: "com.google.guava", module: "guava"
exclude group: "com.google.code.findbugs", module: "jsr305" exclude group: "com.google.code.findbugs", module: "jsr305"
} }
@ -306,14 +328,15 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
// new for tidepool // new for tidepool
implementation 'com.squareup.okhttp3:okhttp:4.2.2' implementation "com.squareup.okhttp3:okhttp:$okhttp3Version"
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2' implementation "com.squareup.okhttp3:logging-interceptor:$okhttp3Version"
implementation "com.squareup.retrofit2:retrofit:2.6.2" implementation "com.squareup.retrofit2:retrofit:$retrofit2Version"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.6.2" implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version"
implementation "com.squareup.retrofit2:converter-gson:2.6.2" implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
// Phone checker // Phone checker
implementation 'com.scottyab:rootbeer-lib:0.0.7' implementation 'com.scottyab:rootbeer-lib:0.0.7'
@ -322,6 +345,19 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.3.0-alpha03' androidTestImplementation 'androidx.test:rules:1.3.0-alpha03'
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2' androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
/* Dagger2 - We are going to use dagger.android which includes
* support for Activity and fragment injection so we need to include
* the following dependencies */
implementation 'com.google.dagger:dagger-android:2.25.2'
implementation 'com.google.dagger:dagger-android-support:2.25.2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.25.2'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.25.2'
kapt 'com.google.dagger:dagger-android-processor:2.25.2'
/* Dagger2 - default dependency */
kapt 'com.google.dagger:dagger-compiler:2.25.2'
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
} }
@ -385,9 +421,13 @@ preBuild.dependsOn copyLibs
printf('--------------\n') printf('--------------\n')
printf('isMaster: %s\n', isMaster().toString()) printf('isMaster: %s\n', isMaster().toString())
printf('gitAvailable: %s\n', gitAvailable().toString())
printf('allCommited: %s\n', allCommited().toString()) printf('allCommited: %s\n', allCommited().toString())
printf('--------------\n') printf('--------------\n')
if (isMaster() && !gitAvailable()) {
throw new GradleException('GIT system is not available. On Windows try to run Android Studio as an Administrator. Check if GIT is installed and Studio have permissions to use it')
}
if (isMaster() && !allCommited()) { if (isMaster() && !allCommited()) {
throw new GradleException('There are uncommitted changes or git system is not available. Clone sources again as described in wiki and do not allow gradle update') throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update')
} }

View file

@ -8,11 +8,11 @@ import androidx.test.rule.GrantPermissionRule
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.PumpInterface
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin
@ -20,9 +20,10 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.source.RandomBgPlugin import info.nightscout.androidaps.plugins.source.RandomBgPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.utils.isRunningTest import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject import org.json.JSONObject
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
@ -30,21 +31,33 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import javax.inject.Inject
@LargeTest @LargeTest
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class RealPumpTest { class RealPumpTest {
private val log = LoggerFactory.getLogger(L.CORE)
companion object { companion object {
val pump: PumpInterface = DanaRv2Plugin.getPlugin()
const val R_PASSWORD = 1234 const val R_PASSWORD = 1234
const val R_SERIAL = "PBB00013LR_P" const val R_SERIAL = "PBB00013LR_P"
} }
private val validProfile = "{\"dia\":\"6\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"10\"},{\"time\":\"2:00\",\"value\":\"11\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" private val validProfile = "{\"dia\":\"6\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"10\"},{\"time\":\"2:00\",\"value\":\"11\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
@Inject lateinit var pump : DanaRv2Plugin
@Inject lateinit var randomBgPlugin :RandomBgPlugin
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var insulinOrefUltraRapidActingPlugin: InsulinOrefUltraRapidActingPlugin
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
@Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var actionsPlugin: ActionsPlugin
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
@Inject lateinit var objectivesPlugin: ObjectivesPlugin
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var sp: SP
@Rule @Rule
@JvmField @JvmField
var mActivityTestRule = ActivityTestRule(MainActivity::class.java) var mActivityTestRule = ActivityTestRule(MainActivity::class.java)
@ -60,42 +73,43 @@ class RealPumpTest {
@Before @Before
fun clear() { fun clear() {
SP.clear() sp.clear()
SP.putBoolean(R.string.key_setupwizard_processed, true) sp.putBoolean(R.string.key_setupwizard_processed, true)
SP.putString(R.string.key_aps_mode, "closed") sp.putString(R.string.key_aps_mode, "closed")
MainApp.getDbHelper().resetDatabases() MainApp.getDbHelper().resetDatabases()
MainApp.devBranch = false MainApp.devBranch = false
} }
private fun preparePlugins() { private fun preparePlugins() {
// Source // Source
RandomBgPlugin.performPluginSwitch(true, PluginType.BGSOURCE) configBuilderPlugin.performPluginSwitch(randomBgPlugin,true, PluginType.BGSOURCE)
// Profile // Profile
LocalProfilePlugin.performPluginSwitch(true, PluginType.PROFILE) configBuilderPlugin.performPluginSwitch(localProfilePlugin, true, PluginType.PROFILE)
val profile = Profile(JSONObject(validProfile), Constants.MGDL) val profile = Profile(JSONObject(validProfile), Constants.MGDL)
Assert.assertTrue(profile.isValid("Test")) Assert.assertTrue(profile.isValid("Test"))
LocalProfilePlugin.profiles.clear() localProfilePlugin.profiles.clear()
LocalProfilePlugin.numOfProfiles = 0 localProfilePlugin.numOfProfiles = 0
val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(profile, "TestProfile") val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(localProfilePlugin.rawProfile, profile, "TestProfile")
LocalProfilePlugin.addProfile(singleProfile) localProfilePlugin.addProfile(singleProfile)
ProfileFunctions.doProfileSwitch(LocalProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, DateUtil.now()) val profileSwitch = profileFunction.prepareProfileSwitch(localProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, DateUtil.now())
treatmentsPlugin.addToHistoryProfileSwitch(profileSwitch)
// Insulin // Insulin
InsulinOrefUltraRapidActingPlugin.getPlugin().performPluginSwitch(true, PluginType.INSULIN) configBuilderPlugin.performPluginSwitch(insulinOrefUltraRapidActingPlugin, true, PluginType.INSULIN)
// Pump // Pump
SP.putInt(R.string.key_danar_password, R_PASSWORD) sp.putInt(R.string.key_danar_password, R_PASSWORD)
SP.putString(R.string.key_danar_bt_name, R_SERIAL) sp.putString(R.string.key_danar_bt_name, R_SERIAL)
(pump as PluginBase).performPluginSwitch(true, PluginType.PUMP) configBuilderPlugin.performPluginSwitch((pump as PluginBase), true, PluginType.PUMP)
// Sensitivity // Sensitivity
SensitivityOref1Plugin.getPlugin().performPluginSwitch(true, PluginType.SENSITIVITY) configBuilderPlugin.performPluginSwitch(sensitivityOref1Plugin, true, PluginType.SENSITIVITY)
// APS // APS
OpenAPSSMBPlugin.getPlugin().performPluginSwitch(true, PluginType.APS) configBuilderPlugin.performPluginSwitch(openAPSSMBPlugin, true, PluginType.APS)
LoopPlugin.getPlugin().performPluginSwitch(true, PluginType.LOOP) configBuilderPlugin.performPluginSwitch(loopPlugin, true, PluginType.LOOP)
// Enable common // Enable common
ActionsPlugin.performPluginSwitch(true, PluginType.GENERAL) configBuilderPlugin.performPluginSwitch(actionsPlugin, true, PluginType.GENERAL)
// Disable unneeded // Disable unneeded
MainApp.getPluginsList().remove(ObjectivesPlugin) MainApp.getPluginsList().remove(objectivesPlugin)
} }
@Test @Test
@ -104,12 +118,12 @@ class RealPumpTest {
preparePlugins() preparePlugins()
while (!pump.isInitialized) { while (!pump.isInitialized) {
log.debug("Waiting for initialization") //log.debug("Waiting for initialization")
SystemClock.sleep(1000) SystemClock.sleep(1000)
} }
while (true) { while (true) {
log.debug("Tick") //log.debug("Tick")
SystemClock.sleep(1000) SystemClock.sleep(1000)
} }
} }

View file

@ -29,7 +29,7 @@ import info.nightscout.androidaps.plugins.source.RandomBgPlugin
import info.nightscout.androidaps.setupwizard.SetupWizardActivity import info.nightscout.androidaps.setupwizard.SetupWizardActivity
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.isRunningTest import info.nightscout.androidaps.utils.extensions.isRunningTest
import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.Description import org.hamcrest.Description
import org.hamcrest.Matcher import org.hamcrest.Matcher

View file

@ -38,7 +38,14 @@
android:roundIcon="${appIconRound}" android:roundIcon="${appIconRound}"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Launcher" android:theme="@style/AppTheme.Launcher"
android:fullBackupContent="true"> android:fullBackupOnly="false"
android:backupAgent=".utils.SPBackupAgent"
android:restoreAnyVersion="true">
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI3JiApyMrbP2QFzZ2fYfCPsgjkRp53Dm2S1-zPQ" />
<meta-data <meta-data
android:name="com.google.android.gms.car.application" android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" /> android:resource="@xml/automotive_app_desc" />
@ -76,7 +83,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" /> <activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" />
<activity android:name=".activities.HistoryBrowseActivity" /> <activity android:name=".historyBrowser.HistoryBrowseActivity" />
<activity android:name=".activities.SurveyActivity" /> <activity android:name=".activities.SurveyActivity" />
<activity android:name=".activities.StatsActivity" /> <activity android:name=".activities.StatsActivity" />
@ -267,6 +274,13 @@
android:label="@string/pairing_information" android:label="@string/pairing_information"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<activity android:name=".activities.RequestDexcomPermissionActivity" /> <activity android:name=".activities.RequestDexcomPermissionActivity" />
<activity android:name=".plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- Medtronic service and activities --> <!-- Medtronic service and activities -->
<service <service

View file

@ -1,316 +0,0 @@
/*
Determine Basal
Released under MIT license. See the accompanying LICENSE.txt file for
full terms and conditions
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, offline, meal_data, setTempBasal) {
var rT = { //short for requestedTemp
};
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
rT.error ='Error: could not get current basal rate';
return rT;
}
var bg = glucose_status.glucose;
if (bg < 38) { //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose
rT.error = "CGM is calibrating or in ??? state";
return rT;
}
var max_iob = profile.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver
// if target_bg is set, great. otherwise, if min and max are set, then set target to their average
var target_bg;
if (typeof profile.target_bg !== 'undefined') {
target_bg = profile.target_bg;
} else {
if (typeof profile.min_bg !== 'undefined' && typeof profile.max_bg !== 'undefined') {
target_bg = (profile.min_bg + profile.max_bg) / 2;
} else {
rT.error ='Error: could not determine target_bg';
return rT;
}
}
if (typeof iob_data === 'undefined' ) {
rT.error ='Error: iob_data undefined';
return rT;
}
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' || typeof iob_data.activity === 'undefined') {
rT.error ='Error: iob_data missing some property';
return rT;
}
var tick;
if (glucose_status.delta >= 0) {
tick = "+" + glucose_status.delta;
} else {
tick = glucose_status.delta;
}
var minDelta = Math.min(glucose_status.delta, glucose_status.avgdelta);
//var maxDelta = Math.max(glucose_status.delta, glucose_status.avgdelta);
//calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
var bgi = Math.round(( -iob_data.activity * profile.sens * 5 )*100)/100;
// project positive deviations for 15 minutes
var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) );
// project negative deviations for 30 minutes
if (deviation < 0) {
deviation = Math.round( 30 / 5 * ( glucose_status.avgdelta - bgi ) );
}
//console.log("Avg.Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1) + " 15m activity projection: " + deviation.toFixed(0));
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
var naive_eventualBG = Math.round( bg - (iob_data.iob * profile.sens) );
// and adjust it for the deviation above
var eventualBG = naive_eventualBG + deviation;
// calculate what portion of that is due to bolussnooze
var bolusContrib = iob_data.bolussnooze * profile.sens;
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
// adjust that for deviation like we did eventualBG
var snoozeBG = naive_snoozeBG + deviation;
//console.log("BG: " + bg +"(" + tick + ","+glucose_status.avgdelta.toFixed(1)+")"+ " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + "), BGI: " + bgi);
var expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
//console.log("expectedDelta: " + expectedDelta);
if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) {
rT.error ='Error: could not calculate eventualBG';
return rT;
}
// min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90
var threshold = profile.min_bg - 0.5*(profile.min_bg-50);
rT = {
'temp': 'absolute'
, 'bg': bg
, 'tick': tick
, 'eventualBG': eventualBG
, 'snoozeBG': snoozeBG
};
var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
// allow meal assist to run when carbs are just barely covered
if (minDelta > Math.max(3, bgi) && ( (meal_data.carbs > 0 && (1.1 * meal_data.carbs/profile.carb_ratio > meal_data.boluses + basaliob)) || ( deviation > 25 && minDelta > 7 ) ) ) {
// ignore all covered IOB, and just set eventualBG to the current bg
eventualBG = Math.max(bg,eventualBG) + deviation;
rT.eventualBG = eventualBG;
profile.min_bg = 80;
target_bg = (profile.min_bg + profile.max_bg) / 2;
expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
rT.mealAssist = "On: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
} else {
rT.mealAssist = "Off: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
}
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
rT.reason = "BG " + bg + "<" + threshold;
if ((glucose_status.delta <= 0 && glucose_status.avgdelta <= 0) || (glucose_status.delta < expectedDelta && glucose_status.avgdelta < expectedDelta)) {
// BG is still falling / rising slower than predicted
return setTempBasal(0, 30, profile, rT, offline);
}
if (glucose_status.delta > glucose_status.avgdelta) {
rT.reason += ", delta " + glucose_status.delta + ">0";
} else {
rT.reason += ", avg delta " + glucose_status.avgdelta.toFixed(2) + ">0";
}
if (currenttemp.rate > profile.current_basal) { // if a high-temp is running
rT.reason += ", cancel high temp";
return setTempBasal(0, 0, profile, rT, offline); // cancel high temp
} else if (currenttemp.duration && eventualBG > profile.max_bg) { // if low-temped and predicted to go high from negative IOB
rT.reason += ", cancel low temp";
return setTempBasal(0, 0, profile, rT, offline); // cancel low temp
}
rT.reason += "; no high-temp to cancel";
return rT;
}
if (eventualBG < profile.min_bg) { // if eventual BG is below target:
if (rT.mealAssist.indexOf("On") == 0) {
rT.reason = "Meal assist: " + meal_data.carbs + "g, " + meal_data.boluses + "U";
} else {
rT.reason = "Eventual BG " + eventualBG + "<" + profile.min_bg;
// if 5m or 15m avg BG is rising faster than expected delta
if (minDelta > expectedDelta && minDelta > 0) {
if (glucose_status.delta > glucose_status.avgdelta) {
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
} else {
rT.reason += ", but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
}
if (currenttemp.duration > 0) { // if there is currently any temp basal running
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
} else {
rT.reason = rT.reason += "; no temp to cancel";
return rT;
}
}
}
if (eventualBG < profile.min_bg) {
// if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed)
if (snoozeBG > profile.min_bg) { // if adding back in the bolus contribution BG would be above min
// if BG is falling and high-temped, or rising and low-temped, cancel
// compare against zero here, not BGI, because BGI will be highly negative from boluses and no carbs
if (glucose_status.delta < 0 && currenttemp.duration > 0 && currenttemp.rate > profile.current_basal) {
rT.reason += tick + ", and temp " + currenttemp.rate + " > basal " + profile.current_basal;
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
} else if (glucose_status.delta > 0 && currenttemp.duration > 0 && currenttemp.rate < profile.current_basal) {
rT.reason += tick + ", and temp " + currenttemp.rate + " < basal " + profile.current_basal;
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
}
rT.reason += ", bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
return rT;
} else {
// calculate 30m low-temp required to get projected BG up to target
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
// multiply by 2 to low-temp faster for increased hypo safety
var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / profile.sens);
if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative
rT.reason += ", Snooze BG " + snoozeBG;
var newinsulinReq = Math.round(( insulinReq * (minDelta / expectedDelta) ) * 100)/100;
//console.log("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// rate required to deliver insulinReq less insulin over 30m:
var rate = profile.current_basal + (2 * insulinReq);
rate = Math.round( rate * 1000 ) / 1000;
// if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
if (insulinScheduled < insulinReq - 0.2) { // if current temp would deliver >0.2U less than the required insulin, raise the rate
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-0.2U";
return setTempBasal(rate, 30, profile, rT, offline);
}
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate > currenttemp.rate - 0.1)) {
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
return rT;
} else {
rT.reason += ", setting " + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline);
}
}
}
}
// if eventual BG is above min but BG is falling faster than expected Delta
if (minDelta < expectedDelta) {
if (glucose_status.delta < glucose_status.avgdelta) {
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
} else {
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " < Exp. Delta " + expectedDelta;
}
if (currenttemp.duration > 0) { // if there is currently any temp basal running
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
} else {
rT.reason = rT.reason += "; no temp to cancel";
return rT;
}
}
if (eventualBG < profile.max_bg) {
rT.reason = eventualBG + " is in range. No temp required";
if (currenttemp.duration > 0) { // if there is currently any temp basal running
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
}
if (offline == 'Offline') {
// if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
if ((!currenttemp.duration || (currenttemp.rate == profile.current_basal)) && !rT.duration) {
rT.reason = rT.reason + "; setting current basal of " + profile.current_basal + " as temp";
return setTempBasal(profile.current_basal, 30, profile, rT, offline);
}
}
return rT;
}
if (snoozeBG < profile.max_bg) {
rT.reason = snoozeBG + " < " + profile.max_bg;
if (currenttemp.duration > 0) { // if there is currently any temp basal running
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
} else {
rT.reason = rT.reason += "; no temp to cancel";
return rT;
}
}
// eventual BG is at/above target:
// if iob is over max, just cancel any temps
var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
rT.reason = "Eventual BG " + eventualBG + ">=" + profile.max_bg + ", ";
if (basaliob > max_iob) {
rT.reason = "basaliob " + basaliob + " > max_iob " + max_iob;
return setTempBasal(0, 0, profile, rT, offline);
} else { // otherwise, calculate 30m high-temp required to get projected BG down to target
// insulinReq is the additional insulin required to get down to max bg:
// if in meal assist mode, check if snoozeBG is lower, as eventualBG is not dependent on IOB
var insulinReq = (Math.min(snoozeBG,eventualBG) - target_bg) / profile.sens;
if (minDelta < 0 && minDelta > expectedDelta) {
var newinsulinReq = Math.round(( insulinReq * (1 - (minDelta / expectedDelta)) ) * 100)/100;
//console.log("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-basaliob) {
rT.reason = "max_iob " + max_iob + ", ";
insulinReq = max_iob-basaliob;
}
// rate required to deliver insulinReq more insulin over 30m:
var rate = profile.current_basal + (2 * insulinReq);
rate = Math.round( rate * 1000 ) / 1000;
var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
if (rate > maxSafeBasal) {
rT.reason += "adj. req. rate:"+rate.toFixed(1) +" to maxSafeBasal:"+maxSafeBasal.toFixed(1)+", ";
rate = maxSafeBasal;
}
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
if (insulinScheduled > insulinReq + 0.2) { // if current temp would deliver >0.2U more than the required insulin, lower the rate
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > req " + insulinReq + "+0.2U";
return setTempBasal(rate, 30, profile, rT, offline);
}
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline);
}
if (currenttemp.duration > 5 && rate < currenttemp.rate + 0.1) { // if required temp <~ existing temp basal
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
return rT;
}
// required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline);
}
};
module.exports = determine_basal;

View file

@ -31,14 +31,13 @@ function calculate_expected_delta(target_bg, eventual_bg, bgi) {
// (hours * mins_per_hour) / 5 = how many 5 minute periods in 2h = 24 // (hours * mins_per_hour) / 5 = how many 5 minute periods in 2h = 24
var five_min_blocks = (2 * 60) / 5; var five_min_blocks = (2 * 60) / 5;
var target_delta = target_bg - eventual_bg; var target_delta = target_bg - eventual_bg;
var expectedDelta = round(bgi + (target_delta / five_min_blocks), 1); return /* expectedDelta */ round(bgi + (target_delta / five_min_blocks), 1);
return expectedDelta;
} }
function convert_bg(value, profile) function convert_bg(value, profile)
{ {
if (profile.out_units == "mmol/L") if (profile.out_units === "mmol/L")
{ {
return round(value / 18, 1).toFixed(1); return round(value / 18, 1).toFixed(1);
} }
@ -48,10 +47,76 @@ function convert_bg(value, profile)
} }
} }
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data) { function enable_smb(
profile,
microBolusAllowed,
meal_data,
target_bg
) {
// disable SMB when a high temptarget is set
if (! microBolusAllowed) {
console.error("SMB disabled (!microBolusAllowed)");
return false;
} else if (! profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > 100) {
console.error("SMB disabled due to high temptarget of",target_bg);
return false;
} else if (meal_data.bwFound === true && profile.A52_risk_enable === false) {
console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours.");
return false;
}
// enable SMB/UAM if always-on (unless previously disabled for high temptarget)
if (profile.enableSMB_always === true) {
if (meal_data.bwFound) {
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard");
} else {
console.error("SMB enabled due to enableSMB_always");
}
return true;
}
// enable SMB/UAM (if enabled in preferences) while we have COB
if (profile.enableSMB_with_COB === true && meal_data.mealCOB) {
if (meal_data.bwCarbs) {
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard");
} else {
console.error("SMB enabled for COB of",meal_data.mealCOB);
}
return true;
}
// enable SMB/UAM (if enabled in preferences) for a full 6 hours after any carb entry
// (6 hours is defined in carbWindow in lib/meal/total.js)
if (profile.enableSMB_after_carbs === true && meal_data.carbs ) {
if (meal_data.bwCarbs) {
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard");
} else {
console.error("SMB enabled for 6h after carb entry");
}
return true;
}
// enable SMB/UAM (if enabled in preferences) if a low temptarget is set
if (profile.enableSMB_with_temptarget === true && (profile.temptargetSet && target_bg < 100)) {
if (meal_data.bwFound) {
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard");
} else {
console.error("SMB enabled for temptarget of",convert_bg(target_bg, profile));
}
return true;
}
console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)");
return false;
}
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data, currentTime) {
var rT = {}; //short for requestedTemp var rT = {}; //short for requestedTemp
var deliverAt = new Date(); var deliverAt = new Date();
if (currentTime) {
deliverAt = new Date(currentTime);
}
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') { if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
rT.error ='Error: could not get current basal rate'; rT.error ='Error: could not get current basal rate';
@ -61,26 +126,41 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var basal = profile_current_basal; var basal = profile_current_basal;
var systemTime = new Date(); var systemTime = new Date();
if (currentTime) {
systemTime = currentTime;
}
var bgTime = new Date(glucose_status.date); var bgTime = new Date(glucose_status.date);
var minAgo = round( (systemTime - bgTime) / 60 / 1000 ,1); var minAgo = round( (systemTime - bgTime) / 60 / 1000 ,1);
var bg = glucose_status.glucose; var bg = glucose_status.glucose;
if (bg < 39) { //Dexcom is in ??? mode or calibrating var noise = glucose_status.noise;
rT.reason = "CGM is calibrating or in ??? state"; // 38 is an xDrip error state that usually indicates sensor failure
// all other BG values between 11 and 37 mg/dL reflect non-error-code BG values, so we should zero temp for those
if (bg <= 10 || bg === 38 || noise >= 3) { //Dexcom is in ??? mode or calibrating, or xDrip reports high noise
rT.reason = "CGM is calibrating, in ??? state, or noise is high";
} }
if (minAgo > 12 || minAgo < -5) { // Dexcom data is too old, or way in the future if (minAgo > 12 || minAgo < -5) { // Dexcom data is too old, or way in the future
rT.reason = "If current system time "+systemTime+" is correct, then BG data is too old. The last BG data was read "+minAgo+"m ago at "+bgTime; rT.reason = "If current system time "+systemTime+" is correct, then BG data is too old. The last BG data was read "+minAgo+"m ago at "+bgTime;
// if BG is too old/noisy, or is changing less than 1 mg/dL/5m for 45m, cancel any high temps and shorten any long zero temps
//cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc
} else if ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) {
if ( glucose_status.last_cal && glucose_status.last_cal < 3 ) {
rT.reason = "CGM was just calibrated";
} else {
rT.reason = "Error: CGM data is unchanged for the past ~45m";
} }
if (bg < 39 || minAgo > 12 || minAgo < -5) { }
if (currenttemp.rate >= basal) { // high temp is running //cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc
rT.reason += ". Canceling high temp basal of "+currenttemp.rate; if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) ) {
if (currenttemp.rate > basal) { // high temp is running
rT.reason += ". Replacing high temp basal of "+currenttemp.rate+" with neutral temp of "+basal;
rT.deliverAt = deliverAt; rT.deliverAt = deliverAt;
rT.temp = 'absolute'; rT.temp = 'absolute';
rT.duration = 0; rT.duration = 30;
rT.rate = 0; rT.rate = basal;
return rT; return rT;
//return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); //return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
} else if ( currenttemp.rate == 0 && currenttemp.duration > 30 ) { //shorten long zero temps to 30m } else if ( currenttemp.rate === 0 && currenttemp.duration > 30 ) { //shorten long zero temps to 30m
rT.reason += ". Shortening " + currenttemp.duration + "m long zero temp to 30m. "; rT.reason += ". Shortening " + currenttemp.duration + "m long zero temp to 30m. ";
rT.deliverAt = deliverAt; rT.deliverAt = deliverAt;
rT.temp = 'absolute'; rT.temp = 'absolute';
@ -115,14 +195,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var sensitivityRatio; var sensitivityRatio;
var high_temptarget_raises_sensitivity = profile.exercise_mode || profile.high_temptarget_raises_sensitivity; var high_temptarget_raises_sensitivity = profile.exercise_mode || profile.high_temptarget_raises_sensitivity;
var normalTarget = 100; // evaluate high/low temptarget against 100, not scheduled basal (which might change) var normalTarget = 100; // evaluate high/low temptarget against 100, not scheduled target (which might change)
if ( profile.half_basal_exercise_target ) { if ( profile.half_basal_exercise_target ) {
var halfBasalTarget = profile.half_basal_exercise_target; var halfBasalTarget = profile.half_basal_exercise_target;
} else { } else {
var halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%) halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%)
// 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default) // 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
} }
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget + 10 if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget
|| profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) { || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44 // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6 // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
@ -132,36 +212,36 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// limit sensitivityRatio to profile.autosens_max (1.2x by default) // limit sensitivityRatio to profile.autosens_max (1.2x by default)
sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max); sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max);
sensitivityRatio = round(sensitivityRatio,2); sensitivityRatio = round(sensitivityRatio,2);
console.error("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; "); console.log("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; ");
} else if (typeof autosens_data !== 'undefined' ) { } else if (typeof autosens_data !== 'undefined' && autosens_data) {
sensitivityRatio = autosens_data.ratio; sensitivityRatio = autosens_data.ratio;
console.error("Autosens ratio: "+sensitivityRatio+"; "); console.log("Autosens ratio: "+sensitivityRatio+"; ");
} }
if (sensitivityRatio) { if (sensitivityRatio) {
basal = profile.current_basal * sensitivityRatio; basal = profile.current_basal * sensitivityRatio;
basal = round_basal(basal, profile); basal = round_basal(basal, profile);
if (basal != profile_current_basal) { if (basal !== profile_current_basal) {
console.error("Adjusting basal from "+profile_current_basal+" to "+basal+"; "); console.log("Adjusting basal from "+profile_current_basal+" to "+basal+"; ");
} else { } else {
console.error("Basal unchanged: "+basal+"; "); console.log("Basal unchanged: "+basal+"; ");
} }
} }
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120 // adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
if (profile.temptargetSet) { if (profile.temptargetSet) {
//console.error("Temp Target set, not adjusting with autosens; "); //console.log("Temp Target set, not adjusting with autosens; ");
} else if (typeof autosens_data !== 'undefined' ) { } else if (typeof autosens_data !== 'undefined' && autosens_data) {
if ( profile.sensitivity_raises_target && autosens_data.ratio < 1 || profile.resistance_lowers_target && autosens_data.ratio > 1 ) { if ( profile.sensitivity_raises_target && autosens_data.ratio < 1 || profile.resistance_lowers_target && autosens_data.ratio > 1 ) {
// with a target of 100, default 0.7-1.2 autosens min/max range would allow a 93-117 target range // with a target of 100, default 0.7-1.2 autosens min/max range would allow a 93-117 target range
min_bg = round((min_bg - 60) / autosens_data.ratio) + 60; min_bg = round((min_bg - 60) / autosens_data.ratio) + 60;
max_bg = round((max_bg - 60) / autosens_data.ratio) + 60; max_bg = round((max_bg - 60) / autosens_data.ratio) + 60;
new_target_bg = round((target_bg - 60) / autosens_data.ratio) + 60; var new_target_bg = round((target_bg - 60) / autosens_data.ratio) + 60;
// don't allow target_bg below 80 // don't allow target_bg below 80
new_target_bg = Math.max(80, new_target_bg); new_target_bg = Math.max(80, new_target_bg);
if (target_bg == new_target_bg) { if (target_bg === new_target_bg) {
console.error("target_bg unchanged: "+new_target_bg+"; "); console.log("target_bg unchanged: "+new_target_bg+"; ");
} else { } else {
console.error("target_bg from "+target_bg+" to "+new_target_bg+"; "); console.log("target_bg from "+target_bg+" to "+new_target_bg+"; ");
} }
target_bg = new_target_bg; target_bg = new_target_bg;
} }
@ -197,34 +277,33 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var profile_sens = round(profile.sens,1) var profile_sens = round(profile.sens,1)
var sens = profile.sens; var sens = profile.sens;
if (typeof autosens_data !== 'undefined' ) { if (typeof autosens_data !== 'undefined' && autosens_data) {
sens = profile.sens / sensitivityRatio; sens = profile.sens / sensitivityRatio;
sens = round(sens, 1); sens = round(sens, 1);
if (sens != profile_sens) { if (sens !== profile_sens) {
console.error("ISF from "+profile_sens+" to "+sens); console.log("ISF from "+profile_sens+" to "+sens);
} else { } else {
console.error("ISF unchanged: "+sens); console.log("ISF unchanged: "+sens);
} }
//console.error(" (autosens ratio "+sensitivityRatio+")"); //console.log(" (autosens ratio "+sensitivityRatio+")");
} }
console.error("; CR:",profile.carb_ratio); console.error("; CR:",profile.carb_ratio);
// compare currenttemp to iob_data.lastTemp and cancel temp if they don't match // compare currenttemp to iob_data.lastTemp and cancel temp if they don't match
var lastTempAge; var lastTempAge;
if (typeof iob_data.lastTemp !== 'undefined' ) { if (typeof iob_data.lastTemp !== 'undefined' ) {
lastTempAge = round(( new Date().getTime() - iob_data.lastTemp.date ) / 60000); // in minutes lastTempAge = round(( new Date(systemTime).getTime() - iob_data.lastTemp.date ) / 60000); // in minutes
// } ---- added to not produce errors
} else { } else {
lastTempAge = 0; lastTempAge = 0;
} }
//console.error("currenttemp:",currenttemp,"lastTemp:",JSON.stringify(iob_data.lastTemp),"lastTempAge:",lastTempAge,"m"); //console.error("currenttemp:",currenttemp,"lastTemp:",JSON.stringify(iob_data.lastTemp),"lastTempAge:",lastTempAge,"m");
tempModulus = (lastTempAge + currenttemp.duration) % 30; var tempModulus = (lastTempAge + currenttemp.duration) % 30;
console.error("currenttemp:",currenttemp,"lastTempAge:",lastTempAge,"m","tempModulus:",tempModulus,"m"); console.error("currenttemp:",currenttemp,"lastTempAge:",lastTempAge,"m","tempModulus:",tempModulus,"m");
rT.temp = 'absolute'; rT.temp = 'absolute';
rT.deliverAt = deliverAt; rT.deliverAt = deliverAt;
if ( microBolusAllowed && currenttemp && iob_data.lastTemp && currenttemp.rate != iob_data.lastTemp.rate ) { if ( microBolusAllowed && currenttemp && iob_data.lastTemp && currenttemp.rate !== iob_data.lastTemp.rate && lastTempAge > 10 && currenttemp.duration ) {
rT.reason = "Warning: currenttemp rate "+currenttemp.rate+" != lastTemp rate "+iob_data.lastTemp.rate+" from pumphistory; setting neutral temp of "+basal+"."; rT.reason = "Warning: currenttemp rate "+currenttemp.rate+" != lastTemp rate "+iob_data.lastTemp.rate+" from pumphistory; canceling temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
} }
if ( currenttemp && iob_data.lastTemp && currenttemp.duration > 0 ) { if ( currenttemp && iob_data.lastTemp && currenttemp.duration > 0 ) {
// TODO: fix this (lastTemp.duration is how long it has run; currenttemp.duration is time left // TODO: fix this (lastTemp.duration is how long it has run; currenttemp.duration is time left
@ -234,10 +313,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
//} //}
//console.error(lastTempAge, round(iob_data.lastTemp.duration,1), round(lastTempAge - iob_data.lastTemp.duration,1)); //console.error(lastTempAge, round(iob_data.lastTemp.duration,1), round(lastTempAge - iob_data.lastTemp.duration,1));
var lastTempEnded = lastTempAge - iob_data.lastTemp.duration var lastTempEnded = lastTempAge - iob_data.lastTemp.duration
if ( lastTempEnded > 5 ) { if ( lastTempEnded > 5 && lastTempAge > 10 ) {
rT.reason = "Warning: currenttemp running but lastTemp from pumphistory ended "+lastTempEnded+"m ago; setting neutral temp of "+basal+"."; rT.reason = "Warning: currenttemp running but lastTemp from pumphistory ended "+lastTempEnded+"m ago; canceling temp";
//console.error(currenttemp, round(iob_data.lastTemp,1), round(lastTempAge,1)); //console.error(currenttemp, round(iob_data.lastTemp,1), round(lastTempAge,1));
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
} }
// TODO: figure out a way to do this check that doesn't fail across basal schedule boundaries // TODO: figure out a way to do this check that doesn't fail across basal schedule boundaries
//if ( tempModulus < 25 && tempModulus > 5 ) { //if ( tempModulus < 25 && tempModulus > 5 ) {
@ -264,37 +343,44 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
if (iob_data.iob > 0) { if (iob_data.iob > 0) {
var naive_eventualBG = round( bg - (iob_data.iob * sens) ); var naive_eventualBG = round( bg - (iob_data.iob * sens) );
} else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens } else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens
var naive_eventualBG = round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) ); naive_eventualBG = round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) );
} }
// and adjust it for the deviation above // and adjust it for the deviation above
var eventualBG = naive_eventualBG + deviation; var eventualBG = naive_eventualBG + deviation;
// calculate what portion of that is due to bolussnooze
//var bolusContrib = iob_data.bolussnooze * sens;
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
//var naive_snoozeBG = round( naive_eventualBG + 1.5 * bolusContrib );
// adjust that for deviation like we did eventualBG
//var snoozeBG = naive_snoozeBG + deviation;
// adjust target BG range if needed to safely bring down high BG faster without causing lows // raise target for noisy / raw CGM data
if ( bg > max_bg && profile.adv_target_adjustments && ! profile.temptargetSet ) { if (glucose_status.noise >= 2) {
// increase target at least 10% (default 30%) for raw / noisy data
var noisyCGMTargetMultiplier = Math.max( 1.1, profile.noisyCGMTargetMultiplier );
// don't allow maxRaw above 250
var maxRaw = Math.min( 250, profile.maxRaw );
var adjustedMinBG = round(Math.min(200, min_bg * noisyCGMTargetMultiplier ));
var adjustedTargetBG = round(Math.min(200, target_bg * noisyCGMTargetMultiplier ));
var adjustedMaxBG = round(Math.min(200, max_bg * noisyCGMTargetMultiplier ));
console.log("Raising target_bg for noisy / raw CGM data, from "+target_bg+" to "+adjustedTargetBG+"; ");
min_bg = adjustedMinBG;
target_bg = adjustedTargetBG;
max_bg = adjustedMaxBG;
// adjust target BG range if configured to bring down high BG faster
} else if ( bg > max_bg && profile.adv_target_adjustments && ! profile.temptargetSet ) {
// with target=100, as BG rises from 100 to 160, adjustedTarget drops from 100 to 80 // with target=100, as BG rises from 100 to 160, adjustedTarget drops from 100 to 80
var adjustedMinBG = round(Math.max(80, min_bg - (bg - min_bg)/3 ),0); adjustedMinBG = round(Math.max(80, min_bg - (bg - min_bg)/3 ),0);
var adjustedTargetBG =round( Math.max(80, target_bg - (bg - target_bg)/3 ),0); adjustedTargetBG =round( Math.max(80, target_bg - (bg - target_bg)/3 ),0);
var adjustedMaxBG = round(Math.max(80, max_bg - (bg - max_bg)/3 ),0); adjustedMaxBG = round(Math.max(80, max_bg - (bg - max_bg)/3 ),0);
// if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedMinBG, dont use it // if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedMinBG, dont use it
//console.error("naive_eventualBG:",naive_eventualBG+", eventualBG:",eventualBG); //console.error("naive_eventualBG:",naive_eventualBG+", eventualBG:",eventualBG);
if (eventualBG > adjustedMinBG && naive_eventualBG > adjustedMinBG && min_bg > adjustedMinBG) { if (eventualBG > adjustedMinBG && naive_eventualBG > adjustedMinBG && min_bg > adjustedMinBG) {
console.error("Adjusting targets for high BG: min_bg from "+min_bg+" to "+adjustedMinBG+"; "); console.log("Adjusting targets for high BG: min_bg from "+min_bg+" to "+adjustedMinBG+"; ");
min_bg = adjustedMinBG; min_bg = adjustedMinBG;
} else { } else {
console.error("min_bg unchanged: "+min_bg+"; "); console.log("min_bg unchanged: "+min_bg+"; ");
} }
// if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedTargetBG, dont use it // if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedTargetBG, dont use it
if (eventualBG > adjustedTargetBG && naive_eventualBG > adjustedTargetBG && target_bg > adjustedTargetBG) { if (eventualBG > adjustedTargetBG && naive_eventualBG > adjustedTargetBG && target_bg > adjustedTargetBG) {
console.error("target_bg from "+target_bg+" to "+adjustedTargetBG+"; "); console.log("target_bg from "+target_bg+" to "+adjustedTargetBG+"; ");
target_bg = adjustedTargetBG; target_bg = adjustedTargetBG;
} else { } else {
console.error("target_bg unchanged: "+target_bg+"; "); console.log("target_bg unchanged: "+target_bg+"; ");
} }
// if eventualBG, naive_eventualBG, and max_bg aren't all above adjustedMaxBG, dont use it // if eventualBG, naive_eventualBG, and max_bg aren't all above adjustedMaxBG, dont use it
if (eventualBG > adjustedMaxBG && naive_eventualBG > adjustedMaxBG && max_bg > adjustedMaxBG) { if (eventualBG > adjustedMaxBG && naive_eventualBG > adjustedMaxBG && max_bg > adjustedMaxBG) {
@ -321,7 +407,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
, 'bg': bg , 'bg': bg
, 'tick': tick , 'tick': tick
, 'eventualBG': eventualBG , 'eventualBG': eventualBG
//, 'snoozeBG': snoozeBG
, 'insulinReq': 0 , 'insulinReq': 0
, 'reservoir' : reservoir_data // The expected reservoir volume at which to deliver the microbolus (the reservoir volume from right before the last pumphistory run) , 'reservoir' : reservoir_data // The expected reservoir volume at which to deliver the microbolus (the reservoir volume from right before the last pumphistory run)
, 'deliverAt' : deliverAt // The time at which the microbolus should be delivered , 'deliverAt' : deliverAt // The time at which the microbolus should be delivered
@ -341,71 +426,13 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
ZTpredBGs.push(bg); ZTpredBGs.push(bg);
UAMpredBGs.push(bg); UAMpredBGs.push(bg);
// enable SMB whenever we have COB or UAM is enabled var enableSMB = enable_smb(
// SMB is disabled by default, unless explicitly enabled in preferences.json profile,
var enableSMB=false; microBolusAllowed,
// disable SMB when a high temptarget is set meal_data,
if (! microBolusAllowed) { target_bg
console.error("SMB disabled (!microBolusAllowed)") );
} else if (! profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > 100) {
console.error("SMB disabled due to high temptarget of",target_bg);
enableSMB=false;
// enable SMB/UAM (if enabled in preferences) while we have COB
} else if (profile.enableSMB_with_COB === true && meal_data.mealCOB) {
if (meal_data.bwCarbs) {
if (profile.A52_risk_enable) {
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard")
enableSMB=true;
} else {
console.error("SMB not enabled for Bolus Wizard COB");
}
} else {
console.error("SMB enabled for COB of",meal_data.mealCOB);
enableSMB=true;
}
// enable SMB/UAM (if enabled in preferences) for a full 6 hours after any carb entry
// (6 hours is defined in carbWindow in lib/meal/total.js)
} else if (profile.enableSMB_after_carbs === true && meal_data.carbs ) {
if (meal_data.bwCarbs) {
if (profile.A52_risk_enable) {
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard")
enableSMB=true;
} else {
console.error("SMB not enabled for Bolus Wizard carbs");
}
} else {
console.error("SMB enabled for 6h after carb entry");
enableSMB=true;
}
// enable SMB/UAM (if enabled in preferences) if a low temptarget is set
} else if (profile.enableSMB_with_temptarget === true && (profile.temptargetSet && target_bg < 100)) {
if (meal_data.bwFound) {
if (profile.A52_risk_enable) {
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard")
enableSMB=true;
} else {
console.error("enableSMB_with_temptarget not supported within 6h of using Bolus Wizard");
}
} else {
console.error("SMB enabled for temptarget of",convert_bg(target_bg, profile));
enableSMB=true;
}
// enable SMB/UAM if always-on (unless previously disabled for high temptarget)
} else if (profile.enableSMB_always === true) {
if (meal_data.bwFound) {
if (profile.A52_risk_enable === true) {
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard")
enableSMB=true;
} else {
console.error("enableSMB_always not supported within 6h of using Bolus Wizard");
}
} else {
console.error("SMB enabled due to enableSMB_always");
enableSMB=true;
}
} else {
console.error("SMB disabled (no enableSMB preferences active)");
}
// enable UAM (if enabled in preferences) // enable UAM (if enabled in preferences)
var enableUAM=(profile.enableUAM); var enableUAM=(profile.enableUAM);
@ -417,43 +444,48 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// calculate current carb absorption rate, and how long to absorb all carbs // calculate current carb absorption rate, and how long to absorb all carbs
// CI = current carb impact on BG in mg/dL/5m // CI = current carb impact on BG in mg/dL/5m
ci = round((minDelta - bgi),1); ci = round((minDelta - bgi),1);
uci = round((minDelta - bgi),1); var uci = round((minDelta - bgi),1);
// ISF (mg/dL/U) / CR (g/U) = CSF (mg/dL/g) // ISF (mg/dL/U) / CR (g/U) = CSF (mg/dL/g)
if (profile.temptargetSet) {
// TODO: remove commented-out code for old behavior
//if (profile.temptargetSet) {
// if temptargetSet, use unadjusted profile.sens to allow activity mode sensitivityRatio to adjust CR // if temptargetSet, use unadjusted profile.sens to allow activity mode sensitivityRatio to adjust CR
var csf = profile.sens / profile.carb_ratio; //var csf = profile.sens / profile.carb_ratio;
} else { //} else {
// otherwise, use autosens-adjusted sens to counteract autosens meal insulin dosing adjustments // otherwise, use autosens-adjusted sens to counteract autosens meal insulin dosing adjustments
// so that autotuned CR is still in effect even when basals and ISF are being adjusted by autosens // so that autotuned CR is still in effect even when basals and ISF are being adjusted by autosens
var csf = sens / profile.carb_ratio; //var csf = sens / profile.carb_ratio;
} //}
// use autosens-adjusted sens to counteract autosens meal insulin dosing adjustments so that
// autotuned CR is still in effect even when basals and ISF are being adjusted by TT or autosens
// this avoids overdosing insulin for large meals when low temp targets are active
csf = sens / profile.carb_ratio;
console.error("profile.sens:",profile.sens,"sens:",sens,"CSF:",csf);
var maxCarbAbsorptionRate = 30; // g/h; maximum rate to assume carbs will absorb if no CI observed var maxCarbAbsorptionRate = 30; // g/h; maximum rate to assume carbs will absorb if no CI observed
// limit Carb Impact to maxCarbAbsorptionRate * csf in mg/dL per 5m // limit Carb Impact to maxCarbAbsorptionRate * csf in mg/dL per 5m
maxCI = round(maxCarbAbsorptionRate*csf*5/60,1) var maxCI = round(maxCarbAbsorptionRate*csf*5/60,1)
if (ci > maxCI) { if (ci > maxCI) {
console.error("Limiting carb impact from",ci,"to",maxCI,"mg/dL/5m (",maxCarbAbsorptionRate,"g/h )"); console.error("Limiting carb impact from",ci,"to",maxCI,"mg/dL/5m (",maxCarbAbsorptionRate,"g/h )");
ci = maxCI; ci = maxCI;
} }
// set meal_carbimpact high enough to absorb all meal carbs over 6 hours var remainingCATimeMin = 3; // h; duration of expected not-yet-observed carb absorption
// total_impact (mg/dL) = CSF (mg/dL/g) * carbs (g) // adjust remainingCATime (instead of CR) for autosens if sensitivityRatio defined
//console.error(csf * meal_data.carbs); if (sensitivityRatio){
// meal_carbimpact (mg/dL/5m) = CSF (mg/dL/g) * carbs (g) / 6 (h) * (1h/60m) * 5 (m/5m) * 2 (for linear decay)
//var meal_carbimpact = round((csf * meal_data.carbs / 6 / 60 * 5 * 2),1)
var remainingCATimeMin = 3; // h; before carb absorption starts
// adjust remainingCATime (instead of CR) for autosens
remainingCATimeMin = remainingCATimeMin / sensitivityRatio; remainingCATimeMin = remainingCATimeMin / sensitivityRatio;
}
// 20 g/h means that anything <= 60g will get a remainingCATimeMin, 80g will get 4h, and 120g 6h // 20 g/h means that anything <= 60g will get a remainingCATimeMin, 80g will get 4h, and 120g 6h
// when actual absorption ramps up it will take over from remainingCATime // when actual absorption ramps up it will take over from remainingCATime
var assumedCarbAbsorptionRate = 20; // g/h; maximum rate to assume carbs will absorb if no CI observed var assumedCarbAbsorptionRate = 20; // g/h; maximum rate to assume carbs will absorb if no CI observed
var remainingCATime = remainingCATimeMin; // added by mike https://github.com/openaps/oref0/issues/884 var remainingCATime = remainingCATimeMin;
if (meal_data.carbs) { if (meal_data.carbs) {
// if carbs * assumedCarbAbsorptionRate > remainingCATimeMin, raise it // if carbs * assumedCarbAbsorptionRate > remainingCATimeMin, raise it
// so <= 90g is assumed to take 3h, and 120g=4h // so <= 90g is assumed to take 3h, and 120g=4h
remainingCATimeMin = Math.max(remainingCATimeMin, meal_data.mealCOB/assumedCarbAbsorptionRate); remainingCATimeMin = Math.max(remainingCATimeMin, meal_data.mealCOB/assumedCarbAbsorptionRate);
var lastCarbAge = round(( new Date().getTime() - meal_data.lastCarbTime ) / 60000); var lastCarbAge = round(( new Date(systemTime).getTime() - meal_data.lastCarbTime ) / 60000);
//console.error(meal_data.lastCarbTime, lastCarbAge); //console.error(meal_data.lastCarbTime, lastCarbAge);
fractionCOBAbsorbed = ( meal_data.carbs - meal_data.mealCOB ) / meal_data.carbs; var fractionCOBAbsorbed = ( meal_data.carbs - meal_data.mealCOB ) / meal_data.carbs;
remainingCATime = remainingCATimeMin + 1.5 * lastCarbAge/60; remainingCATime = remainingCATimeMin + 1.5 * lastCarbAge/60;
remainingCATime = round(remainingCATime,1); remainingCATime = round(remainingCATime,1);
//console.error(fractionCOBAbsorbed, remainingCATimeAdjustment, remainingCATime) //console.error(fractionCOBAbsorbed, remainingCATimeAdjustment, remainingCATime)
@ -478,7 +510,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// remainingCIpeak (mg/dL/5m) = remainingCarbs (g) * CSF (mg/dL/g) * 5 (m/5m) * 1h/60m / (remainingCATime/2) (h) // remainingCIpeak (mg/dL/5m) = remainingCarbs (g) * CSF (mg/dL/g) * 5 (m/5m) * 1h/60m / (remainingCATime/2) (h)
var remainingCIpeak = remainingCarbs * csf * 5 / 60 / (remainingCATime/2); var remainingCIpeak = remainingCarbs * csf * 5 / 60 / (remainingCATime/2);
//console.error(profile.min_5m_carbimpact,ci,totalCI,totalCA,remainingCarbs,remainingCI,remainingCATime); //console.error(profile.min_5m_carbimpact,ci,totalCI,totalCA,remainingCarbs,remainingCI,remainingCATime);
//if (meal_data.mealCOB * 3 > meal_data.carbs) { }
// calculate peak deviation in last hour, and slope from that to current deviation // calculate peak deviation in last hour, and slope from that to current deviation
var slopeFromMaxDeviation = round(meal_data.slopeFromMaxDeviation,2); var slopeFromMaxDeviation = round(meal_data.slopeFromMaxDeviation,2);
@ -488,17 +519,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var slopeFromDeviations = Math.min(slopeFromMaxDeviation,-slopeFromMinDeviation/3); var slopeFromDeviations = Math.min(slopeFromMaxDeviation,-slopeFromMinDeviation/3);
//console.error(slopeFromMaxDeviation); //console.error(slopeFromMaxDeviation);
aci = 10; var aci = 10;
//5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m) //5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
// duration (in 5m data points) = COB (g) * CSF (mg/dL/g) / ci (mg/dL/5m) // duration (in 5m data points) = COB (g) * CSF (mg/dL/g) / ci (mg/dL/5m)
// limit cid to remainingCATime hours: the reset goes to remainingCI // limit cid to remainingCATime hours: the reset goes to remainingCI
if (ci == 0) { if (ci === 0) {
// avoid divide by zero // avoid divide by zero
cid = 0; cid = 0;
} else { } else {
cid = Math.min(remainingCATime*60/5/2,Math.max(0, meal_data.mealCOB * csf / ci )); cid = Math.min(remainingCATime*60/5/2,Math.max(0, meal_data.mealCOB * csf / ci ));
} }
acid = Math.max(0, meal_data.mealCOB * csf / aci ); var acid = Math.max(0, meal_data.mealCOB * csf / aci );
// duration (hours) = duration (5m) * 5 / 60 * 2 (to account for linear decay) // duration (hours) = duration (5m) * 5 / 60 * 2 (to account for linear decay)
console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",round(cid*5/60*2,1),"hours; remaining CI (~2h peak):",round(remainingCIpeak,1),"mg/dL per 5m"); console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",round(cid*5/60*2,1),"hours; remaining CI (~2h peak):",round(remainingCIpeak,1),"mg/dL per 5m");
//console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",round(acid*5/60*2,1),"hours"); //console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",round(acid*5/60*2,1),"hours");
@ -529,18 +560,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
try { try {
iobArray.forEach(function(iobTick) { iobArray.forEach(function(iobTick) {
//console.error(iobTick); //console.error(iobTick);
predBGI = round(( -iobTick.activity * sens * 5 ), 2); var predBGI = round(( -iobTick.activity * sens * 5 ), 2);
predZTBGI = round(( -iobTick.iobWithZeroTemp.activity * sens * 5 ), 2); var predZTBGI = round(( -iobTick.iobWithZeroTemp.activity * sens * 5 ), 2);
// for IOBpredBGs, predicted deviation impact drops linearly from current deviation down to zero // for IOBpredBGs, predicted deviation impact drops linearly from current deviation down to zero
// over 60 minutes (data points every 5m) // over 60 minutes (data points every 5m)
predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) ); var predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev; IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev;
// calculate predBGs with long zero temp without deviations // calculate predBGs with long zero temp without deviations
ZTpredBG = ZTpredBGs[ZTpredBGs.length-1] + predZTBGI; var ZTpredBG = ZTpredBGs[ZTpredBGs.length-1] + predZTBGI;
// for COBpredBGs, predicted carb impact drops linearly from current carb impact down to zero // for COBpredBGs, predicted carb impact drops linearly from current carb impact down to zero
// eventually accounting for all carbs (if they can be absorbed over DIA) // eventually accounting for all carbs (if they can be absorbed over DIA)
predCI = Math.max(0, Math.max(0,ci) * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) ); var predCI = Math.max(0, Math.max(0,ci) * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
predACI = Math.max(0, Math.max(0,aci) * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) ); var predACI = Math.max(0, Math.max(0,aci) * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
// if any carbs aren't absorbed after remainingCATime hours, assume they'll absorb in a /\ shaped // if any carbs aren't absorbed after remainingCATime hours, assume they'll absorb in a /\ shaped
// bilinear curve peaking at remainingCIpeak at remainingCATime/2 hours (remainingCATime/2*12 * 5m) // bilinear curve peaking at remainingCIpeak at remainingCATime/2 hours (remainingCATime/2*12 * 5m)
// and ending at remainingCATime h (remainingCATime*12 * 5m intervals) // and ending at remainingCATime h (remainingCATime*12 * 5m intervals)
@ -549,18 +580,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
remainingCItotal += predCI+remainingCI; remainingCItotal += predCI+remainingCI;
remainingCIs.push(round(remainingCI,0)); remainingCIs.push(round(remainingCI,0));
predCIs.push(round(predCI,0)); predCIs.push(round(predCI,0));
//console.error(round(predCI,1)+"+"+round(remainingCI,1)+" "); //console.log(round(predCI,1)+"+"+round(remainingCI,1)+" ");
COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI + remainingCI; COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI + remainingCI;
aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI; var aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
// for UAMpredBGs, predicted carb impact drops at slopeFromDeviations // for UAMpredBGs, predicted carb impact drops at slopeFromDeviations
// calculate predicted CI from UAM based on slopeFromDeviations // calculate predicted CI from UAM based on slopeFromDeviations
predUCIslope = Math.max(0, uci + ( UAMpredBGs.length*slopeFromDeviations ) ); var predUCIslope = Math.max(0, uci + ( UAMpredBGs.length*slopeFromDeviations ) );
// if slopeFromDeviations is too flat, predicted deviation impact drops linearly from // if slopeFromDeviations is too flat, predicted deviation impact drops linearly from
// current deviation down to zero over 3h (data points every 5m) // current deviation down to zero over 3h (data points every 5m)
predUCImax = Math.max(0, uci * ( 1 - UAMpredBGs.length/Math.max(3*60/5,1) ) ); var predUCImax = Math.max(0, uci * ( 1 - UAMpredBGs.length/Math.max(3*60/5,1) ) );
//console.error(predUCIslope, predUCImax); //console.error(predUCIslope, predUCImax);
// predicted CI from UAM is the lesser of CI based on deviationSlope or DIA // predicted CI from UAM is the lesser of CI based on deviationSlope or DIA
predUCI = Math.min(predUCIslope, predUCImax); var predUCI = Math.min(predUCIslope, predUCImax);
if(predUCI>0) { if(predUCI>0) {
//console.error(UAMpredBGs.length,slopeFromDeviations, predUCI); //console.error(UAMpredBGs.length,slopeFromDeviations, predUCI);
UAMduration=round((UAMpredBGs.length+1)*5/60,1); UAMduration=round((UAMpredBGs.length+1)*5/60,1);
@ -582,7 +613,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// set minPredBGs starting when currently-dosed insulin activity will peak // set minPredBGs starting when currently-dosed insulin activity will peak
// look ahead 60m (regardless of insulin type) so as to be less aggressive on slower insulins // look ahead 60m (regardless of insulin type) so as to be less aggressive on slower insulins
var insulinPeakTime = 60; var insulinPeakTime = 60;
// add 30m to allow for insluin delivery (SMBs or temps) // add 30m to allow for insulin delivery (SMBs or temps)
insulinPeakTime = 90; insulinPeakTime = 90;
var insulinPeak5m = (insulinPeakTime/60)*12; var insulinPeak5m = (insulinPeakTime/60)*12;
//console.error(insulinPeakTime, insulinPeak5m, profile.insulinPeakTime, profile.curve); //console.error(insulinPeakTime, insulinPeak5m, profile.insulinPeakTime, profile.curve);
@ -599,19 +630,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// set eventualBG to include effect of carbs // set eventualBG to include effect of carbs
//console.error("PredBGs:",JSON.stringify(predBGs)); //console.error("PredBGs:",JSON.stringify(predBGs));
} catch (e) { } catch (e) {
console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled:",e); console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled");
} }
if (meal_data.mealCOB) { if (meal_data.mealCOB) {
console.error("predCIs (mg/dL/5m):",predCIs.join(" ")); console.error("predCIs (mg/dL/5m):",predCIs.join(" "));
console.error("remainingCIs: ",remainingCIs.join(" ")); console.error("remainingCIs: ",remainingCIs.join(" "));
} }
//,"totalCA:",round(totalCA,2),"remainingCItotal/csf+totalCA:",round(remainingCItotal/csf+totalCA,2));
rT.predBGs = {}; rT.predBGs = {};
IOBpredBGs.forEach(function(p, i, theArray) { IOBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = round(Math.min(401,Math.max(39,p))); theArray[i] = round(Math.min(401,Math.max(39,p)));
}); });
for (var i=IOBpredBGs.length-1; i > 12; i--) { for (var i=IOBpredBGs.length-1; i > 12; i--) {
if (IOBpredBGs[i-1] != IOBpredBGs[i]) { break; } if (IOBpredBGs[i-1] !== IOBpredBGs[i]) { break; }
else { IOBpredBGs.pop(); } else { IOBpredBGs.pop(); }
} }
rT.predBGs.IOB = IOBpredBGs; rT.predBGs.IOB = IOBpredBGs;
@ -619,10 +649,9 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
ZTpredBGs.forEach(function(p, i, theArray) { ZTpredBGs.forEach(function(p, i, theArray) {
theArray[i] = round(Math.min(401,Math.max(39,p))); theArray[i] = round(Math.min(401,Math.max(39,p)));
}); });
for (var i=ZTpredBGs.length-1; i > 6; i--) { for (i=ZTpredBGs.length-1; i > 6; i--) {
//if (ZTpredBGs[i-1] != ZTpredBGs[i]) { break; }
// stop displaying ZTpredBGs once they're rising and above target // stop displaying ZTpredBGs once they're rising and above target
if (ZTpredBGs[i-1] >= ZTpredBGs[i] || ZTpredBGs[i] < target_bg) { break; } if (ZTpredBGs[i-1] >= ZTpredBGs[i] || ZTpredBGs[i] <= target_bg) { break; }
else { ZTpredBGs.pop(); } else { ZTpredBGs.pop(); }
} }
rT.predBGs.ZT = ZTpredBGs; rT.predBGs.ZT = ZTpredBGs;
@ -631,19 +660,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
aCOBpredBGs.forEach(function(p, i, theArray) { aCOBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = round(Math.min(401,Math.max(39,p))); theArray[i] = round(Math.min(401,Math.max(39,p)));
}); });
for (var i=aCOBpredBGs.length-1; i > 12; i--) { for (i=aCOBpredBGs.length-1; i > 12; i--) {
if (aCOBpredBGs[i-1] != aCOBpredBGs[i]) { break; } if (aCOBpredBGs[i-1] !== aCOBpredBGs[i]) { break; }
else { aCOBpredBGs.pop(); } else { aCOBpredBGs.pop(); }
} }
// disable for now. may want to add a preference to re-enable
//rT.predBGs.aCOB = aCOBpredBGs;
} }
if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) { if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) {
COBpredBGs.forEach(function(p, i, theArray) { COBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = round(Math.min(401,Math.max(39,p))); theArray[i] = round(Math.min(401,Math.max(39,p)));
}); });
for (var i=COBpredBGs.length-1; i > 12; i--) { for (i=COBpredBGs.length-1; i > 12; i--) {
if (COBpredBGs[i-1] != COBpredBGs[i]) { break; } if (COBpredBGs[i-1] !== COBpredBGs[i]) { break; }
else { COBpredBGs.pop(); } else { COBpredBGs.pop(); }
} }
rT.predBGs.COB = COBpredBGs; rT.predBGs.COB = COBpredBGs;
@ -655,8 +682,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
UAMpredBGs.forEach(function(p, i, theArray) { UAMpredBGs.forEach(function(p, i, theArray) {
theArray[i] = round(Math.min(401,Math.max(39,p))); theArray[i] = round(Math.min(401,Math.max(39,p)));
}); });
for (var i=UAMpredBGs.length-1; i > 12; i--) { for (i=UAMpredBGs.length-1; i > 12; i--) {
if (UAMpredBGs[i-1] != UAMpredBGs[i]) { break; } if (UAMpredBGs[i-1] !== UAMpredBGs[i]) { break; }
else { UAMpredBGs.pop(); } else { UAMpredBGs.pop(); }
} }
rT.predBGs.UAM = UAMpredBGs; rT.predBGs.UAM = UAMpredBGs;
@ -666,7 +693,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
} }
// set eventualBG and snoozeBG based on COB or UAM predBGs // set eventualBG based on COB or UAM predBGs
rT.eventualBG = eventualBG; rT.eventualBG = eventualBG;
} }
@ -733,14 +760,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
//console.error("minUAMPredBG:",minUAMPredBG,"minZTGuardBG:",minZTGuardBG,"minZTUAMPredBG:",minZTUAMPredBG); //console.error("minUAMPredBG:",minUAMPredBG,"minZTGuardBG:",minZTGuardBG,"minZTUAMPredBG:",minZTUAMPredBG);
// if any carbs have been entered recently // if any carbs have been entered recently
if (meal_data.carbs) { if (meal_data.carbs) {
// average the minIOBPredBG and minUAMPredBG if available
/*
if ( minUAMPredBG < 999 ) {
avgMinPredBG = round( (minIOBPredBG+minUAMPredBG)/2 );
} else {
avgMinPredBG = minIOBPredBG;
}
*/
// if UAM is disabled, use max of minIOBPredBG, minCOBPredBG // if UAM is disabled, use max of minIOBPredBG, minCOBPredBG
if ( ! enableUAM && minCOBPredBG < 999 ) { if ( ! enableUAM && minCOBPredBG < 999 ) {
@ -748,30 +767,29 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// if we have COB, use minCOBPredBG, or blendedMinPredBG if it's higher // if we have COB, use minCOBPredBG, or blendedMinPredBG if it's higher
} else if ( minCOBPredBG < 999 ) { } else if ( minCOBPredBG < 999 ) {
// calculate blendedMinPredBG based on how many carbs remain as COB // calculate blendedMinPredBG based on how many carbs remain as COB
//blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minUAMPredBG; var blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minZTUAMPredBG;
blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minZTUAMPredBG;
// if blendedMinPredBG > minCOBPredBG, use that instead // if blendedMinPredBG > minCOBPredBG, use that instead
minPredBG = round(Math.max(minIOBPredBG, minCOBPredBG, blendedMinPredBG)); minPredBG = round(Math.max(minIOBPredBG, minCOBPredBG, blendedMinPredBG));
// if carbs have been entered, but have expired, use minUAMPredBG // if carbs have been entered, but have expired, use minUAMPredBG
} else { } else if ( enableUAM ) {
//minPredBG = minUAMPredBG;
minPredBG = minZTUAMPredBG; minPredBG = minZTUAMPredBG;
} else {
minPredBG = minGuardBG;
} }
// in pure UAM mode, use the higher of minIOBPredBG,minUAMPredBG // in pure UAM mode, use the higher of minIOBPredBG,minUAMPredBG
} else if ( enableUAM ) { } else if ( enableUAM ) {
//minPredBG = round(Math.max(minIOBPredBG,minUAMPredBG));
minPredBG = round(Math.max(minIOBPredBG,minZTUAMPredBG)); minPredBG = round(Math.max(minIOBPredBG,minZTUAMPredBG));
} }
// make sure minPredBG isn't higher than avgPredBG // make sure minPredBG isn't higher than avgPredBG
minPredBG = Math.min( minPredBG, avgPredBG ); minPredBG = Math.min( minPredBG, avgPredBG );
console.error("minPredBG: "+minPredBG+" minIOBPredBG: "+minIOBPredBG+" minZTGuardBG: "+minZTGuardBG); console.log("minPredBG: "+minPredBG+" minIOBPredBG: "+minIOBPredBG+" minZTGuardBG: "+minZTGuardBG);
if (minCOBPredBG < 999) { if (minCOBPredBG < 999) {
console.error(" minCOBPredBG: "+minCOBPredBG); console.log(" minCOBPredBG: "+minCOBPredBG);
} }
if (minUAMPredBG < 999) { if (minUAMPredBG < 999) {
console.error(" minUAMPredBG: "+minUAMPredBG); console.log(" minUAMPredBG: "+minUAMPredBG);
} }
console.error(" avgPredBG:",avgPredBG,"COB:",meal_data.mealCOB,"/",meal_data.carbs); console.error(" avgPredBG:",avgPredBG,"COB:",meal_data.mealCOB,"/",meal_data.carbs);
// But if the COB line falls off a cliff, don't trust UAM too much: // But if the COB line falls off a cliff, don't trust UAM too much:
@ -790,9 +808,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rT.reason += ", UAMpredBG " + convert_bg(lastUAMpredBG, profile) rT.reason += ", UAMpredBG " + convert_bg(lastUAMpredBG, profile)
} }
rT.reason += "; "; rT.reason += "; ";
//var bgUndershoot = threshold - Math.min(minGuardBG, Math.max( naive_eventualBG, eventualBG ));
// use naive_eventualBG if above 40, but switch to minGuardBG if both eventualBGs hit floor of 39 // use naive_eventualBG if above 40, but switch to minGuardBG if both eventualBGs hit floor of 39
//var carbsReqBG = Math.max( naive_eventualBG, eventualBG );
var carbsReqBG = naive_eventualBG; var carbsReqBG = naive_eventualBG;
if ( carbsReqBG < 40 ) { if ( carbsReqBG < 40 ) {
carbsReqBG = Math.min( minGuardBG, carbsReqBG ); carbsReqBG = Math.min( minGuardBG, carbsReqBG );
@ -802,14 +818,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var minutesAboveMinBG = 240; var minutesAboveMinBG = 240;
var minutesAboveThreshold = 240; var minutesAboveThreshold = 240;
if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) { if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) {
for (var i=0; i<COBpredBGs.length; i++) { for (i=0; i<COBpredBGs.length; i++) {
//console.error(COBpredBGs[i], min_bg); //console.error(COBpredBGs[i], min_bg);
if ( COBpredBGs[i] < min_bg ) { if ( COBpredBGs[i] < min_bg ) {
minutesAboveMinBG = 5*i; minutesAboveMinBG = 5*i;
break; break;
} }
} }
for (var i=0; i<COBpredBGs.length; i++) { for (i=0; i<COBpredBGs.length; i++) {
//console.error(COBpredBGs[i], threshold); //console.error(COBpredBGs[i], threshold);
if ( COBpredBGs[i] < threshold ) { if ( COBpredBGs[i] < threshold ) {
minutesAboveThreshold = 5*i; minutesAboveThreshold = 5*i;
@ -817,14 +833,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
} }
} else { } else {
for (var i=0; i<IOBpredBGs.length; i++) { for (i=0; i<IOBpredBGs.length; i++) {
//console.error(IOBpredBGs[i], min_bg); //console.error(IOBpredBGs[i], min_bg);
if ( IOBpredBGs[i] < min_bg ) { if ( IOBpredBGs[i] < min_bg ) {
minutesAboveMinBG = 5*i; minutesAboveMinBG = 5*i;
break; break;
} }
} }
for (var i=0; i<IOBpredBGs.length; i++) { for (i=0; i<IOBpredBGs.length; i++) {
//console.error(IOBpredBGs[i], threshold); //console.error(IOBpredBGs[i], threshold);
if ( IOBpredBGs[i] < threshold ) { if ( IOBpredBGs[i] < threshold ) {
minutesAboveThreshold = 5*i; minutesAboveThreshold = 5*i;
@ -848,9 +864,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
if ( minutesAboveThreshold < 240 || minutesAboveMinBG < 60 ) { if ( minutesAboveThreshold < 240 || minutesAboveMinBG < 60 ) {
console.error("BG projected to remain above",convert_bg(threshold,profile),"for",minutesAboveThreshold,"minutes"); console.error("BG projected to remain above",convert_bg(threshold,profile),"for",minutesAboveThreshold,"minutes");
} }
// include at least minutesAboveMinBG worth of zero temps in calculating carbsReq // include at least minutesAboveThreshold worth of zero temps in calculating carbsReq
// always include at least 30m worth of zero temp (carbs to 80, low temp up to target) // always include at least 30m worth of zero temp (carbs to 80, low temp up to target)
//var zeroTempDuration = Math.max(30,minutesAboveMinBG);
var zeroTempDuration = minutesAboveThreshold; var zeroTempDuration = minutesAboveThreshold;
// BG undershoot, minus effect of zero temps until hitting min_bg, converted to grams, minus COB // BG undershoot, minus effect of zero temps until hitting min_bg, converted to grams, minus COB
var zeroTempEffect = profile.current_basal*sens*zeroTempDuration/60; var zeroTempEffect = profile.current_basal*sens*zeroTempDuration/60;
@ -871,7 +886,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// predictive low glucose suspend mode: BG is / is projected to be < threshold // predictive low glucose suspend mode: BG is / is projected to be < threshold
} else if ( bg < threshold || minGuardBG < threshold ) { } else if ( bg < threshold || minGuardBG < threshold ) {
rT.reason += "minGuardBG " + convert_bg(minGuardBG, profile) + "<" + convert_bg(threshold, profile); rT.reason += "minGuardBG " + convert_bg(minGuardBG, profile) + "<" + convert_bg(threshold, profile);
var bgUndershoot = target_bg - minGuardBG; bgUndershoot = target_bg - minGuardBG;
var worstCaseInsulinReq = bgUndershoot / sens; var worstCaseInsulinReq = bgUndershoot / sens;
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal); var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
durationReq = round(durationReq/30)*30; durationReq = round(durationReq/30)*30;
@ -880,6 +895,13 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
return tempBasalFunctions.setTempBasal(0, durationReq, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(0, durationReq, profile, rT, currenttemp);
} }
// if not in LGS mode, cancel temps before the top of the hour to reduce beeping/vibration
// console.error(profile.skip_neutral_temps, rT.deliverAt.getMinutes());
if ( profile.skip_neutral_temps && rT.deliverAt.getMinutes() >= 55 ) {
rT.reason += "; Canceling temp at " + rT.deliverAt.getMinutes() + "m past the hour. ";
return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
}
if (eventualBG < min_bg) { // if eventual BG is below target: if (eventualBG < min_bg) { // if eventual BG is below target:
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " < " + convert_bg(min_bg, profile); rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " < " + convert_bg(min_bg, profile);
// if 5m or 30m avg BG is rising faster than expected delta // if 5m or 30m avg BG is rising faster than expected delta
@ -904,9 +926,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
// calculate 30m low-temp required to get projected BG up to target // calculate 30m low-temp required to get projected BG up to target
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
// multiply by 2 to low-temp faster for increased hypo safety // multiply by 2 to low-temp faster for increased hypo safety
//var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / sens);
var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / sens); var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / sens);
insulinReq = round( insulinReq , 2); insulinReq = round( insulinReq , 2);
// calculate naiveInsulinReq based on naive_eventualBG // calculate naiveInsulinReq based on naive_eventualBG
@ -914,7 +934,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
naiveInsulinReq = round( naiveInsulinReq , 2); naiveInsulinReq = round( naiveInsulinReq , 2);
if (minDelta < 0 && minDelta > expectedDelta) { if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative // if we're barely falling, newinsulinReq should be barely negative
//rT.reason += ", Snooze BG " + convert_bg(snoozeBG, profile);
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2); var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq); //console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq; insulinReq = newinsulinReq;
@ -922,6 +941,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// rate required to deliver insulinReq less insulin over 30m: // rate required to deliver insulinReq less insulin over 30m:
var rate = basal + (2 * insulinReq); var rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile); rate = round_basal(rate, profile);
// if required temp < existing temp basal // if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60; var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
// if current temp would deliver a lot (30% of basal) less than the required insulin, // if current temp would deliver a lot (30% of basal) less than the required insulin,
@ -937,18 +957,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} else { } else {
// calculate a long enough zero temp to eventually correct back up to target // calculate a long enough zero temp to eventually correct back up to target
if ( rate <=0 ) { if ( rate <=0 ) {
var bgUndershoot = target_bg - naive_eventualBG; bgUndershoot = target_bg - naive_eventualBG;
var worstCaseInsulinReq = bgUndershoot / sens; worstCaseInsulinReq = bgUndershoot / sens;
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal); durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
if (durationReq < 0) { if (durationReq < 0) {
durationReq = 0; durationReq = 0;
// don't set an SMB zero temp longer than 60 minutess // don't set a temp longer than 120 minutes
} else { } else {
durationReq = round(durationReq/30)*30; durationReq = round(durationReq/30)*30;
durationReq = Math.min(60,Math.max(0,durationReq)); durationReq = Math.min(120,Math.max(0,durationReq));
} }
//console.error(durationReq); //console.error(durationReq);
//rT.reason += "insulinReq " + insulinReq + "; "
if (durationReq > 0) { if (durationReq > 0) {
rT.reason += ", setting " + durationReq + "m zero temp. "; rT.reason += ", setting " + durationReq + "m zero temp. ";
return tempBasalFunctions.setTempBasal(rate, durationReq, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(rate, durationReq, profile, rT, currenttemp);
@ -995,8 +1014,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// eventual BG is at/above target // eventual BG is at/above target
// if iob is over max, just cancel any temps // if iob is over max, just cancel any temps
// if we're not here because of SMB, eventual BG is at/above target if ( eventualBG >= max_bg ) {
if (! (microBolusAllowed && rT.COB)) {
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", "; rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", ";
} }
if (iob_data.iob > max_iob) { if (iob_data.iob > max_iob) {
@ -1012,15 +1030,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
// insulinReq is the additional insulin required to get minPredBG down to target_bg // insulinReq is the additional insulin required to get minPredBG down to target_bg
//console.error(minPredBG,eventualBG); //console.error(minPredBG,eventualBG);
//var insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2); insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
var insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
// when dropping, but not as fast as expected, reduce insulinReq proportionally
// to the what fraction of expectedDelta we're dropping at
//if (minDelta < 0 && minDelta > expectedDelta) {
//var newinsulinReq = round(( insulinReq * (1 - (minDelta / expectedDelta)) ), 2);
//console.error("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq + " for minDelta " + minDelta + " vs. expectedDelta " + expectedDelta);
//insulinReq = newinsulinReq;
//}
// if that would put us over max_iob, then reduce accordingly // if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-iob_data.iob) { if (insulinReq > max_iob-iob_data.iob) {
rT.reason += "max_iob " + max_iob + ", "; rT.reason += "max_iob " + max_iob + ", ";
@ -1028,49 +1038,56 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
// rate required to deliver insulinReq more insulin over 30m: // rate required to deliver insulinReq more insulin over 30m:
var rate = basal + (2 * insulinReq); rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile); rate = round_basal(rate, profile);
insulinReq = round(insulinReq,3); insulinReq = round(insulinReq,3);
rT.insulinReq = insulinReq; rT.insulinReq = insulinReq;
//console.error(iob_data.lastBolusTime); //console.error(iob_data.lastBolusTime);
// minutes since last bolus // minutes since last bolus
var lastBolusAge = round(( new Date().getTime() - iob_data.lastBolusTime ) / 60000,1); var lastBolusAge = round(( new Date(systemTime).getTime() - iob_data.lastBolusTime ) / 60000,1);
//console.error(lastBolusAge); //console.error(lastBolusAge);
//console.error(profile.temptargetSet, target_bg, rT.COB); //console.error(profile.temptargetSet, target_bg, rT.COB);
// only allow microboluses with COB or low temp targets, or within DIA hours of a bolus // only allow microboluses with COB or low temp targets, or within DIA hours of a bolus
if (microBolusAllowed && enableSMB && bg > threshold) { if (microBolusAllowed && enableSMB && bg > threshold) {
// never bolus more than maxSMBBasalMinutes worth of basal // never bolus more than maxSMBBasalMinutes worth of basal
mealInsulinReq = round( meal_data.mealCOB / profile.carb_ratio ,3); var mealInsulinReq = round( meal_data.mealCOB / profile.carb_ratio ,3);
if (typeof profile.maxSMBBasalMinutes == 'undefined' ) { if (typeof profile.maxSMBBasalMinutes === 'undefined' ) {
maxBolus = round( profile.current_basal * 30 / 60 ,1); var maxBolus = round( profile.current_basal * 30 / 60 ,1);
console.error("profile.maxSMBBasalMinutes undefined: defaulting to 30m"); console.error("profile.maxSMBBasalMinutes undefined: defaulting to 30m");
// if IOB covers more than COB, limit maxBolus to 30m of basal // if IOB covers more than COB, limit maxBolus to 30m of basal
} else if ( iob_data.iob > mealInsulinReq && iob_data.iob > 0 ) { } else if ( iob_data.iob > mealInsulinReq && iob_data.iob > 0 ) {
console.error("IOB",iob_data.iob,"> COB",meal_data.mealCOB+"; mealInsulinReq =",mealInsulinReq); console.error("IOB",iob_data.iob,"> COB",meal_data.mealCOB+"; mealInsulinReq =",mealInsulinReq);
if (profile.maxUAMSMBBasalMinutes) {
console.error("profile.maxUAMSMBBasalMinutes:",profile.maxUAMSMBBasalMinutes,"profile.current_basal:",profile.current_basal);
maxBolus = round( profile.current_basal * profile.maxUAMSMBBasalMinutes / 60 ,1);
} else {
console.error("profile.maxUAMSMBBasalMinutes undefined: defaulting to 30m");
maxBolus = round( profile.current_basal * 30 / 60 ,1); maxBolus = round( profile.current_basal * 30 / 60 ,1);
}
} else { } else {
console.error("profile.maxSMBBasalMinutes:",profile.maxSMBBasalMinutes,"profile.current_basal:",profile.current_basal); console.error("profile.maxSMBBasalMinutes:",profile.maxSMBBasalMinutes,"profile.current_basal:",profile.current_basal);
maxBolus = round( profile.current_basal * profile.maxSMBBasalMinutes / 60 ,1); maxBolus = round( profile.current_basal * profile.maxSMBBasalMinutes / 60 ,1);
} }
// bolus 1/2 the insulinReq, up to maxBolus, rounding down to nearest 0.1U // bolus 1/2 the insulinReq, up to maxBolus, rounding down to nearest bolus increment
microBolus = Math.floor(Math.min(insulinReq/2,maxBolus)*10)/10; var roundSMBTo = 1 / profile.bolus_increment;
var microBolus = Math.floor(Math.min(insulinReq/2,maxBolus)*roundSMBTo)/roundSMBTo;
// calculate a long enough zero temp to eventually correct back up to target // calculate a long enough zero temp to eventually correct back up to target
var smbTarget = target_bg; var smbTarget = target_bg;
var worstCaseInsulinReq = (smbTarget - (naive_eventualBG + minIOBPredBG)/2 ) / sens; worstCaseInsulinReq = (smbTarget - (naive_eventualBG + minIOBPredBG)/2 ) / sens;
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal); durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
// if insulinReq > 0 but not enough for a microBolus, don't set an SMB zero temp // if insulinReq > 0 but not enough for a microBolus, don't set an SMB zero temp
if (insulinReq > 0 && microBolus < 0.1) { if (insulinReq > 0 && microBolus < profile.bolus_increment) {
durationReq = 0; durationReq = 0;
} }
var smbLowTempReq = 0; var smbLowTempReq = 0;
if (durationReq <= 0) { if (durationReq <= 0) {
durationReq = 0; durationReq = 0;
// don't set a temp longer than 120 minutes // don't set an SMB zero temp longer than 60 minutes
} else if (durationReq >= 30) { } else if (durationReq >= 30) {
durationReq = round(durationReq/30)*30; durationReq = round(durationReq/30)*30;
durationReq = Math.min(120,Math.max(0,durationReq)); durationReq = Math.min(60,Math.max(0,durationReq));
} else { } else {
// if SMB durationReq is less than 30m, set a nonzero low temp // if SMB durationReq is less than 30m, set a nonzero low temp
smbLowTempReq = round( basal * durationReq/30 ,2); smbLowTempReq = round( basal * durationReq/30 ,2);
@ -1085,17 +1102,23 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
rT.reason += ". "; rT.reason += ". ";
//allow SMBs every 3 minutes //allow SMBs every 3 minutes by default
var nextBolusMins = round(3-lastBolusAge,1); var SMBInterval = 3;
if (profile.SMBInterval) {
// allow SMBIntervals between 1 and 10 minutes
SMBInterval = Math.min(10,Math.max(1,profile.SMBInterval));
}
var nextBolusMins = round(SMBInterval-lastBolusAge,0);
var nextBolusSeconds = round((SMBInterval - lastBolusAge) * 60, 0) % 60;
//console.error(naive_eventualBG, insulinReq, worstCaseInsulinReq, durationReq); //console.error(naive_eventualBG, insulinReq, worstCaseInsulinReq, durationReq);
console.error("naive_eventualBG",naive_eventualBG+",",durationReq+"m "+smbLowTempReq+"U/h temp needed; last bolus",lastBolusAge+"m ago; maxBolus: "+maxBolus); console.error("naive_eventualBG",naive_eventualBG+",",durationReq+"m "+smbLowTempReq+"U/h temp needed; last bolus",lastBolusAge+"m ago; maxBolus: "+maxBolus);
if (lastBolusAge > 3) { if (lastBolusAge > SMBInterval) {
if (microBolus > 0) { if (microBolus > 0) {
rT.units = microBolus; rT.units = microBolus;
rT.reason += "Microbolusing " + microBolus + "U. "; rT.reason += "Microbolusing " + microBolus + "U. ";
} }
} else { } else {
rT.reason += "Waiting " + nextBolusMins + "m to microbolus again. "; rT.reason += "Waiting " + nextBolusMins + "m " + nextBolusSeconds + "s to microbolus again. ";
} }
//rT.reason += ". "; //rT.reason += ". ";
@ -1106,11 +1129,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
return rT; return rT;
} }
// if insulinReq is negative, snoozeBG > target_bg, and lastCOBpredBG > target_bg, set a neutral temp
//if (insulinReq < 0 && snoozeBG > target_bg && lastCOBpredBG > target_bg) {
//rT.reason += "; SMB bolus snooze: setting current basal of " + basal + " as temp. ";
//return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
//}
} }
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile); var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
@ -1120,13 +1138,13 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rate = round_basal(maxSafeBasal, profile); rate = round_basal(maxSafeBasal, profile);
} }
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60; insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + rate + "U/hr. "; rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + rate + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set if (typeof currenttemp.duration === 'undefined' || currenttemp.duration === 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr. "; rT.reason += "no temp, setting " + rate + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }

View file

@ -18,7 +18,7 @@
<maxHistory>120</maxHistory> <maxHistory>120</maxHistory>
</rollingPolicy> </rollingPolicy>
<encoder> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: [%class{0}.%M\(\):%line]: %msg%n</pattern> <pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>
@ -27,7 +27,7 @@
<pattern>%logger{0}</pattern> <pattern>%logger{0}</pattern>
</tagEncoder> </tagEncoder>
<encoder> <encoder>
<pattern>[%thread] [%class{0}.%M\(\):%line]: %msg%n</pattern> <pattern>[%thread]: %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>

View file

@ -87,4 +87,20 @@ public class Constants {
public static final double STATS_RANGE_HIGH_MMOL = 10.0; public static final double STATS_RANGE_HIGH_MMOL = 10.0;
// One Time Password
/**
* Size of generated key for TOTP Authenticator token, in bits
* rfc6238 suggest at least 160 for SHA1 based TOTP, but it ts too weak
* with 512 generated QRCode to provision authenticator is too detailed
* 256 is chosen as both secure enough and small enough for easy-scannable QRCode
*/
public static final int OTP_GENERATED_KEY_LENGTH_BITS = 256;
/**
* How many old TOTP tokens still accept.
* Each token is 30s valid, but copying and SMS transmision of it can take additional seconds,
* so we add leeway to still accept given amount of older tokens
*/
public static final int OTP_ACCEPT_OLD_TOKENS_COUNT = 1;
} }

View file

@ -1,345 +0,0 @@
package info.nightscout.androidaps;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.tabs.TabLayout;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.activities.PreferencesActivity;
import info.nightscout.androidaps.activities.SingleFragmentActivity;
import info.nightscout.androidaps.activities.StatsActivity;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.androidaps.utils.AndroidPermission;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.PasswordProtection;
import info.nightscout.androidaps.utils.SP;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import static info.nightscout.androidaps.utils.EspressoTestHelperKt.isRunningRealPumpTest;
public class MainActivity extends NoSplashAppCompatActivity {
private static Logger log = LoggerFactory.getLogger(L.CORE);
private CompositeDisposable disposable = new CompositeDisposable();
private ActionBarDrawerToggle actionBarDrawerToggle;
private MenuItem pluginPreferencesMenuItem;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Iconify.with(new FontAwesomeModule());
LocaleHelper.INSTANCE.update(getApplicationContext());
setContentView(R.layout.activity_main);
setSupportActionBar(findViewById(R.id.toolbar));
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.open_navigation, R.string.close_navigation);
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
// initialize screen wake lock
processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
final ViewPager viewPager = findViewById(R.id.pager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
checkPluginPreferences(viewPager);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
//Check here if loop plugin is disabled. Else check via constraints
if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
VersionCheckerUtilsKt.triggerCheckVersion();
FabricPrivacy.setUserStats();
setupTabs();
setupViews();
disposable.add(RxBus.INSTANCE
.toObservable(EventRebuildTabs.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> {
LocaleHelper.INSTANCE.update(getApplicationContext());
if (event.getRecreate()) {
recreate();
} else {
setupTabs();
setupViews();
}
setWakeLock();
}, FabricPrivacy::logException)
);
disposable.add(RxBus.INSTANCE
.toObservable(EventPreferenceChange.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::processPreferenceChange, FabricPrivacy::logException)
);
if (!SP.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) {
Intent intent = new Intent(this, SetupWizardActivity.class);
startActivity(intent);
}
AndroidPermission.notifyForStoragePermission(this);
AndroidPermission.notifyForBatteryOptimizationPermission(this);
if (Config.PUMPDRIVERS) {
AndroidPermission.notifyForLocationPermissions(this);
AndroidPermission.notifyForSMSPermissions(this);
AndroidPermission.notifyForSystemWindowPermissions(this);
}
}
private void checkPluginPreferences(ViewPager viewPager) {
if (pluginPreferencesMenuItem == null) return;
if (((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem()).getPreferencesId() != -1)
pluginPreferencesMenuItem.setEnabled(true);
else pluginPreferencesMenuItem.setEnabled(false);
}
@Override
public void onPostCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
actionBarDrawerToggle.syncState();
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.clear();
}
private void setWakeLock() {
boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false);
if (keepScreenOn)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
else
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
public void processPreferenceChange(final EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_keep_screen_on))
setWakeLock();
}
private void setupViews() {
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
NavigationView navigationView = findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(menuItem -> true);
Menu menu = navigationView.getMenu();
menu.clear();
for (PluginBase p : MainApp.getPluginsList()) {
pageAdapter.registerNewFragment(p);
if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.getType()) && !p.pluginDescription.neverVisible) {
MenuItem menuItem = menu.add(p.getName());
menuItem.setCheckable(true);
menuItem.setOnMenuItemClickListener(item -> {
Intent intent = new Intent(this, SingleFragmentActivity.class);
intent.putExtra("plugin", MainApp.getPluginsList().indexOf(p));
startActivity(intent);
((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawers();
return true;
});
}
}
ViewPager mPager = findViewById(R.id.pager);
mPager.setAdapter(pageAdapter);
//if (switchToLast)
// mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
checkPluginPreferences(mPager);
}
private void setupTabs() {
ViewPager viewPager = findViewById(R.id.pager);
TabLayout normalTabs = findViewById(R.id.tabs_normal);
normalTabs.setupWithViewPager(viewPager, true);
TabLayout compactTabs = findViewById(R.id.tabs_compact);
compactTabs.setupWithViewPager(viewPager, true);
Toolbar toolbar = findViewById(R.id.toolbar);
if (SP.getBoolean("short_tabtitles", false)) {
normalTabs.setVisibility(View.GONE);
compactTabs.setVisibility(View.VISIBLE);
toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.compact_height)));
} else {
normalTabs.setVisibility(View.VISIBLE);
compactTabs.setVisibility(View.GONE);
TypedValue typedValue = new TypedValue();
if (getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
TypedValue.complexToDimensionPixelSize(typedValue.data, getResources().getDisplayMetrics())));
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length != 0) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) {
case AndroidPermission.CASE_STORAGE:
//show dialog after permission is granted
OKDialog.show(this, "", MainApp.gs(R.string.alert_dialog_storage_permission_text));
break;
case AndroidPermission.CASE_LOCATION:
case AndroidPermission.CASE_SMS:
case AndroidPermission.CASE_BATTERY:
case AndroidPermission.CASE_PHONE_STATE:
case AndroidPermission.CASE_SYSTEM_WINDOW:
break;
}
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (v instanceof EditText) {
Rect outRect = new Rect();
v.getGlobalVisibleRect(outRect);
if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
v.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
return super.dispatchTouchEvent(event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences);
checkPluginPreferences(findViewById(R.id.pager));
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_preferences:
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(this, PreferencesActivity.class);
i.putExtra("id", -1);
startActivity(i);
}, null);
return true;
case R.id.nav_historybrowser:
startActivity(new Intent(this, HistoryBrowseActivity.class));
return true;
case R.id.nav_setupwizard:
startActivity(new Intent(this, SetupWizardActivity.class));
return true;
case R.id.nav_about:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION);
builder.setIcon(MainApp.getIcon());
String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + NSSettingsStatus.getInstance().nightscoutVersionName;
if (MainApp.engineeringMode)
message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
message += MainApp.gs(R.string.about_link_urls);
final SpannableString messageSpanned = new SpannableString(message);
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
builder.setMessage(messageSpanned);
builder.setPositiveButton(MainApp.gs(R.string.ok), null);
AlertDialog alertDialog = builder.create();
alertDialog.show();
((TextView) alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
return true;
case R.id.nav_exit:
log.debug("Exiting");
RxBus.INSTANCE.send(new EventAppExit());
finish();
System.runFinalization();
System.exit(0);
return true;
case R.id.nav_plugin_preferences:
ViewPager viewPager = findViewById(R.id.pager);
final PluginBase plugin = ((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem());
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(this, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
startActivity(i);
}, null);
return true;
/*
case R.id.nav_survey:
startActivity(new Intent(this, SurveyActivity.class));
return true;
*/
case R.id.nav_stats:
startActivity(new Intent(this, StatsActivity.class));
return true;
}
return actionBarDrawerToggle.onOptionsItemSelected(item);
}
}

View file

@ -0,0 +1,339 @@
package info.nightscout.androidaps
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.Bundle
import android.os.PersistableBundle
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.viewpager.widget.ViewPager
import com.google.android.material.navigation.NavigationView
import com.google.android.material.tabs.TabLayout
import com.joanzapata.iconify.Iconify
import com.joanzapata.iconify.fonts.FontAwesomeModule
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.activities.SingleFragmentActivity
import info.nightscout.androidaps.activities.StatsActivity
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
import info.nightscout.androidaps.tabs.TabPageAdapter
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.LocaleHelper.update
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.activity_main.*
import javax.inject.Inject
import kotlin.system.exitProcess
class MainActivity : NoSplashAppCompatActivity() {
private val disposable = CompositeDisposable()
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var androidPermission: AndroidPermission
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var nsSettingsStatus: NSSettingsStatus
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var protectionCheck: ProtectionCheck
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
private var pluginPreferencesMenuItem: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Iconify.with(FontAwesomeModule())
update(applicationContext)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeButtonEnabled(true)
actionBarDrawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.open_navigation, R.string.close_navigation).also {
drawer_layout.addDrawerListener(it)
it.syncState()
}
// initialize screen wake lock
processPreferenceChange(EventPreferenceChange(resourceHelper.gs(R.string.key_keep_screen_on)))
pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
checkPluginPreferences(pager)
}
override fun onPageScrollStateChanged(state: Int) {}
})
//Check here if loop plugin is disabled. Else check via constraints
if (!loopPlugin.isEnabled(PluginType.LOOP)) versionCheckerUtils.triggerCheckVersion()
fabricPrivacy.setUserStats()
setupTabs()
setupViews()
disposable.add(rxBus
.toObservable(EventRebuildTabs::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
update(applicationContext)
if (it.recreate) recreate()
else {
setupTabs()
setupViews()
}
setWakeLock()
}) { fabricPrivacy.logException(it) }
)
disposable.add(rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ processPreferenceChange(it) }) { fabricPrivacy.logException(it) }
)
if (!sp.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) {
val intent = Intent(this, SetupWizardActivity::class.java)
startActivity(intent)
}
androidPermission.notifyForStoragePermission(this)
androidPermission.notifyForBatteryOptimizationPermission(this)
if (Config.PUMPDRIVERS) {
androidPermission.notifyForLocationPermissions(this)
androidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin)
androidPermission.notifyForSystemWindowPermissions(this)
}
}
private fun checkPluginPreferences(viewPager: ViewPager) {
pluginPreferencesMenuItem?.isEnabled = (viewPager.adapter as TabPageAdapter).getPluginAt(viewPager.currentItem).preferencesId != -1
}
override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onPostCreate(savedInstanceState, persistentState)
actionBarDrawerToggle.syncState()
}
public override fun onDestroy() {
super.onDestroy()
disposable.clear()
}
override fun onResume() {
super.onResume()
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null,
Runnable {
OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() })
},
Runnable {
OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() })
})
}
private fun setWakeLock() {
val keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false)
if (keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private fun processPreferenceChange(ev: EventPreferenceChange) {
if (ev.isChanged(resourceHelper, R.string.key_keep_screen_on)) setWakeLock()
}
private fun setupViews() {
val pageAdapter = TabPageAdapter(supportFragmentManager, this)
val navigationView = findViewById<NavigationView>(R.id.navigation_view)
navigationView.setNavigationItemSelectedListener { true }
val menu = navigationView.menu.also { it.clear() }
for (p in activePlugin.pluginsList) {
pageAdapter.registerNewFragment(p)
if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.type) && !p.pluginDescription.neverVisible) {
val menuItem = menu.add(p.name)
menuItem.isCheckable = true
menuItem.setOnMenuItemClickListener {
val intent = Intent(this, SingleFragmentActivity::class.java)
intent.putExtra("plugin", activePlugin.pluginsList.indexOf(p))
startActivity(intent)
(findViewById<View>(R.id.drawer_layout) as DrawerLayout).closeDrawers()
true
}
}
}
val mPager = findViewById<ViewPager>(R.id.pager)
mPager.adapter = pageAdapter
//if (switchToLast)
// mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
checkPluginPreferences(mPager)
}
private fun setupTabs() {
val viewPager = findViewById<ViewPager>(R.id.pager)
val normalTabs = findViewById<TabLayout>(R.id.tabs_normal)
normalTabs.setupWithViewPager(viewPager, true)
val compactTabs = findViewById<TabLayout>(R.id.tabs_compact)
compactTabs.setupWithViewPager(viewPager, true)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
if (sp.getBoolean(R.string.key_short_tabtitles, false)) {
normalTabs.visibility = View.GONE
compactTabs.visibility = View.VISIBLE
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, resources.getDimension(R.dimen.compact_height).toInt())
} else {
normalTabs.visibility = View.VISIBLE
compactTabs.visibility = View.GONE
val typedValue = TypedValue()
if (theme.resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
TypedValue.complexToDimensionPixelSize(typedValue.data, resources.displayMetrics))
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (permissions.isNotEmpty()) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
when (requestCode) {
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> {
}
}
}
}
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
val v = currentFocus
if (v is EditText) {
val outRect = Rect()
v.getGlobalVisibleRect(outRect)
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
v.clearFocus()
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
}
}
}
return super.dispatchTouchEvent(event)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
checkPluginPreferences(findViewById(R.id.pager))
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.nav_preferences -> {
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(this, PreferencesActivity::class.java)
i.putExtra("id", -1)
startActivity(i)
})
return true
}
R.id.nav_historybrowser -> {
startActivity(Intent(this, HistoryBrowseActivity::class.java))
return true
}
R.id.nav_setupwizard -> {
startActivity(Intent(this, SetupWizardActivity::class.java))
return true
}
R.id.nav_about -> {
var message = "Build: ${BuildConfig.BUILDVERSION}\n"
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.nightscoutVersionName}"
if (buildHelper.isEngineeringMode()) message += "\n${resourceHelper.gs(R.string.engineering_mode_enabled)}"
message += resourceHelper.gs(R.string.about_link_urls)
val messageSpanned = SpannableString(message)
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
AlertDialog.Builder(this)
.setTitle(resourceHelper.gs(R.string.app_name) + " " + BuildConfig.VERSION)
.setIcon(resourceHelper.getIcon())
.setMessage(messageSpanned)
.setPositiveButton(resourceHelper.gs(R.string.ok), null)
.create().also {
it.show()
(it.findViewById<View>(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance()
}
return true
}
R.id.nav_exit -> {
aapsLogger.debug(LTag.CORE, "Exiting")
rxBus.send(EventAppExit())
finish()
System.runFinalization()
exitProcess(0)
}
R.id.nav_plugin_preferences -> {
val viewPager = findViewById<ViewPager>(R.id.pager)
val plugin = (viewPager.adapter as TabPageAdapter).getPluginAt(viewPager.currentItem)
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(this, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
startActivity(i)
})
return true
}
/*
R.id.nav_survey -> {
startActivity(Intent(this, SurveyActivity::class.java))
return true
}
*/
R.id.nav_stats -> {
startActivity(Intent(this, StatsActivity::class.java))
return true
}
}
return actionBarDrawerToggle.onOptionsItemSelected(item)
}
}

View file

@ -1,16 +1,20 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.app.Application; import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.SystemClock;
import androidx.annotation.ColorRes; import androidx.annotation.ColorRes;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.TaskStackBuilder;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -21,118 +25,77 @@ import com.j256.ormlite.android.apptools.OpenHelperManager;
import net.danlew.android.joda.JodaTimeAndroid; import net.danlew.android.joda.JodaTimeAndroid;
import org.json.JSONException; import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.util.List;
import java.util.ArrayList;
import info.nightscout.androidaps.data.ConstraintChecker; import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin;
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin;
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin;
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin;
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; import info.nightscout.androidaps.receivers.BTReceiver;
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.source.RandomBgPlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.source.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.source.SourcePoctechPlugin;
import info.nightscout.androidaps.plugins.source.SourceTomatoPlugin;
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.receivers.ChargingStateReceiver; import info.nightscout.androidaps.receivers.ChargingStateReceiver;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver; import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
import info.nightscout.androidaps.receivers.NetworkChangeReceiver; import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
import info.nightscout.androidaps.receivers.ReceiverStatusStore;
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver; import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.ActivityMonitor; import info.nightscout.androidaps.utils.ActivityMonitor;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.LocaleHelper; import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.fabric.sdk.android.Fabric; import io.fabric.sdk.android.Fabric;
import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion; public class MainApp extends DaggerApplication {
static MainApp sInstance;
private static Resources sResources;
public class MainApp extends Application { static FirebaseAnalytics firebaseAnalytics;
private static Logger log = LoggerFactory.getLogger(L.CORE);
private static MainApp sInstance; static DatabaseHelper sDatabaseHelper = null;
public static Resources sResources;
private static FirebaseAnalytics mFirebaseAnalytics; private String CHANNEL_ID = "AndroidAPS-Ongoing"; // TODO: move to OngoingNotificationProvider (and dagger)
private int ONGOING_NOTIFICATION_ID = 4711; // TODO: move to OngoingNotificationProvider (and dagger)
private Notification notification; // TODO: move to OngoingNotificationProvider (and dagger)
private static DatabaseHelper sDatabaseHelper = null; @Inject PluginStore pluginStore;
private static ConstraintChecker sConstraintsChecker = null; @Inject public HasAndroidInjector injector;
@Inject AAPSLogger aapsLogger;
@Inject ReceiverStatusStore receiverStatusStore;
@Inject ActivityMonitor activityMonitor;
@Inject FabricPrivacy fabricPrivacy;
@Inject ResourceHelper resourceHelper;
@Inject VersionCheckerUtils versionCheckersUtils;
@Inject SP sp;
@Inject ProfileFunction profileFunction;
private static ArrayList<PluginBase> pluginsList = null; @Inject ConfigBuilderPlugin configBuilderPlugin;
@Inject KeepAliveReceiver.KeepAliveManager keepAliveManager;
private static DataReceiver dataReceiver = new DataReceiver(); @Inject List<PluginBase> plugins;
private static NSAlarmReceiver alarmReceiver = new NSAlarmReceiver();
TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
public static boolean devBranch;
public static boolean engineeringMode;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
log.debug("onCreate");
aapsLogger.debug("onCreate");
sInstance = this; sInstance = this;
sResources = getResources(); sResources = getResources();
LocaleHelper.INSTANCE.update(this); LocaleHelper.INSTANCE.update(this);
sConstraintsChecker = new ConstraintChecker(); generateEmptyNotification();
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class); sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> { Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
@ -140,192 +103,131 @@ public class MainApp extends Application {
// usually the app trying to spawn a thread while being killed // usually the app trying to spawn a thread while being killed
return; return;
} }
aapsLogger.error("Uncaught exception crashing app", ex);
log.error("Uncaught exception crashing app", ex);
}); });
try { try {
if (FabricPrivacy.fabricEnabled()) { if (fabricPrivacy.fabricEnabled()) {
Fabric.with(this, new Crashlytics()); Fabric.with(this, new Crashlytics());
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Error with Fabric init! " + e); aapsLogger.error("Error with Fabric init! " + e);
} }
registerActivityLifecycleCallbacks(ActivityMonitor.INSTANCE); registerActivityLifecycleCallbacks(activityMonitor);
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); firebaseAnalytics = FirebaseAnalytics.getInstance(this);
mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase")); firebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase") && fabricPrivacy.fabricEnabled());
JodaTimeAndroid.init(this); JodaTimeAndroid.init(this);
log.info("Version: " + BuildConfig.VERSION_NAME); aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION); aapsLogger.debug("BuildVersion: " + BuildConfig.BUILDVERSION);
log.info("Remote: " + BuildConfig.REMOTE); aapsLogger.debug("Remote: " + BuildConfig.REMOTE);
String extFilesDir = LoggerUtils.getLogDirectory();
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*");
registerLocalBroadcastReceiver(); registerLocalBroadcastReceiver();
//trigger here to see the new version on app start after an update //trigger here to see the new version on app start after an update
triggerCheckVersion(); versionCheckersUtils.triggerCheckVersion();
if (pluginsList == null) {
pluginsList = new ArrayList<>();
// Register all tabs in app here // Register all tabs in app here
pluginsList.add(OverviewPlugin.INSTANCE); pluginStore.setPlugins(plugins);
pluginsList.add(IobCobCalculatorPlugin.getPlugin()); configBuilderPlugin.initialize();
if (!Config.NSCLIENT) pluginsList.add(ActionsPlugin.INSTANCE);
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin());
pluginsList.add(SensitivityOref0Plugin.getPlugin());
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
pluginsList.add(SensitivityOref1Plugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(MedtronicPumpPlugin.getPlugin());
if (Config.PUMPDRIVERS && engineeringMode)
pluginsList.add(OmnipodPumpPlugin.getPlugin());
if (!Config.NSCLIENT) pluginsList.add(MDIPlugin.getPlugin());
pluginsList.add(VirtualPumpPlugin.getPlugin());
if (Config.NSCLIENT) pluginsList.add(CareportalPlugin.getPlugin());
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
pluginsList.add(NSProfilePlugin.getPlugin());
if (!Config.NSCLIENT) pluginsList.add(LocalProfilePlugin.INSTANCE);
pluginsList.add(TreatmentsPlugin.getPlugin());
if (!Config.NSCLIENT) pluginsList.add(SafetyPlugin.getPlugin());
if (!Config.NSCLIENT) pluginsList.add(VersionCheckerPlugin.INSTANCE);
if (Config.APS) pluginsList.add(StorageConstraintPlugin.getPlugin());
if (Config.APS) pluginsList.add(SignatureVerifierPlugin.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE);
pluginsList.add(SourceXdripPlugin.getPlugin());
pluginsList.add(SourceNSClientPlugin.getPlugin());
pluginsList.add(SourceMM640gPlugin.getPlugin());
pluginsList.add(SourceGlimpPlugin.getPlugin());
pluginsList.add(SourceDexcomPlugin.INSTANCE);
pluginsList.add(SourcePoctechPlugin.getPlugin());
pluginsList.add(SourceTomatoPlugin.getPlugin());
pluginsList.add(SourceEversensePlugin.getPlugin());
pluginsList.add(RandomBgPlugin.INSTANCE);
if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.INSTANCE);
pluginsList.add(FoodPlugin.getPlugin());
pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this));
pluginsList.add(PersistentNotificationPlugin.getPlugin());
pluginsList.add(NSClientPlugin.getPlugin());
// if (engineeringMode) pluginsList.add(TidepoolPlugin.INSTANCE);
pluginsList.add(MaintenancePlugin.initPlugin(this));
pluginsList.add(AutomationPlugin.INSTANCE);
pluginsList.add(ConfigBuilderPlugin.getPlugin());
pluginsList.add(DstHelperPlugin.getPlugin());
ConfigBuilderPlugin.getPlugin().initialize();
}
NSUpload.uploadAppStart(); NSUpload.uploadAppStart();
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); new Thread(() -> keepAliveManager.setAlarm(this)).start();
if (pump != null) {
new Thread(() -> {
SystemClock.sleep(5000);
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Initialization", null);
}).start();
}
new Thread(() -> KeepAliveReceiver.setAlarm(this)).start();
doMigrations(); doMigrations();
} }
private void doMigrations() { private void doMigrations() {
// guarantee that the unreachable threshold is at least 30 and of type String // guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018 // Added in 1.57 at 21.01.2018
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30); int unreachable_threshold = sp.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold); sp.remove(R.string.key_pump_unreachable_threshold);
if (unreachable_threshold < 30) unreachable_threshold = 30; if (unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold)); sp.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
// 2.5 -> 2.6 // 2.5 -> 2.6
if (!SP.contains(R.string.key_units)) { if (!sp.contains(R.string.key_units)) {
String newUnits = Constants.MGDL; String newUnits = Constants.MGDL;
Profile p = ProfileFunctions.getInstance().getProfile(); Profile p = profileFunction.getProfile();
if (p != null && p.getData() != null && p.getData().has("units")) { if (p != null && p.getData() != null && p.getData().has("units")) {
try { try {
newUnits = p.getData().getString("units"); newUnits = p.getData().getString("units");
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
} }
SP.putString(R.string.key_units, newUnits); sp.putString(R.string.key_units, newUnits);
} }
} }
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent
.builder()
.application(this)
.build();
}
private void registerLocalBroadcastReceiver() { private void registerLocalBroadcastReceiver() {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); IntentFilter filter = new IntentFilter();
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); filter.addAction(Intents.ACTION_NEW_TREATMENT);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); filter.addAction(Intents.ACTION_CHANGED_TREATMENT);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); filter.addAction(Intents.ACTION_REMOVED_TREATMENT);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD)); filter.addAction(Intents.ACTION_NEW_SGV);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD)); filter.addAction(Intents.ACTION_NEW_PROFILE);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD)); filter.addAction(Intents.ACTION_NEW_MBG);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); filter.addAction(Intents.ACTION_NEW_CAL);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); LocalBroadcastManager.getInstance(this).registerReceiver(new DataReceiver(), filter);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_MBG));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_DEVICESTATUS));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_CAL));
//register alarms filter = new IntentFilter();
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ALARM)); filter.addAction(Intent.ACTION_TIME_CHANGED);
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ANNOUNCEMENT)); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_CLEAR_ALARM)); registerReceiver(new TimeDateOrTZChangeReceiver(), filter);
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_URGENT_ALARM));
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver(); filter = new IntentFilter();
this.timeDateOrTZChangeReceiver.registerBroadcasts(this); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(new NetworkChangeReceiver(), filter);
IntentFilter intentFilter = new IntentFilter(); filter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_POWER_CONNECTED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION ); filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(new NetworkChangeReceiver(), intentFilter); registerReceiver(new ChargingStateReceiver(), filter);
registerReceiver(new ChargingStateReceiver(), new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(new BTReceiver(), filter);
} }
@Deprecated
public static String gs(@StringRes int id) { public static String gs(@StringRes int id) {
return sResources.getString(id); return sResources.getString(id);
} }
@Deprecated
public static String gs(@StringRes int id, Object... args) { public static String gs(@StringRes int id, Object... args) {
return sResources.getString(id, args); return sResources.getString(id, args);
} }
public static String gq(@PluralsRes int id, int quantity, Object... args) { @Deprecated
return sResources.getQuantityString(id, quantity, args);
}
public static int gc(@ColorRes int id) { public static int gc(@ColorRes int id) {
return ContextCompat.getColor(instance(), id); return ContextCompat.getColor(instance(), id);
} }
@Deprecated
public static Resources resources() {
return sResources;
}
@Deprecated
public static MainApp instance() { public static MainApp instance() {
return sInstance; return sInstance;
} }
@ -334,118 +236,51 @@ public class MainApp extends Application {
return sDatabaseHelper; return sDatabaseHelper;
} }
public static FirebaseAnalytics getFirebaseAnalytics() { public FirebaseAnalytics getFirebaseAnalytics() {
return mFirebaseAnalytics; return firebaseAnalytics;
} }
public static ConstraintChecker getConstraintChecker() { // global Notification has been moved to MainApp because PersistentNotificationPlugin is initialized too late
return sConstraintsChecker; private void generateEmptyNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setOngoing(true)
.setOnlyAlertOnce(true)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.setSmallIcon(resourceHelper.getNotificationIcon())
.setLargeIcon(resourceHelper.decodeResource(resourceHelper.getIcon()));
builder.setContentTitle(resourceHelper.gs(R.string.loading));
Intent resultIntent = new Intent(this, MainApp.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notification = builder.build();
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
} }
public static ArrayList<PluginBase> getPluginsList() { public int notificationId() {
return pluginsList; return ONGOING_NOTIFICATION_ID;
} }
public static ArrayList<PluginBase> getSpecificPluginsList(PluginType type) { public String channelId() {
ArrayList<PluginBase> newList = new ArrayList<>(); return CHANNEL_ID;
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getType() == type)
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
} }
public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(PluginType type) { public void setNotification(Notification notification) {
ArrayList<PluginBase> newList = new ArrayList<>(); this.notification = notification;
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getType() == type)
if (p.showInList(type))
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
} }
public static ArrayList<PluginBase> getSpecificPluginsListByInterface(Class interfaceClass) { public Notification getNotification() {
ArrayList<PluginBase> newList = new ArrayList<>(); return notification;
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
}
public static ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, PluginType type) {
ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
if (p.showInList(type))
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
}
public static boolean isEngineeringModeOrRelease() {
if (!Config.APS)
return true;
return engineeringMode || !devBranch;
}
public static boolean isDev() {
return devBranch;
}
public static int getIcon() {
if (Config.NSCLIENT)
return R.mipmap.ic_yellowowl;
else if (Config.PUMPCONTROL)
return R.mipmap.ic_pumpcontrol;
else
return R.mipmap.ic_launcher;
}
public static int getNotificationIcon() {
if (Config.NSCLIENT)
return R.drawable.ic_notif_nsclient;
else if (Config.PUMPCONTROL)
return R.drawable.ic_notif_pumpcontrol;
else
return R.drawable.ic_notif_aaps;
} }
@Override @Override
public void onTerminate() { public void onTerminate() {
if (L.isEnabled(L.CORE)) aapsLogger.debug(LTag.CORE, "onTerminate");
log.debug("onTerminate"); unregisterActivityLifecycleCallbacks(activityMonitor);
keepAliveManager.cancelAlarm(this);
if (timeDateOrTZChangeReceiver != null)
unregisterReceiver(timeDateOrTZChangeReceiver);
unregisterActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
KeepAliveReceiver.cancelAlarm(this);
super.onTerminate(); super.onTerminate();
} }
public static int dpToPx(int dp) {
float scale = sResources.getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
} }

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.activities package info.nightscout.androidaps.activities
import android.content.Context import android.content.Context
import androidx.appcompat.app.AppCompatActivity import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.utils.LocaleHelper import info.nightscout.androidaps.utils.LocaleHelper
open class DialogAppCompatActivity : AppCompatActivity() { open class DialogAppCompatActivity : DaggerAppCompatActivity() {
public override fun attachBaseContext(newBase: Context) { public override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.wrap(newBase)) super.attachBaseContext(LocaleHelper.wrap(newBase))
} }

View file

@ -4,9 +4,11 @@ import android.os.Bundle
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.ErrorDialog import info.nightscout.androidaps.dialogs.ErrorDialog
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class ErrorHelperActivity : DialogAppCompatActivity() { class ErrorHelperActivity : DialogAppCompatActivity() {
@Inject lateinit var sp : SP
@Override @Override
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -16,11 +18,11 @@ class ErrorHelperActivity : DialogAppCompatActivity() {
errorDialog.status = intent.getStringExtra("status") errorDialog.status = intent.getStringExtra("status")
errorDialog.sound = intent.getIntExtra("soundid", R.raw.error) errorDialog.sound = intent.getIntExtra("soundid", R.raw.error)
errorDialog.title = intent.getStringExtra("title") errorDialog.title = intent.getStringExtra("title")
if (intent.hasExtra("clipboardContent")) //if (intent.hasExtra("clipboardContent"))
errorDialog.clipboardContent = intent.getStringExtra("clipboardContent") // errorDialog.clipboardContent = intent.getStringExtra("clipboardContent")
errorDialog.show(supportFragmentManager, "Error") errorDialog.show(supportFragmentManager, "Error")
if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
NSUpload.uploadError(intent.getStringExtra("status")) NSUpload.uploadError(intent.getStringExtra("status"))
} }
} }

View file

@ -0,0 +1,349 @@
package info.nightscout.androidaps.activities
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.os.Bundle
import androidx.annotation.XmlRes
import androidx.preference.*
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import dagger.android.support.AndroidSupportInjection
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.source.DexcomPlugin
import info.nightscout.androidaps.plugins.source.EversensePlugin
import info.nightscout.androidaps.plugins.source.GlimpPlugin
import info.nightscout.androidaps.plugins.source.PoctechPlugin
import info.nightscout.androidaps.plugins.source.TomatoPlugin
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListener, HasAndroidInjector {
private var pluginId = -1
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var sp: SP
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var pluginStore: PluginStore
@Inject lateinit var automationPlugin: AutomationPlugin
@Inject lateinit var danaRPlugin: DanaRPlugin
@Inject lateinit var danaRKoreanPlugin: DanaRKoreanPlugin
@Inject lateinit var danaRv2Plugin: DanaRv2Plugin
@Inject lateinit var danaRSPlugin: DanaRSPlugin
@Inject lateinit var careportalPlugin: CareportalPlugin
@Inject lateinit var comboPlugin: ComboPlugin
@Inject lateinit var insulinOrefFreePeakPlugin: InsulinOrefFreePeakPlugin
@Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var localInsightPlugin: LocalInsightPlugin
@Inject lateinit var medtronicPumpPlugin: MedtronicPumpPlugin
@Inject lateinit var omnipodPumpPlugin: OmnipodPumpPlugin
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
@Inject lateinit var safetyPlugin: SafetyPlugin
@Inject lateinit var sensitivityAAPSPlugin: SensitivityAAPSPlugin
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
@Inject lateinit var sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin
@Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var eversensePlugin: EversensePlugin
@Inject lateinit var glimpPlugin: GlimpPlugin
@Inject lateinit var poctechPlugin: PoctechPlugin
@Inject lateinit var tomatoPlugin: TomatoPlugin
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var statusLinePlugin: StatusLinePlugin
@Inject lateinit var tidepoolPlugin: TidepoolPlugin
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
@Inject lateinit var wearPlugin: WearPlugin
@Inject lateinit var maintenancePlugin: MaintenancePlugin
@Inject lateinit var passwordCheck: PasswordCheck
@Inject lateinit var androidInjector: DispatchingAndroidInjector<Any>
override fun androidInjector(): AndroidInjector<Any> = androidInjector
override fun onAttach(context: Context) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}
override fun setArguments(args: Bundle?) {
super.setArguments(args)
pluginId = args?.getInt("id") ?: -1
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("id", pluginId)
}
override fun onDestroy() {
super.onDestroy()
PreferenceManager
.getDefaultSharedPreferences(context)
.unregisterOnSharedPreferenceChangeListener(this)
}
private fun addPreferencesFromResourceIfEnabled(p: PluginBase?, rootKey: String?, enabled: Boolean) {
if (enabled) addPreferencesFromResourceIfEnabled(p, rootKey)
}
private fun addPreferencesFromResourceIfEnabled(p: PluginBase?, rootKey: String?) {
if (p!!.isEnabled() && p.preferencesId != -1)
addPreferencesFromResource(p.preferencesId, rootKey)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PreferenceManager
.getDefaultSharedPreferences(context)
.registerOnSharedPreferenceChangeListener(this)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
(savedInstanceState ?: arguments)?.let { bundle ->
if (bundle.containsKey("id")) {
pluginId = bundle.getInt("id")
}
}
if (pluginId != -1) {
addPreferencesFromResource(pluginId, rootKey)
} else {
addPreferencesFromResource(R.xml.pref_general, rootKey)
addPreferencesFromResource(R.xml.pref_overview, rootKey)
addPreferencesFromResourceIfEnabled(safetyPlugin, rootKey)
addPreferencesFromResourceIfEnabled(eversensePlugin, rootKey)
addPreferencesFromResourceIfEnabled(dexcomPlugin, rootKey)
addPreferencesFromResourceIfEnabled(tomatoPlugin, rootKey)
addPreferencesFromResourceIfEnabled(poctechPlugin, rootKey)
addPreferencesFromResourceIfEnabled(glimpPlugin, rootKey)
addPreferencesFromResourceIfEnabled(careportalPlugin, rootKey)
addPreferencesFromResourceIfEnabled(loopPlugin, rootKey, Config.APS)
addPreferencesFromResourceIfEnabled(openAPSAMAPlugin, rootKey, Config.APS)
addPreferencesFromResourceIfEnabled(openAPSSMBPlugin, rootKey, Config.APS)
addPreferencesFromResourceIfEnabled(sensitivityAAPSPlugin, rootKey)
addPreferencesFromResourceIfEnabled(sensitivityWeightedAveragePlugin, rootKey)
addPreferencesFromResourceIfEnabled(sensitivityOref1Plugin, rootKey)
addPreferencesFromResourceIfEnabled(danaRPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(danaRKoreanPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(danaRv2Plugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(danaRSPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(localInsightPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(comboPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(omnipodPumpPlugin, rootKey, Config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey, !Config.NSCLIENT)
addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey)
addPreferencesFromResourceIfEnabled(nsClientPlugin, rootKey)
addPreferencesFromResourceIfEnabled(tidepoolPlugin, rootKey)
addPreferencesFromResourceIfEnabled(smsCommunicatorPlugin, rootKey)
addPreferencesFromResourceIfEnabled(automationPlugin, rootKey)
addPreferencesFromResourceIfEnabled(wearPlugin, rootKey)
addPreferencesFromResourceIfEnabled(statusLinePlugin, rootKey)
addPreferencesFromResource(R.xml.pref_alerts, rootKey) // TODO not organized well
addPreferencesFromResource(R.xml.pref_datachoices, rootKey)
addPreferencesFromResourceIfEnabled(maintenancePlugin, rootKey)
}
initSummary(preferenceScreen, pluginId != -1)
for (plugin in pluginStore.plugins) {
plugin.preprocessPreferences(this)
}
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
rxBus.send(EventPreferenceChange(key))
if (key == resourceHelper.gs(R.string.key_language)) {
rxBus.send(EventRebuildTabs(true))
//recreate() does not update language so better close settings
activity?.finish()
}
if (key == resourceHelper.gs(R.string.key_short_tabtitles)) {
rxBus.send(EventRebuildTabs())
}
if (key == resourceHelper.gs(R.string.key_units)) {
activity?.recreate()
return
}
if (key == resourceHelper.gs(R.string.key_openapsama_useautosens) && sp.getBoolean(R.string.key_openapsama_useautosens, false))
activity?.let {
show(it, resourceHelper.gs(R.string.configbuilder_sensitivity), resourceHelper.gs(R.string.sensitivity_warning))
}
updatePrefSummary(findPreference(key))
}
@SuppressLint("RestrictedApi")
private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) {
val xmlRoot = preferenceManager.inflateFromResource(context,
preferencesResId, null)
val root: Preference?
if (key != null) {
root = xmlRoot.findPreference(key)
if (root == null) return
require(root is PreferenceScreen) {
("Preference object with key " + key
+ " is not a PreferenceScreen")
}
preferenceScreen = root
} else {
addPreferencesFromResource(preferencesResId)
}
}
private fun adjustUnitDependentPrefs(pref: Preference) { // convert preferences values to current units
val unitDependent = arrayOf(
resourceHelper.gs(R.string.key_hypo_target),
resourceHelper.gs(R.string.key_activity_target),
resourceHelper.gs(R.string.key_eatingsoon_target),
resourceHelper.gs(R.string.key_high_mark),
resourceHelper.gs(R.string.key_low_mark)
)
if (listOf(*unitDependent).contains(pref.key)) {
val editTextPref = pref as EditTextPreference
val converted = Profile.toCurrentUnitsString(profileFunction, SafeParse.stringToDouble(editTextPref.text))
editTextPref.summary = converted
editTextPref.text = converted
}
}
private fun updatePrefSummary(pref: Preference?) {
if (pref is ListPreference) {
pref.setSummary(pref.entry)
// Preferences
// Preferences
if (pref.getKey() == resourceHelper.gs(R.string.key_settings_protection)) {
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_settings_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
}
// Application
// Application
if (pref.getKey() == resourceHelper.gs(R.string.key_application_protection)) {
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_application_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
}
// Bolus
// Bolus
if (pref.getKey() == resourceHelper.gs(R.string.key_bolus_protection)) {
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_bolus_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
}
}
if (pref is EditTextPreference) {
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******")
} else if (pref.text != null) {
pref.dialogMessage = pref.dialogMessage
pref.setSummary(pref.text)
} else {
for (plugin in pluginStore.plugins) {
plugin.updatePreferenceSummary(pref)
}
}
}
val hmacPasswords = arrayOf(
resourceHelper.gs(R.string.key_bolus_password),
resourceHelper.gs(R.string.key_master_password),
resourceHelper.gs(R.string.key_application_password),
resourceHelper.gs(R.string.key_settings_password)
)
if (pref is Preference) {
if ((pref.key != null) && (hmacPasswords.contains(pref.key))) {
if (sp.getString(pref.key, "").startsWith("hmac:")) {
pref.summary = "******"
} else {
pref.summary = resourceHelper.gs(R.string.password_not_set)
}
}
}
pref?.let { adjustUnitDependentPrefs(it) }
}
private fun initSummary(p: Preference, isSinglePreference: Boolean) {
p.isIconSpaceReserved = false // remove extra spacing on left after migration to androidx
// expand single plugin preference by default
if (p is PreferenceScreen && isSinglePreference) {
if (p.size > 0 && p.getPreference(0) is PreferenceCategory)
(p.getPreference(0) as PreferenceCategory).initialExpandedChildrenCount = Int.MAX_VALUE
}
if (p is PreferenceGroup) {
for (i in 0 until p.preferenceCount) {
initSummary(p.getPreference(i), isSinglePreference)
}
} else {
updatePrefSummary(p)
}
}
// We use Preference and custom editor instead of EditTextPreference
// to hash password while it is saved and never have to show it, even hashed
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
context?.let { context ->
if (preference != null) {
if (preference.key == resourceHelper.gs(R.string.key_master_password)) {
passwordCheck.queryPassword(context, R.string.current_master_password, R.string.key_master_password, {
passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password)
})
return true
}
if (preference.key == resourceHelper.gs(R.string.key_settings_password)) {
passwordCheck.setPassword(context, R.string.settings_password, R.string.key_settings_password)
return true
}
if (preference.key == resourceHelper.gs(R.string.key_bolus_password)) {
passwordCheck.setPassword(context, R.string.bolus_password, R.string.key_bolus_password)
return true
}
if (preference.key == resourceHelper.gs(R.string.key_application_password)) {
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
return true
}
}
}
return super.onPreferenceTreeClick(preference)
}
}

View file

@ -2,14 +2,16 @@ package info.nightscout.androidaps.activities
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.LocaleHelper import info.nightscout.androidaps.utils.LocaleHelper
open class NoSplashAppCompatActivity : AppCompatActivity() { @Suppress("registered")
open class NoSplashAppCompatActivity : DaggerAppCompatActivity() {
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme_NoActionBar)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setTheme(R.style.AppTheme_NoActionBar)
} }
public override fun attachBaseContext(newBase: Context) { public override fun attachBaseContext(newBase: Context) {

View file

@ -1,270 +0,0 @@
package info.nightscout.androidaps.activities;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import java.util.Arrays;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
MyPreferenceFragment myPreferenceFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState);
myPreferenceFragment = new MyPreferenceFragment();
Bundle args = new Bundle();
args.putInt("id", getIntent().getIntExtra("id", -1));
myPreferenceFragment.setArguments(args);
getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleHelper.INSTANCE.wrap(newBase));
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
RxBus.INSTANCE.send(new EventPreferenceChange(key));
if (key.equals(MainApp.gs(R.string.key_language))) {
RxBus.INSTANCE.send(new EventRebuildTabs(true));
//recreate() does not update language so better close settings
finish();
}
if (key.equals(MainApp.gs(R.string.key_short_tabtitles))) {
RxBus.INSTANCE.send(new EventRebuildTabs());
}
if (key.equals(MainApp.gs(R.string.key_units))) {
recreate();
return;
}
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning));
}
updatePrefSummary(myPreferenceFragment.findPreference(key));
}
private static void adjustUnitDependentPrefs(Preference pref) {
// convert preferences values to current units
String[] unitDependent = new String[]{
MainApp.gs(R.string.key_hypo_target),
MainApp.gs(R.string.key_activity_target),
MainApp.gs(R.string.key_eatingsoon_target),
MainApp.gs(R.string.key_high_mark),
MainApp.gs(R.string.key_low_mark)
};
if (Arrays.asList(unitDependent).contains(pref.getKey())) {
EditTextPreference editTextPref = (EditTextPreference) pref;
String converted = Profile.toCurrentUnitsString(SafeParse.stringToDouble(editTextPref.getText()));
editTextPref.setSummary(converted);
editTextPref.setText(converted);
}
}
private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
if (pref instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******");
} else if (editTextPref.getText() != null) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText());
} else {
for (PluginBase plugin : MainApp.getPluginsList()) {
plugin.updatePreferenceSummary(pref);
}
}
}
if (pref != null)
adjustUnitDependentPrefs(pref);
}
public static void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
initSummary(pGrp.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
public static class MyPreferenceFragment extends PreferenceFragment {
private Integer id;
@Override
public void setArguments(Bundle args) {
super.setArguments(args);
id = args.getInt("id");
}
void addPreferencesFromResourceIfEnabled(PluginBase p, PluginType type) {
if (p.isEnabled(type) && p.getPreferencesId() != -1)
addPreferencesFromResource(p.getPreferencesId());
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey("id")) {
id = savedInstanceState.getInt("id");
}
if (id != -1) {
addPreferencesFromResource(id);
} else {
if (!Config.NSCLIENT) {
addPreferencesFromResource(R.xml.pref_password);
}
addPreferencesFromResource(R.xml.pref_general);
addPreferencesFromResource(R.xml.pref_age);
addPreferencesFromResource(R.xml.pref_overview);
addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
if (Config.APS) {
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginType.LOOP);
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginType.APS);
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginType.APS);
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginType.APS);
}
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref1Plugin.getPlugin(), PluginType.SENSITIVITY);
if (Config.PUMPDRIVERS) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP);
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile);
}
}
if (!Config.NSCLIENT) {
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginType.PUMP);
}
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResource(R.xml.pref_others);
addPreferencesFromResource(R.xml.pref_datachoices);
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL);
}
initSummary(getPreferenceScreen());
for (PluginBase plugin : MainApp.getPluginsList()) {
plugin.preprocessPreferences(this);
}
PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
PreferenceScreen localAlertsPreferenceScreen = (PreferenceScreen) findPreference(MainApp.gs(R.string.key_preferences_screen_local_alerts));
if (activePump != null && localAlertsPreferenceScreen != null && activePump.getPumpDescription().hasFixedUnreachableAlert) {
Preference pumpUnreachableEnabledPreference = findPreference(MainApp.gs(R.string.key_enable_pump_unreachable_alert));
if (pumpUnreachableEnabledPreference != null) {
((SwitchPreference) pumpUnreachableEnabledPreference).setChecked(true);
pumpUnreachableEnabledPreference.setEnabled(false);
pumpUnreachableEnabledPreference.setShouldDisableView(true);
}
Preference pumpUnreachableThresholdPreference = findPreference(MainApp.gs(R.string.key_pump_unreachable_threshold));
if (pumpUnreachableThresholdPreference != null) {
pumpUnreachableThresholdPreference.setDependency(null);
}
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("id", id);
}
}
}

View file

@ -0,0 +1,47 @@
package info.nightscout.androidaps.activities
import android.content.Context
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.LocaleHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
@Inject lateinit var resourceHelper: ResourceHelper
var preferenceId = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_fragment)
title = resourceHelper.gs(R.string.nav_preferences)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
val myPreferenceFragment = MyPreferenceFragment()
preferenceId = intent.getIntExtra("id", -1)
val args = Bundle()
args.putInt("id", preferenceId)
myPreferenceFragment.arguments = args
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment).commit()
}
override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat, pref: PreferenceScreen): Boolean {
val fragment = MyPreferenceFragment()
val args = Bundle()
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
args.putInt("id", preferenceId)
fragment.arguments = args
supportFragmentManager.beginTransaction()
.replace(R.id.frame_layout, fragment, pref.key)
.addToBackStack(pref.key)
.commit()
return true
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
}

View file

@ -1,15 +1,17 @@
package info.nightscout.androidaps.activities package info.nightscout.androidaps.activities
import android.os.Bundle import android.os.Bundle
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin import info.nightscout.androidaps.plugins.source.DexcomPlugin
import javax.inject.Inject
class RequestDexcomPermissionActivity : DialogAppCompatActivity() { class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
@Inject lateinit var dexcomPlugin: DexcomPlugin
private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum() private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode) requestPermissions(arrayOf(DexcomPlugin.PERMISSION), requestCode)
} }
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {

View file

@ -5,19 +5,24 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.utils.LocaleHelper import info.nightscout.androidaps.utils.LocaleHelper
import info.nightscout.androidaps.utils.PasswordProtection import info.nightscout.androidaps.utils.protection.ProtectionCheck
import javax.inject.Inject
class SingleFragmentActivity : DaggerAppCompatActivity() {
@Inject lateinit var pluginStore: PluginStore
@Inject lateinit var protectionCheck: ProtectionCheck
class SingleFragmentActivity : AppCompatActivity() {
private var plugin: PluginBase? = null private var plugin: PluginBase? = null
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_fragment) setContentView(R.layout.activity_single_fragment)
plugin = MainApp.getPluginsList()[intent.getIntExtra("plugin", -1)] plugin = pluginStore.plugins[intent.getIntExtra("plugin", -1)]
title = plugin?.name title = plugin?.name
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true)
@ -32,7 +37,7 @@ class SingleFragmentActivity : AppCompatActivity() {
finish() finish()
return true return true
} else if (item.itemId == R.id.nav_plugin_preferences) { } else if (item.itemId == R.id.nav_plugin_preferences) {
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", Runnable { protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(this, PreferencesActivity::class.java) val i = Intent(this, PreferencesActivity::class.java)
i.putExtra("id", plugin?.preferencesId) i.putExtra("id", plugin?.preferencesId)
startActivity(i) startActivity(i)

View file

@ -1,28 +1,33 @@
package info.nightscout.androidaps.activities package info.nightscout.androidaps.activities
import android.os.Bundle import android.os.Bundle
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.ActivityMonitor import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.TddCalculator import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.androidaps.utils.TirCalculator import info.nightscout.androidaps.utils.stats.TirCalculator
import kotlinx.android.synthetic.main.stats_activity.* import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.activity_stats.*
import javax.inject.Inject
class StatsActivity : NoSplashAppCompatActivity() { class StatsActivity : NoSplashAppCompatActivity() {
@Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var tirCalculator: TirCalculator
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activityMonitor: ActivityMonitor
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.stats_activity) setContentView(R.layout.activity_stats)
stats_tdds.text = TddCalculator.stats() stats_tdds.text = tddCalculator.stats()
stats_tir.text = TirCalculator.stats() stats_tir.text = tirCalculator.stats()
stats_activity.text = ActivityMonitor.stats() stats_activity.text = activityMonitor.stats()
ok.setOnClickListener { finish() } ok.setOnClickListener { finish() }
stats_reset.setOnClickListener { stats_reset.setOnClickListener {
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats), Runnable { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats), Runnable {
ActivityMonitor.reset() activityMonitor.reset()
recreate() recreate()
}) })
} }

View file

@ -6,15 +6,31 @@ import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.FirebaseDatabase
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.InstanceId
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.androidaps.utils.stats.TirCalculator
import kotlinx.android.synthetic.main.survey_activity.* import kotlinx.android.synthetic.main.survey_activity.*
import org.slf4j.LoggerFactory import javax.inject.Inject
class SurveyActivity : NoSplashAppCompatActivity() { class SurveyActivity : NoSplashAppCompatActivity() {
private val log = LoggerFactory.getLogger(SurveyActivity::class.java) @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var tirCalculator: TirCalculator
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activityMonitor: ActivityMonitor
@Inject lateinit var defaultProfile: DefaultProfile
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -22,13 +38,13 @@ class SurveyActivity : NoSplashAppCompatActivity() {
survey_id.text = InstanceId.instanceId() survey_id.text = InstanceId.instanceId()
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile val profileStore = activePlugin.activeProfileInterface.profile
val profileList = profileStore?.getProfileList() ?: return val profileList = profileStore?.getProfileList() ?: return
survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList) survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
survey_tdds.text = TddCalculator.stats() survey_tdds.text = tddCalculator.stats()
survey_tir.text = TirCalculator.stats() survey_tir.text = tirCalculator.stats()
survey_activity.text = ActivityMonitor.stats() survey_activity.text = activityMonitor.stats()
survey_profile.setOnClickListener { survey_profile.setOnClickListener {
val age = SafeParse.stringToDouble(survey_age.text.toString()) val age = SafeParse.stringToDouble(survey_age.text.toString())
@ -46,7 +62,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
ToastUtils.showToastInUiThread(this, R.string.invalidweight) ToastUtils.showToastInUiThread(this, R.string.invalidweight)
return@setOnClickListener return@setOnClickListener
} }
val profile = DefaultProfile().profile(age, tdd, weight, ProfileFunctions.getSystemUnits()) val profile = defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
val args = Bundle() val args = Bundle()
args.putLong("time", DateUtil.now()) args.putLong("time", DateUtil.now())
args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal) args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal)
@ -83,13 +99,13 @@ class SurveyActivity : NoSplashAppCompatActivity() {
auth.signInAnonymously() auth.signInAnonymously()
.addOnCompleteListener(this) { task -> .addOnCompleteListener(this) { task ->
if (task.isSuccessful) { if (task.isSuccessful) {
log.debug("signInAnonymously:success") aapsLogger.debug(LTag.CORE, "signInAnonymously:success")
//val user = auth.currentUser // TODO: do we need this, seems unused? //val user = auth.currentUser // TODO: do we need this, seems unused?
val database = FirebaseDatabase.getInstance().reference val database = FirebaseDatabase.getInstance().reference
database.child("survey").child(r.id).setValue(r) database.child("survey").child(r.id).setValue(r)
} else { } else {
log.error("signInAnonymously:failure", task.exception) aapsLogger.error("signInAnonymously:failure", task.exception!!)
ToastUtils.showToastInUiThread(this, "Authentication failed.") ToastUtils.showToastInUiThread(this, "Authentication failed.")
//updateUI(null) //updateUI(null)
} }

View file

@ -4,7 +4,6 @@ import android.graphics.Color;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@ -18,28 +17,29 @@ import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TDD; import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus;
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
@ -47,15 +47,29 @@ import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse; import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
public class TDDStatsActivity extends NoSplashAppCompatActivity { public class TDDStatsActivity extends NoSplashAppCompatActivity {
private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class); @Inject AAPSLogger aapsLogger;
@Inject ResourceHelper resourceHelper;
@Inject RxBusWrapper rxBus;
@Inject SP sp;
@Inject ProfileFunction profileFunction;
@Inject ActivePluginProvider activePlugin;
@Inject DanaRSPlugin danaRSPlugin;
@Inject DanaRPlugin danaRPlugin;
@Inject DanaRv2Plugin danaRv2Plugin;
@Inject DanaRKoreanPlugin danaRKoreanPlugin;
@Inject LocalInsightPlugin localInsightPlugin;
@Inject ConfigBuilderPlugin configBuilderPlugin;
@Inject CommandQueueProvider commandQueue;
@Inject FabricPrivacy fabricPrivacy;
private CompositeDisposable disposable = new CompositeDisposable(); private CompositeDisposable disposable = new CompositeDisposable();
TextView statusView, statsMessage, totalBaseBasal2; TextView statusView, statsMessage, totalBaseBasal2;
@ -77,18 +91,18 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventPumpStatusChanged.class) .toObservable(EventPumpStatusChanged.class)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException) .subscribe(event -> statusView.setText(event.getStatus(resourceHelper)), exception -> fabricPrivacy.logException(exception))
); );
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventDanaRSyncStatus.class) .toObservable(EventDanaRSyncStatus.class)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> { .subscribe(event -> {
log.debug("EventDanaRSyncStatus: " + event.getMessage()); aapsLogger.debug("EventDanaRSyncStatus: " + event.getMessage());
statusView.setText(event.getMessage()); statusView.setText(event.getMessage());
}, FabricPrivacy::logException) }, exception -> fabricPrivacy.logException(exception))
); );
} }
@ -118,11 +132,11 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.danar_statsactivity); setContentView(R.layout.danar_statsactivity);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
statusView = (TextView) findViewById(R.id.danar_stats_connection_status); statusView = findViewById(R.id.danar_stats_connection_status);
reloadButton = (Button) findViewById(R.id.danar_statsreload); reloadButton = findViewById(R.id.danar_statsreload);
totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal); totalBaseBasal = findViewById(R.id.danar_stats_editTotalBaseBasal);
totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2); totalBaseBasal2 = findViewById(R.id.danar_stats_editTotalBaseBasal2);
statsMessage = (TextView) findViewById(R.id.danar_stats_Message); statsMessage = findViewById(R.id.danar_stats_Message);
statusView.setVisibility(View.GONE); statusView.setVisibility(View.GONE);
statsMessage.setVisibility(View.GONE); statsMessage.setVisibility(View.GONE);
@ -135,21 +149,21 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
decimalFormat = new DecimalFormat("0.000"); decimalFormat = new DecimalFormat("0.000");
llm = new LinearLayoutManager(this); llm = new LinearLayoutManager(this);
TBB = SP.getString("TBB", "10.00"); TBB = sp.getString("TBB", "10.00");
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = profileFunction.getProfile();
if (profile != null) { if (profile != null) {
double cppTBB = profile.baseBasalSum(); double cppTBB = profile.baseBasalSum();
TBB = decimalFormat.format(cppTBB); TBB = decimalFormat.format(cppTBB);
SP.putString("TBB", TBB); sp.putString("TBB", TBB);
} }
totalBaseBasal.setText(TBB); totalBaseBasal.setText(TBB);
if (!ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().needsManualTDDLoad) if (!activePlugin.getActivePump().getPumpDescription().needsManualTDDLoad)
reloadButton.setVisibility(View.GONE); reloadButton.setVisibility(View.GONE);
// stats table // stats table
tl = (TableLayout) findViewById(R.id.main_table); tl = findViewById(R.id.main_table);
TableRow tr_head = new TableRow(this); TableRow tr_head = new TableRow(this);
tr_head.setBackgroundColor(Color.DKGRAY); tr_head.setBackgroundColor(Color.DKGRAY);
tr_head.setLayoutParams(new TableLayout.LayoutParams( tr_head.setLayoutParams(new TableLayout.LayoutParams(
@ -157,27 +171,27 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_date = new TextView(this); TextView label_date = new TextView(this);
label_date.setText(MainApp.gs(R.string.danar_stats_date)); label_date.setText(resourceHelper.gs(R.string.danar_stats_date));
label_date.setTextColor(Color.WHITE); label_date.setTextColor(Color.WHITE);
tr_head.addView(label_date); tr_head.addView(label_date);
TextView label_basalrate = new TextView(this); TextView label_basalrate = new TextView(this);
label_basalrate.setText(MainApp.gs(R.string.danar_stats_basalrate)); label_basalrate.setText(resourceHelper.gs(R.string.danar_stats_basalrate));
label_basalrate.setTextColor(Color.WHITE); label_basalrate.setTextColor(Color.WHITE);
tr_head.addView(label_basalrate); tr_head.addView(label_basalrate);
TextView label_bolus = new TextView(this); TextView label_bolus = new TextView(this);
label_bolus.setText(MainApp.gs(R.string.danar_stats_bolus)); label_bolus.setText(resourceHelper.gs(R.string.danar_stats_bolus));
label_bolus.setTextColor(Color.WHITE); label_bolus.setTextColor(Color.WHITE);
tr_head.addView(label_bolus); tr_head.addView(label_bolus);
TextView label_tdd = new TextView(this); TextView label_tdd = new TextView(this);
label_tdd.setText(MainApp.gs(R.string.danar_stats_tdd)); label_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_tdd.setTextColor(Color.WHITE); label_tdd.setTextColor(Color.WHITE);
tr_head.addView(label_tdd); tr_head.addView(label_tdd);
TextView label_ratio = new TextView(this); TextView label_ratio = new TextView(this);
label_ratio.setText(MainApp.gs(R.string.danar_stats_ratio)); label_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_ratio.setTextColor(Color.WHITE); label_ratio.setTextColor(Color.WHITE);
tr_head.addView(label_ratio); tr_head.addView(label_ratio);
@ -187,7 +201,7 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
// cumulative table // cumulative table
ctl = (TableLayout) findViewById(R.id.cumulative_table); ctl = findViewById(R.id.cumulative_table);
TableRow ctr_head = new TableRow(this); TableRow ctr_head = new TableRow(this);
ctr_head.setBackgroundColor(Color.DKGRAY); ctr_head.setBackgroundColor(Color.DKGRAY);
ctr_head.setLayoutParams(new TableLayout.LayoutParams( ctr_head.setLayoutParams(new TableLayout.LayoutParams(
@ -195,17 +209,17 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_cum_amount_days = new TextView(this); TextView label_cum_amount_days = new TextView(this);
label_cum_amount_days.setText(MainApp.gs(R.string.danar_stats_amount_days)); label_cum_amount_days.setText(resourceHelper.gs(R.string.danar_stats_amount_days));
label_cum_amount_days.setTextColor(Color.WHITE); label_cum_amount_days.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_amount_days); ctr_head.addView(label_cum_amount_days);
TextView label_cum_tdd = new TextView(this); TextView label_cum_tdd = new TextView(this);
label_cum_tdd.setText(MainApp.gs(R.string.danar_stats_tdd)); label_cum_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_cum_tdd.setTextColor(Color.WHITE); label_cum_tdd.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_tdd); ctr_head.addView(label_cum_tdd);
TextView label_cum_ratio = new TextView(this); TextView label_cum_ratio = new TextView(this);
label_cum_ratio.setText(MainApp.gs(R.string.danar_stats_ratio)); label_cum_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_cum_ratio.setTextColor(Color.WHITE); label_cum_ratio.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_ratio); ctr_head.addView(label_cum_ratio);
@ -215,7 +229,7 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
// expontial table // expontial table
etl = (TableLayout) findViewById(R.id.expweight_table); etl = findViewById(R.id.expweight_table);
TableRow etr_head = new TableRow(this); TableRow etr_head = new TableRow(this);
etr_head.setBackgroundColor(Color.DKGRAY); etr_head.setBackgroundColor(Color.DKGRAY);
etr_head.setLayoutParams(new TableLayout.LayoutParams( etr_head.setLayoutParams(new TableLayout.LayoutParams(
@ -223,17 +237,17 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_exp_weight = new TextView(this); TextView label_exp_weight = new TextView(this);
label_exp_weight.setText(MainApp.gs(R.string.danar_stats_weight)); label_exp_weight.setText(resourceHelper.gs(R.string.danar_stats_weight));
label_exp_weight.setTextColor(Color.WHITE); label_exp_weight.setTextColor(Color.WHITE);
etr_head.addView(label_exp_weight); etr_head.addView(label_exp_weight);
TextView label_exp_tdd = new TextView(this); TextView label_exp_tdd = new TextView(this);
label_exp_tdd.setText(MainApp.gs(R.string.danar_stats_tdd)); label_exp_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_exp_tdd.setTextColor(Color.WHITE); label_exp_tdd.setTextColor(Color.WHITE);
etr_head.addView(label_exp_tdd); etr_head.addView(label_exp_tdd);
TextView label_exp_ratio = new TextView(this); TextView label_exp_ratio = new TextView(this);
label_exp_ratio.setText(MainApp.gs(R.string.danar_stats_ratio)); label_exp_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_exp_ratio.setTextColor(Color.WHITE); label_exp_ratio.setTextColor(Color.WHITE);
etr_head.addView(label_exp_ratio); etr_head.addView(label_exp_ratio);
@ -242,59 +256,44 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
reloadButton.setOnClickListener(new View.OnClickListener() { reloadButton.setOnClickListener(v -> {
@Override runOnUiThread(() -> {
public void onClick(View v) {
runOnUiThread(new Runnable() {
@Override
public void run() {
reloadButton.setVisibility(View.GONE); reloadButton.setVisibility(View.GONE);
statusView.setVisibility(View.VISIBLE); statusView.setVisibility(View.VISIBLE);
statsMessage.setVisibility(View.VISIBLE); statsMessage.setVisibility(View.VISIBLE);
statsMessage.setText(MainApp.gs(R.string.danar_stats_warning_Message)); statsMessage.setText(resourceHelper.gs(R.string.danar_stats_warning_Message));
}
}); });
ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs(new Callback() { commandQueue.loadTDDs(new Callback() {
@Override @Override
public void run() { public void run() {
loadDataFromDB(); loadDataFromDB();
runOnUiThread(new Runnable() { runOnUiThread(() -> {
@Override
public void run() {
reloadButton.setVisibility(View.VISIBLE); reloadButton.setVisibility(View.VISIBLE);
statusView.setVisibility(View.GONE); statusView.setVisibility(View.GONE);
statsMessage.setVisibility(View.GONE); statsMessage.setVisibility(View.GONE);
}
}); });
} }
}); });
}
}); });
totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() { totalBaseBasal.setOnEditorActionListener((v, actionId, event) -> {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
totalBaseBasal.clearFocus(); totalBaseBasal.clearFocus();
return true; return true;
} }
return false; return false;
}
}); });
totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() { totalBaseBasal.setOnFocusChangeListener((v, hasFocus) -> {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) { if (hasFocus) {
totalBaseBasal.getText().clear(); totalBaseBasal.getText().clear();
} else { } else {
SP.putString("TBB", totalBaseBasal.getText().toString()); sp.putString("TBB", totalBaseBasal.getText().toString());
TBB = SP.getString("TBB", ""); TBB = sp.getString("TBB", "");
loadDataFromDB(); loadDataFromDB();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
} }
}
}); });
loadDataFromDB(); loadDataFromDB();
@ -308,7 +307,7 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
//fill single gaps //fill single gaps
dummies = new LinkedList(); dummies = new LinkedList();
DateFormat df = new SimpleDateFormat("dd.MM."); DateFormat df = new SimpleDateFormat("dd.MM.", Locale.getDefault());
for (int i = 0; i < historyList.size() - 1; i++) { for (int i = 0; i < historyList.size() - 1; i++) {
TDD elem1 = historyList.get(i); TDD elem1 = historyList.get(i);
TDD elem2 = historyList.get(i + 1); TDD elem2 = historyList.get(i + 1);
@ -324,20 +323,13 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
} }
} }
historyList.addAll(dummies); historyList.addAll(dummies);
Collections.sort(historyList, new Comparator<TDD>() { Collections.sort(historyList, (lhs, rhs) -> (int) (rhs.date - lhs.date));
@Override
public int compare(TDD lhs, TDD rhs) {
return (int) (rhs.date - lhs.date);
}
});
runOnUiThread(new Runnable() { runOnUiThread(() -> {
@Override
public void run() {
cleanTable(tl); cleanTable(tl);
cleanTable(ctl); cleanTable(ctl);
cleanTable(etl); cleanTable(etl);
DateFormat df = new SimpleDateFormat("dd.MM."); DateFormat df1 = new SimpleDateFormat("dd.MM.", Locale.getDefault());
if (TextUtils.isEmpty(TBB)) { if (TextUtils.isEmpty(TBB)) {
totalBaseBasal.setError("Please Enter Total Base Basal"); totalBaseBasal.setError("Please Enter Total Base Basal");
@ -374,25 +366,25 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
// Here create the TextView dynamically // Here create the TextView dynamically
TextView labelDATE = new TextView(TDDStatsActivity.this); TextView labelDATE = new TextView(TDDStatsActivity.this);
labelDATE.setId(200 + i); labelDATE.setId(200 + i);
labelDATE.setText(df.format(new Date(record.date))); labelDATE.setText(df1.format(new Date(record.date)));
labelDATE.setTextColor(Color.WHITE); labelDATE.setTextColor(Color.WHITE);
tr.addView(labelDATE); tr.addView(labelDATE);
TextView labelBASAL = new TextView(TDDStatsActivity.this); TextView labelBASAL = new TextView(TDDStatsActivity.this);
labelBASAL.setId(300 + i); labelBASAL.setId(300 + i);
labelBASAL.setText(DecimalFormatter.to2Decimal(record.basal) + " U"); labelBASAL.setText(resourceHelper.gs(R.string.formatinsulinunits, record.basal));
labelBASAL.setTextColor(Color.WHITE); labelBASAL.setTextColor(Color.WHITE);
tr.addView(labelBASAL); tr.addView(labelBASAL);
TextView labelBOLUS = new TextView(TDDStatsActivity.this); TextView labelBOLUS = new TextView(TDDStatsActivity.this);
labelBOLUS.setId(400 + i); labelBOLUS.setId(400 + i);
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.bolus) + " U"); labelBOLUS.setText(resourceHelper.gs(R.string.formatinsulinunits, record.bolus));
labelBOLUS.setTextColor(Color.WHITE); labelBOLUS.setTextColor(Color.WHITE);
tr.addView(labelBOLUS); tr.addView(labelBOLUS);
TextView labelTDD = new TextView(TDDStatsActivity.this); TextView labelTDD = new TextView(TDDStatsActivity.this);
labelTDD.setId(500 + i); labelTDD.setId(500 + i);
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U"); labelTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, tdd));
labelTDD.setTextColor(Color.WHITE); labelTDD.setTextColor(Color.WHITE);
tr.addView(labelTDD); tr.addView(labelTDD);
@ -414,7 +406,7 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
//cumulative TDDs //cumulative TDDs
for (TDD record : historyList) { for (TDD record : historyList) {
if (!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) { if (!historyList.isEmpty() && df1.format(new Date(record.date)).equals(df1.format(new Date()))) {
//Today should not be included //Today should not be included
continue; continue;
} }
@ -439,7 +431,7 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TextView labelCUMTDD = new TextView(TDDStatsActivity.this); TextView labelCUMTDD = new TextView(TDDStatsActivity.this);
labelCUMTDD.setId(900 + i); labelCUMTDD.setId(900 + i);
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U"); labelCUMTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, sum / i));
labelCUMTDD.setTextColor(Color.WHITE); labelCUMTDD.setTextColor(Color.WHITE);
ctr.addView(labelCUMTDD); ctr.addView(labelCUMTDD);
@ -455,15 +447,15 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
} }
if (isOldData(historyList) && ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().needsManualTDDLoad) { if (isOldData(historyList) && activePlugin.getActivePump().getPumpDescription().needsManualTDDLoad) {
statsMessage.setVisibility(View.VISIBLE); statsMessage.setVisibility(View.VISIBLE);
statsMessage.setText(MainApp.gs(R.string.danar_stats_olddata_Message)); statsMessage.setText(resourceHelper.gs(R.string.danar_stats_olddata_Message));
} else { } else {
tl.setBackgroundColor(Color.TRANSPARENT); tl.setBackgroundColor(Color.TRANSPARENT);
} }
if (!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) { if (!historyList.isEmpty() && df1.format(new Date(historyList.get(0).date)).equals(df1.format(new Date()))) {
//Today should not be included //Today should not be included
historyList.remove(0); historyList.remove(0);
} }
@ -504,9 +496,9 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
TextView labelEXPTDD = new TextView(TDDStatsActivity.this); TextView labelEXPTDD = new TextView(TDDStatsActivity.this);
labelEXPTDD.setId(1300 + i); labelEXPTDD.setId(1300 + i);
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03) labelEXPTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, weighted03) + "\n" +
+ " U\n" + DecimalFormatter.to2Decimal(weighted05) resourceHelper.gs(R.string.formatinsulinunits, weighted05) + "\n" +
+ " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U"); resourceHelper.gs(R.string.formatinsulinunits, weighted07));
labelEXPTDD.setTextColor(Color.WHITE); labelEXPTDD.setTextColor(Color.WHITE);
etr.addView(labelEXPTDD); etr.addView(labelEXPTDD);
@ -522,7 +514,6 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
etl.addView(etr, new TableLayout.LayoutParams( etl.addView(etr, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
}
}); });
} }
@ -534,17 +525,11 @@ public class TDDStatsActivity extends NoSplashAppCompatActivity {
} }
} }
public static boolean isOldData(List<TDD> historyList) { public boolean isOldData(List<TDD> historyList) {
Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
PumpInterface dana = DanaRPlugin.getPlugin();
PumpInterface danaRS = DanaRSPlugin.getPlugin();
PumpInterface danaV2 = DanaRv2Plugin.getPlugin();
PumpInterface danaKorean = DanaRKoreanPlugin.getPlugin();
PumpInterface insight = LocalInsightPlugin.getPlugin();
boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight; boolean startsYesterday = danaRPlugin.isEnabled() || danaRSPlugin.isEnabled() || danaRv2Plugin.isEnabled() || danaRKoreanPlugin.isEnabled() || localInsightPlugin.isEnabled();
DateFormat df = new SimpleDateFormat("dd.MM."); DateFormat df = new SimpleDateFormat("dd.MM.", Locale.getDefault());
return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0)))))); return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0))))));
} }
} }

View file

@ -1,237 +0,0 @@
package info.nightscout.androidaps.data;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
/**
* Created by mike on 19.03.2018.
*/
public class ConstraintChecker implements ConstraintsInterface {
public Constraint<Boolean> isLoopInvokationAllowed() {
return isLoopInvocationAllowed(new Constraint<>(true));
}
public Constraint<Boolean> isClosedLoopAllowed() {
return isClosedLoopAllowed(new Constraint<>(true));
}
public Constraint<Boolean> isAutosensModeEnabled() {
return isAutosensModeEnabled(new Constraint<>(true));
}
public Constraint<Boolean> isAMAModeEnabled() {
return isAMAModeEnabled(new Constraint<>(true));
}
public Constraint<Boolean> isSMBModeEnabled() {
return isSMBModeEnabled(new Constraint<>(true));
}
public Constraint<Boolean> isUAMEnabled() {
return isUAMEnabled(new Constraint<>(true));
}
public Constraint<Boolean> isAdvancedFilteringEnabled() {
return isAdvancedFilteringEnabled(new Constraint<>(true));
}
public Constraint<Boolean> isSuperBolusEnabled() {
return isSuperBolusEnabled(new Constraint<>(true));
}
public Constraint<Double> getMaxBasalAllowed(Profile profile) {
return applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile);
}
public Constraint<Integer> getMaxBasalPercentAllowed(Profile profile) {
return applyBasalPercentConstraints(new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE), profile);
}
public Constraint<Double> getMaxBolusAllowed() {
return applyBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS));
}
public Constraint<Double> getMaxExtendedBolusAllowed() {
return applyExtendedBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS));
}
public Constraint<Integer> getMaxCarbsAllowed() {
return applyCarbsConstraints(new Constraint<>(Constants.REALLYHIGHCARBS));
}
public Constraint<Double> getMaxIOBAllowed() {
return applyMaxIOBConstraints(new Constraint<>(Constants.REALLYHIGHIOB));
}
@Override
public Constraint<Boolean> isLoopInvocationAllowed(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isLoopInvocationAllowed(value);
}
return value;
}
@Override
public Constraint<Boolean> isClosedLoopAllowed(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isClosedLoopAllowed(value);
}
return value;
}
@Override
public Constraint<Boolean> isAutosensModeEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isAutosensModeEnabled(value);
}
return value;
}
@Override
public Constraint<Boolean> isAMAModeEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.isAMAModeEnabled(value);
}
return value;
}
@Override
public Constraint<Boolean> isSMBModeEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isSMBModeEnabled(value);
}
return value;
}
@Override
public Constraint<Boolean> isUAMEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isUAMEnabled(value);
}
return value;
}
@Override
public Constraint<Boolean> isAdvancedFilteringEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isAdvancedFilteringEnabled(value);
}
return value;
}
@Override
public Constraint<Boolean> isSuperBolusEnabled(@NonNull Constraint<Boolean> value) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.isSuperBolusEnabled(value);
}
return value;
}
@Override
public Constraint<Double> applyBasalConstraints(@NonNull Constraint<Double> absoluteRate, Profile profile) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constraint.applyBasalConstraints(absoluteRate, profile);
}
return absoluteRate;
}
@Override
public Constraint<Integer> applyBasalPercentConstraints(@NonNull Constraint<Integer> percentRate, Profile profile) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.applyBasalPercentConstraints(percentRate, profile);
}
return percentRate;
}
@Override
public Constraint<Double> applyBolusConstraints(@NonNull Constraint<Double> insulin) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.applyBolusConstraints(insulin);
}
return insulin;
}
@Override
public Constraint<Double> applyExtendedBolusConstraints(@NonNull Constraint<Double> insulin) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.applyExtendedBolusConstraints(insulin);
}
return insulin;
}
@Override
public Constraint<Integer> applyCarbsConstraints(@NonNull Constraint<Integer> carbs) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.applyCarbsConstraints(carbs);
}
return carbs;
}
@Override
public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) {
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
constrain.applyMaxIOBConstraints(maxIob);
}
return maxIob;
}
}

View file

@ -7,13 +7,14 @@ import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.Round;
public class IobTotal implements DataPointWithLabelInterface { public class IobTotal implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(IobTotal.class); private static Logger log = StacktraceLoggerWrapper.getLogger(IobTotal.class);
public double iob; public double iob;
public double activity; public double activity;

View file

@ -2,24 +2,27 @@ package info.nightscout.androidaps.data;
import androidx.collection.LongSparseArray; import androidx.collection.LongSparseArray;
import org.joda.time.DateTime;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.TimeZone; import java.util.TimeZone;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
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.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
@ -27,9 +30,16 @@ import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.MidnightTime; import info.nightscout.androidaps.utils.MidnightTime;
import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
public class Profile { public class Profile {
private static Logger log = LoggerFactory.getLogger(Profile.class); @Inject public AAPSLogger aapsLogger;
@Inject public ActivePluginProvider activePlugin;
@Inject public ResourceHelper resourceHelper;
@Inject public RxBusWrapper rxBus;
@Inject public FabricPrivacy fabricPrivacy;
private HasAndroidInjector injector;
private JSONObject json; private JSONObject json;
private String units; private String units;
@ -52,8 +62,14 @@ public class Profile {
protected boolean isValid; protected boolean isValid;
protected boolean isValidated; protected boolean isValidated;
// Default constructor for tests // Default constructor for DB
protected Profile() { public Profile() {
MainApp.instance().injector.androidInjector().inject(this);
}
protected Profile(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
this.injector = injector;
} }
@Override @Override
@ -65,24 +81,27 @@ public class Profile {
} }
// Constructor from profileStore JSON // Constructor from profileStore JSON
public Profile(JSONObject json, String units) { public Profile(HasAndroidInjector injector, JSONObject json, String units) {
this(injector);
init(json, 100, 0); init(json, 100, 0);
if (this.units == null) { if (this.units == null) {
if (units != null) if (units != null)
this.units = units; this.units = units;
else { else {
FabricPrivacy.log("Profile failover failed too"); fabricPrivacy.log("Profile failover failed too");
this.units = Constants.MGDL; this.units = Constants.MGDL;
} }
} }
} }
// Constructor from profileStore JSON // Constructor from profileStore JSON
public Profile(JSONObject json) { public Profile(HasAndroidInjector injector, JSONObject json) {
this(injector);
init(json, 100, 0); init(json, 100, 0);
} }
public Profile(JSONObject json, int percentage, int timeshift) { public Profile(HasAndroidInjector injector, JSONObject json, int percentage, int timeshift) {
this(injector);
init(json, percentage, timeshift); init(json, percentage, timeshift);
} }
@ -115,7 +134,7 @@ public class Profile {
targetLow = json.getJSONArray("target_low"); targetLow = json.getJSONArray("target_low");
targetHigh = json.getJSONArray("target_high"); targetHigh = json.getJSONArray("target_high");
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
isValid = false; isValid = false;
isValidated = true; isValidated = true;
} }
@ -136,7 +155,7 @@ public class Profile {
try { try {
json.put("units", units); json.put("units", units);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
return json; return json;
} }
@ -181,9 +200,9 @@ public class Profile {
double value = o.getDouble("value") * multiplier; double value = o.getDouble("value") * multiplier;
sparse.put(tas, value); sparse.put(tas, value);
} catch (Exception e) { } catch (Exception e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
log.error(json.toString()); aapsLogger.error(json.toString());
FabricPrivacy.logException(e); fabricPrivacy.logException(e);
} }
} }
@ -229,21 +248,20 @@ public class Profile {
if (isValid) { if (isValid) {
// Check for hours alignment // Check for hours alignment
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); PumpInterface pump = activePlugin.getActivePump();
if (pump != null && !pump.getPumpDescription().is30minBasalRatesCapable) { if (!pump.getPumpDescription().is30minBasalRatesCapable) {
for (int index = 0; index < basal_v.size(); index++) { for (int index = 0; index < basal_v.size(); index++) {
long secondsFromMidnight = basal_v.keyAt(index); long secondsFromMidnight = basal_v.keyAt(index);
if (notify && secondsFromMidnight % 3600 != 0) { if (notify && secondsFromMidnight % 3600 != 0) {
if (Config.APS) { if (Config.APS) {
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, resourceHelper.gs(R.string.basalprofilenotaligned, from), Notification.NORMAL);
RxBus.INSTANCE.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
} }
} }
} }
} }
// Check for minimal basal value // Check for minimal basal value
if (pump != null) {
PumpDescription description = pump.getPumpDescription(); PumpDescription description = pump.getPumpDescription();
for (int i = 0; i < basal_v.size(); i++) { for (int i = 0; i < basal_v.size(); i++) {
if (basal_v.valueAt(i) < description.basalMinimumRate) { if (basal_v.valueAt(i) < description.basalMinimumRate) {
@ -256,23 +274,17 @@ public class Profile {
sendAboveMaximumNotification(from); sendAboveMaximumNotification(from);
} }
} }
} else {
// if pump not available (at start)
// do not store converted array
basal_v = null;
isValidated = false;
}
} }
return isValid; return isValid;
} }
protected void sendBelowMinimumNotification(String from) { protected void sendBelowMinimumNotification(String from) {
RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL))); rxBus.send(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, resourceHelper.gs(R.string.minimalbasalvaluereplaced, from), Notification.NORMAL)));
} }
protected void sendAboveMaximumNotification(String from) { protected void sendAboveMaximumNotification(String from) {
RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL))); rxBus.send(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, resourceHelper.gs(R.string.maximumbasalvaluereplaced, from), Notification.NORMAL)));
} }
private void validate(LongSparseArray array) { private void validate(LongSparseArray array) {
@ -326,7 +338,7 @@ public class Profile {
else if (array == basal_v) else if (array == basal_v)
multiplier = percentage / 100d; multiplier = percentage / 100d;
else else
log.error("Unknown array type"); aapsLogger.error("Unknown array type");
return multiplier; return multiplier;
} }
@ -344,7 +356,7 @@ public class Profile {
else if (array == targetHigh) else if (array == targetHigh)
multiplier = 1d; multiplier = 1d;
else else
log.error("Unknown array type"); aapsLogger.error("Unknown array type");
return multiplier; return multiplier;
} }
@ -407,7 +419,7 @@ public class Profile {
public String getIsfList() { public String getIsfList() {
if (isf_v == null) if (isf_v == null)
isf_v = convertToSparseArray(isf); isf_v = convertToSparseArray(isf);
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit)); return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + resourceHelper.gs(R.string.profile_per_unit));
} }
public ProfileValue[] getIsfsMgdl() { public ProfileValue[] getIsfsMgdl() {
@ -440,7 +452,7 @@ public class Profile {
public String getIcList() { public String getIcList() {
if (ic_v == null) if (ic_v == null)
ic_v = convertToSparseArray(ic); ic_v = convertToSparseArray(ic);
return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit)); return getValuesList(ic_v, null, new DecimalFormat("0.0"), resourceHelper.gs(R.string.profile_carbs_per_unit));
} }
public ProfileValue[] getIcs() { public ProfileValue[] getIcs() {
@ -474,7 +486,7 @@ public class Profile {
public String getBasalList() { public String getBasalList() {
if (basal_v == null) if (basal_v == null)
basal_v = convertToSparseArray(basal); basal_v = convertToSparseArray(basal);
return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hour)); return getValuesList(basal_v, null, new DecimalFormat("0.00"), resourceHelper.gs(R.string.profile_ins_units_per_hour));
} }
public class ProfileValue { public class ProfileValue {
@ -486,6 +498,7 @@ public class Profile {
public int timeAsSeconds; public int timeAsSeconds;
public double value; public double value;
public boolean equals(Object otherObject) { public boolean equals(Object otherObject) {
if (!(otherObject instanceof ProfileValue)) { if (!(otherObject instanceof ProfileValue)) {
return false; return false;
@ -608,13 +621,15 @@ public class Profile {
} }
public static int secondsFromMidnight() { public static int secondsFromMidnight() {
long passed = DateUtil.now() - MidnightTime.calc(); // long passed = DateUtil.now() - MidnightTime.calc();
long passed = new DateTime().getMillisOfDay();
return (int) (passed / 1000); return (int) (passed / 1000);
} }
public static int secondsFromMidnight(long date) { public static int secondsFromMidnight(long date) {
long midnight = MidnightTime.calc(date); //long midnight = MidnightTime.calc(date);
long passed = date - midnight; //long passed = date - midnight;
long passed = new DateTime(date).getMillisOfDay();
return (int) (passed / 1000); return (int) (passed / 1000);
} }
@ -654,16 +669,21 @@ public class Profile {
else return (valueInMmol > 0 ? "+" : "") + DecimalFormatter.to1Decimal(valueInMmol); else return (valueInMmol > 0 ? "+" : "") + DecimalFormatter.to1Decimal(valueInMmol);
} }
public static double toCurrentUnits(double anyBg) { public static double toCurrentUnits(ProfileFunction profileFunction, double anyBg) {
if (anyBg < 32) return fromMmolToUnits(anyBg, ProfileFunctions.getSystemUnits()); if (anyBg < 32) return fromMmolToUnits(anyBg, profileFunction.getUnits());
else return fromMgdlToUnits(anyBg, ProfileFunctions.getSystemUnits()); else return fromMgdlToUnits(anyBg, profileFunction.getUnits());
} }
public static String toCurrentUnitsString(double anyBg) { public static double toCurrentUnits(String units, double anyBg) {
if (anyBg < 32) return fromMmolToUnits(anyBg, units);
else return fromMgdlToUnits(anyBg, units);
}
public static String toCurrentUnitsString(ProfileFunction profileFunction, double anyBg) {
if (anyBg < 32) if (anyBg < 32)
return toUnitsString(anyBg * Constants.MMOLL_TO_MGDL, anyBg, ProfileFunctions.getSystemUnits()); return toUnitsString(anyBg * Constants.MMOLL_TO_MGDL, anyBg, profileFunction.getUnits());
else else
return toUnitsString(anyBg, anyBg * Constants.MGDL_TO_MMOLL, ProfileFunctions.getSystemUnits()); return toUnitsString(anyBg, anyBg * Constants.MGDL_TO_MMOLL, profileFunction.getUnits());
} }
// targets are stored in mg/dl but profile vary // targets are stored in mg/dl but profile vary
@ -807,12 +827,13 @@ public class Profile {
o.put("target_high", target_high); o.put("target_high", target_high);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception" + e); aapsLogger.error("Unhandled exception" + e);
} }
return new Profile(o); return new Profile(injector, o);
} }
public boolean isProfileTheSame(Profile otherProfile) {
public boolean areProfileBasalPatternsSame(Profile otherProfile) {
if (!Round.isSame(this.baseBasalSum(), otherProfile.baseBasalSum())) if (!Round.isSame(this.baseBasalSum(), otherProfile.baseBasalSum()))
return false; return false;

View file

@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
/** /**
* Created by mike on 09.05.2017. * Created by mike on 09.05.2017.
@ -19,7 +20,7 @@ import info.nightscout.androidaps.interfaces.Interval;
// When no interval match the lastest record without duration is used // When no interval match the lastest record without duration is used
public class ProfileIntervals<T extends Interval> { public class ProfileIntervals<T extends Interval> {
private static Logger log = LoggerFactory.getLogger(ProfileIntervals.class); private static Logger log = StacktraceLoggerWrapper.getLogger(ProfileIntervals.class);
private LongSparseArray<T> rawData; // oldest at index 0 private LongSparseArray<T> rawData; // oldest at index 0

View file

@ -1,14 +1,20 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.data
import androidx.collection.ArrayMap import androidx.collection.ArrayMap
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.slf4j.LoggerFactory
import java.util.* import java.util.*
import javax.inject.Inject
class ProfileStore(val data: JSONObject) { class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject) {
private val log = LoggerFactory.getLogger(ProfileStore::class.java) @Inject lateinit var aapsLogger: AAPSLogger
init {
injector.androidInjector().inject(this)
}
private val cachedObjects = ArrayMap<String, Profile>() private val cachedObjects = ArrayMap<String, Profile>()
@ -16,7 +22,7 @@ class ProfileStore(val data: JSONObject) {
try { try {
if (data.has("store")) return data.getJSONObject("store") if (data.has("store")) return data.getJSONObject("store")
} catch (e: JSONException) { } catch (e: JSONException) {
log.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
} }
return null return null
} }
@ -48,7 +54,7 @@ class ProfileStore(val data: JSONObject) {
JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject -> JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject ->
// take units from profile and if N/A from store // take units from profile and if N/A from store
JsonHelper.safeGetStringAllowNull(profileObject, "units", JsonHelper.safeGetString(data, "units"))?.let { units -> JsonHelper.safeGetStringAllowNull(profileObject, "units", JsonHelper.safeGetString(data, "units"))?.let { units ->
profile = Profile(profileObject, units) profile = Profile(injector, profileObject, units)
cachedObjects[profileName] = profile cachedObjects[profileName] = profile
} }
} }

View file

@ -2,17 +2,19 @@ package info.nightscout.androidaps.data;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
public class PumpEnactResult { public class PumpEnactResult {
private static Logger log = LoggerFactory.getLogger(L.APS); @Inject public AAPSLogger aapsLogger;
@Inject public ResourceHelper resourceHelper;
public boolean success = false; // request was processed successfully (but possible no change was needed) public boolean success = false; // request was processed successfully (but possible no change was needed)
public boolean enacted = false; // request was processed successfully and change has been made public boolean enacted = false; // request was processed successfully and change has been made
@ -30,6 +32,10 @@ public class PumpEnactResult {
public boolean queued = false; public boolean queued = false;
public PumpEnactResult(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
}
public PumpEnactResult success(boolean success) { public PumpEnactResult success(boolean success) {
this.success = success; this.success = success;
return this; return this;
@ -46,7 +52,7 @@ public class PumpEnactResult {
} }
public PumpEnactResult comment(int comment) { public PumpEnactResult comment(int comment) {
this.comment = MainApp.gs(comment); this.comment = resourceHelper.gs(comment);
return this; return this;
} }
@ -105,66 +111,66 @@ public class PumpEnactResult {
} }
public String toString() { public String toString() {
String ret = MainApp.gs(R.string.success) + ": " + success; String ret = resourceHelper.gs(R.string.success) + ": " + success;
if (enacted) { if (enacted) {
if (bolusDelivered > 0) { if (bolusDelivered > 0) {
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted; ret += "\n" + resourceHelper.gs(R.string.enacted) + ": " + enacted;
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment; ret += "\n" + resourceHelper.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.gs(R.string.configbuilder_insulin) ret += "\n" + resourceHelper.gs(R.string.configbuilder_insulin)
+ ": " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname); + ": " + bolusDelivered + " " + resourceHelper.gs(R.string.insulin_unit_shortname);
} else if (isTempCancel) { } else if (isTempCancel) {
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted; ret += "\n" + resourceHelper.gs(R.string.enacted) + ": " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment; ret += "\n" + resourceHelper.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.gs(R.string.canceltemp); ret += "\n" + resourceHelper.gs(R.string.canceltemp);
} else if (isPercent) { } else if (isPercent) {
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted; ret += "\n" + resourceHelper.gs(R.string.enacted) + ": " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment; ret += "\n" + resourceHelper.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min"; ret += "\n" + resourceHelper.gs(R.string.duration) + ": " + duration + " min";
ret += "\n" + MainApp.gs(R.string.percent) + ": " + percent + "%"; ret += "\n" + resourceHelper.gs(R.string.percent) + ": " + percent + "%";
} else { } else {
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted; ret += "\n" + resourceHelper.gs(R.string.enacted) + ": " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment; ret += "\n" + resourceHelper.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min"; ret += "\n" + resourceHelper.gs(R.string.duration) + ": " + duration + " min";
ret += "\n" + MainApp.gs(R.string.absolute) + ": " + absolute + " U/h"; ret += "\n" + resourceHelper.gs(R.string.absolute) + ": " + absolute + " U/h";
} }
} else { } else {
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment; ret += "\n" + resourceHelper.gs(R.string.comment) + ": " + comment;
} }
return ret; return ret;
} }
public String toHtml() { public String toHtml() {
String ret = "<b>" + MainApp.gs(R.string.success) + "</b>: " + success; String ret = "<b>" + resourceHelper.gs(R.string.success) + "</b>: " + success;
if (queued) { if (queued) {
ret = MainApp.gs(R.string.waitingforpumpresult); ret = resourceHelper.gs(R.string.waitingforpumpresult);
} else if (enacted) { } else if (enacted) {
if (bolusDelivered > 0) { if (bolusDelivered > 0) {
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted; ret += "<br><b>" + resourceHelper.gs(R.string.enacted) + "</b>: " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment; ret += "<br><b>" + resourceHelper.gs(R.string.comment) + "</b>: " + comment;
ret += "<br><b>" + MainApp.gs(R.string.smb_shortname) + "</b>: " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname); ret += "<br><b>" + resourceHelper.gs(R.string.smb_shortname) + "</b>: " + bolusDelivered + " " + resourceHelper.gs(R.string.insulin_unit_shortname);
} else if (isTempCancel) { } else if (isTempCancel) {
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted; ret += "<br><b>" + resourceHelper.gs(R.string.enacted) + "</b>: " + enacted;
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment + ret += "<br><b>" + resourceHelper.gs(R.string.comment) + "</b>: " + comment +
"<br>" + MainApp.gs(R.string.canceltemp); "<br>" + resourceHelper.gs(R.string.canceltemp);
} else if (isPercent && percent != -1) { } else if (isPercent && percent != -1) {
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted; ret += "<br><b>" + resourceHelper.gs(R.string.enacted) + "</b>: " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment; ret += "<br><b>" + resourceHelper.gs(R.string.comment) + "</b>: " + comment;
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min"; ret += "<br><b>" + resourceHelper.gs(R.string.duration) + "</b>: " + duration + " min";
ret += "<br><b>" + MainApp.gs(R.string.percent) + "</b>: " + percent + "%"; ret += "<br><b>" + resourceHelper.gs(R.string.percent) + "</b>: " + percent + "%";
} else if (absolute != -1) { } else if (absolute != -1) {
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted; ret += "<br><b>" + resourceHelper.gs(R.string.enacted) + "</b>: " + enacted;
if (!comment.isEmpty()) if (!comment.isEmpty())
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment; ret += "<br><b>" + resourceHelper.gs(R.string.comment) + "</b>: " + comment;
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min"; ret += "<br><b>" + resourceHelper.gs(R.string.duration) + "</b>: " + duration + " min";
ret += "<br><b>" + MainApp.gs(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h"; ret += "<br><b>" + resourceHelper.gs(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
} }
} else { } else {
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment; ret += "<br><b>" + resourceHelper.gs(R.string.comment) + "</b>: " + comment;
} }
return ret; return ret;
} }
@ -187,7 +193,7 @@ public class PumpEnactResult {
result.put("duration", duration); result.put("duration", duration);
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
return result; return result;
} }

View file

@ -1,238 +0,0 @@
package info.nightscout.androidaps.data;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
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.BolusWizard;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 25.12.2017.
*/
public class QuickWizardEntry {
private static Logger log = LoggerFactory.getLogger(QuickWizardEntry.class);
public JSONObject storage;
public int position;
public static final int YES = 0;
public static final int NO = 1;
public static final int POSITIVE_ONLY = 2;
public static final int NEGATIVE_ONLY = 3;
/*
{
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
validTo: 9 * 60 * 60, // seconds from midnight
useBG: 0,
useCOB: 0,
useBolusIOB: 0,
useBasalIOB: 0,
useTrend: 0,
useSuperBolus: 0,
useTemptarget: 0
}
*/
QuickWizardEntry() {
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
try {
storage = new JSONObject(emptyData);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
position = -1;
}
QuickWizardEntry(JSONObject entry, int position) {
storage = entry;
this.position = position;
}
Boolean isActive() {
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
}
public BolusWizard doCalc(Profile profile, String profileName, BgReading lastBG, boolean _synchronized) {
final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
//BG
double bg = 0;
if (lastBG != null && useBG() == YES) {
bg = lastBG.valueToUnits(ProfileFunctions.getSystemUnits());
}
// COB
double cob = 0d;
if (useCOB() == YES) {
CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(_synchronized, "QuickWizard COB");
if (cobInfo.displayCob != null)
cob = cobInfo.displayCob;
}
// Bolus IOB
boolean bolusIOB = false;
if (useBolusIOB() == YES) {
bolusIOB = true;
}
// Basal IOB
TreatmentsInterface treatments = TreatmentsPlugin.getPlugin();
treatments.updateTotalIOBTempBasals();
IobTotal basalIob = treatments.getLastCalculationTempBasals().round();
boolean basalIOB = false;
if (useBasalIOB() == YES) {
basalIOB = true;
} else if (useBasalIOB() == POSITIVE_ONLY && basalIob.iob > 0) {
basalIOB = true;
} else if (useBasalIOB() == NEGATIVE_ONLY && basalIob.iob < 0) {
basalIOB = true;
}
// SuperBolus
boolean superBolus = false;
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
superBolus = true;
}
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus())
superBolus = false;
// Trend
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
boolean trend = false;
if (useTrend() == YES) {
trend = true;
} else if (useTrend() == POSITIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta > 0) {
trend = true;
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta < 0) {
trend = true;
}
double percentage = SP.getDouble(R.string.key_boluswizard_percentage, 100.0);
return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard");
}
public String buttonText() {
try {
return storage.getString("buttonText");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return "";
}
public Integer carbs() {
try {
return storage.getInt("carbs");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Date validFromDate() {
return DateUtil.toDate(validFrom());
}
public Date validToDate() {
return DateUtil.toDate(validTo());
}
public Integer validFrom() {
try {
return storage.getInt("validFrom");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Integer validTo() {
try {
return storage.getInt("validTo");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public int useBG() {
try {
return storage.getInt("useBG");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useCOB() {
try {
return storage.getInt("useCOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useBolusIOB() {
try {
return storage.getInt("useBolusIOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useBasalIOB() {
try {
return storage.getInt("useBasalIOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useTrend() {
try {
return storage.getInt("useTrend");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useSuperBolus() {
try {
return storage.getInt("useSuperBolus");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useTempTarget() {
try {
return storage.getInt("useTempTarget");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
}

View file

@ -1,13 +1,17 @@
package info.nightscout.androidaps.data.defaultProfile package info.nightscout.androidaps.data.defaultProfile
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
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
import java.util.* import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DefaultProfile @Inject constructor(val injector: HasAndroidInjector) {
class DefaultProfile {
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()
@ -45,7 +49,7 @@ class DefaultProfile {
profile.put("timezone", TimeZone.getDefault().getID()) profile.put("timezone", TimeZone.getDefault().getID())
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))))
return Profile(profile, units) return Profile(injector, profile, units)
} }
init { init {

View file

@ -1,30 +1,38 @@
package info.nightscout.androidaps.db; package info.nightscout.androidaps.db;
import androidx.annotation.NonNull;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.DefaultValueHelper;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS)
public class BgReading implements DataPointWithLabelInterface { public class BgReading implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(L.GLUCOSE); @Inject public AAPSLogger aapsLogger;
@Inject public DefaultValueHelper defaultValueHelper;
@Inject public ProfileFunction profileFunction;
@Inject public ResourceHelper resourceHelper;
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;
@ -51,6 +59,11 @@ public class BgReading implements DataPointWithLabelInterface {
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT) public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
public BgReading() { public BgReading() {
MainApp.instance().androidInjector().inject(this);
}
public BgReading(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
} }
public BgReading(NSSgv sgv) { public BgReading(NSSgv sgv) {
@ -108,11 +121,11 @@ public class BgReading implements DataPointWithLabelInterface {
} }
@Override @NonNull @Override
public String toString() { public String toString() {
return "BgReading{" + return "BgReading{" +
"date=" + date + "date=" + date +
", date=" + new Date(date).toLocaleString() + ", date=" + DateUtil.dateAndTimeString(date) +
", value=" + value + ", value=" + value +
", direction=" + direction + ", direction=" + direction +
", raw=" + raw + ", raw=" + raw +
@ -121,8 +134,7 @@ public class BgReading implements DataPointWithLabelInterface {
public boolean isDataChanging(BgReading other) { public boolean isDataChanging(BgReading other) {
if (date != other.date) { if (date != other.date) {
if (L.isEnabled(L.GLUCOSE)) aapsLogger.debug(LTag.GLUCOSE, "Comparing different");
log.error("Comparing different");
return false; return false;
} }
if (value != other.value) if (value != other.value)
@ -132,8 +144,7 @@ public class BgReading implements DataPointWithLabelInterface {
public boolean isEqual(BgReading other) { public boolean isEqual(BgReading other) {
if (date != other.date) { if (date != other.date) {
if (L.isEnabled(L.GLUCOSE)) aapsLogger.debug(LTag.GLUCOSE, "Comparing different");
log.error("Comparing different");
return false; return false;
} }
if (value != other.value) if (value != other.value)
@ -149,8 +160,7 @@ public class BgReading implements DataPointWithLabelInterface {
public void copyFrom(BgReading other) { public void copyFrom(BgReading other) {
if (date != other.date) { if (date != other.date) {
if (L.isEnabled(L.GLUCOSE)) aapsLogger.error(LTag.GLUCOSE, "Copying different");
log.error("Copying different");
return; return;
} }
value = other.value; value = other.value;
@ -182,7 +192,7 @@ public class BgReading implements DataPointWithLabelInterface {
@Override @Override
public double getY() { public double getY() {
return valueToUnits(ProfileFunctions.getSystemUnits()); return valueToUnits(profileFunction.getUnits());
} }
@Override @Override
@ -215,30 +225,30 @@ public class BgReading implements DataPointWithLabelInterface {
@Override @Override
public int getColor() { public int getColor() {
String units = ProfileFunctions.getSystemUnits(); String units = profileFunction.getUnits();
Double lowLine = OverviewPlugin.INSTANCE.determineLowLine(); Double lowLine = defaultValueHelper.determineLowLine();
Double highLine = OverviewPlugin.INSTANCE.determineHighLine(); Double highLine = defaultValueHelper.determineHighLine();
int color = MainApp.gc(R.color.inrange); int color = resourceHelper.gc(R.color.inrange);
if (isPrediction()) if (isPrediction())
return getPredectionColor(); return getPredectionColor();
else if (valueToUnits(units) < lowLine) else if (valueToUnits(units) < lowLine)
color = MainApp.gc(R.color.low); color = resourceHelper.gc(R.color.low);
else if (valueToUnits(units) > highLine) else if (valueToUnits(units) > highLine)
color = MainApp.gc(R.color.high); color = resourceHelper.gc(R.color.high);
return color; return color;
} }
public int getPredectionColor() { public int getPredectionColor() {
if (isIOBPrediction) if (isIOBPrediction)
return MainApp.gc(R.color.iob); return resourceHelper.gc(R.color.iob);
if (isCOBPrediction) if (isCOBPrediction)
return MainApp.gc(R.color.cob); return resourceHelper.gc(R.color.cob);
if (isaCOBPrediction) if (isaCOBPrediction)
return 0x80FFFFFF & MainApp.gc(R.color.cob); return 0x80FFFFFF & resourceHelper.gc(R.color.cob);
if (isUAMPrediction) if (isUAMPrediction)
return MainApp.gc(R.color.uam); return resourceHelper.gc(R.color.uam);
if (isZTPrediction) if (isZTPrediction)
return MainApp.gc(R.color.zt); return resourceHelper.gc(R.color.zt);
return R.color.mdtp_white; return R.color.mdtp_white;
} }
@ -270,8 +280,7 @@ public class BgReading implements DataPointWithLabelInterface {
else else
slope = (previous.value - current.value) / (previous.date - current.date); slope = (previous.value - current.value) / (previous.date - current.date);
if (L.isEnabled(L.GLUCOSE)) aapsLogger.error(LTag.GLUCOSE, "Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.date - previous.date));
log.debug("Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.date - previous.date));
double slope_by_minute = slope * 60000; double slope_by_minute = slope * 60000;
String arrow = "NONE"; String arrow = "NONE";
@ -291,8 +300,7 @@ public class BgReading implements DataPointWithLabelInterface {
} else if (slope_by_minute <= (40)) { } else if (slope_by_minute <= (40)) {
arrow = "DoubleUp"; arrow = "DoubleUp";
} }
if (L.isEnabled(L.GLUCOSE)) aapsLogger.error(LTag.GLUCOSE, "Direction set to: " + arrow);
log.debug("Direction set to: " + arrow);
return arrow; return arrow;
} }
} }

View file

@ -9,7 +9,6 @@ import org.apache.commons.lang3.StringUtils;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -25,7 +24,8 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg; import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg;
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
@ -36,7 +36,7 @@ import info.nightscout.androidaps.utils.Translator;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS)
public class CareportalEvent implements DataPointWithLabelInterface, Interval { public class CareportalEvent implements DataPointWithLabelInterface, Interval {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;
@ -107,10 +107,6 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours; return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours;
} }
public String age() {
return age(OverviewFragment.shorttextmode);
}
public boolean isOlderThan(double hours) { public boolean isOlderThan(double hours) {
return getHoursFromStart() > hours; return getHoursFromStart() > hours;
} }
@ -149,7 +145,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
CareportalEvent event = list.get(i); CareportalEvent event = list.get(i);
if (event.date <= time && event.date > (time - T.mins(5).msecs())) { if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Found event for time: " + DateUtil.dateAndTimeFullString(time) + " " + event.toString()); log.debug("Found event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
return true; return true;
} }
} }
@ -167,7 +163,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
@Override @Override
public double getY() { public double getY() {
String units = ProfileFunctions.getSystemUnits(); String units = ConfigBuilderPlugin.getPlugin().getProfileFunction().getUnits();
if (eventType.equals(MBG)) { if (eventType.equals(MBG)) {
double mbg = 0d; double mbg = 0d;
try { try {
@ -260,7 +256,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
@Override @Override
public float getSize() { public float getSize() {
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet); boolean isTablet = MainApp.resources().getBoolean(R.bool.isTablet);
return isTablet ? 12 : 10; return isTablet ? 12 : 10;
} }

View file

@ -18,7 +18,6 @@ import com.j256.ormlite.table.TableUtils;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +31,6 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.data.NonOverlappingIntervals; import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
@ -48,12 +46,12 @@ import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistory;
import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID; import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID;
import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset; import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset;
@ -73,7 +71,7 @@ import info.nightscout.androidaps.utils.ToastUtils;
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service. * direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
*/ */
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_NAME = "AndroidAPSDb";
public static final String DATABASE_BGREADINGS = "BgReadings"; public static final String DATABASE_BGREADINGS = "BgReadings";
@ -138,7 +136,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
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);
//TableUtils.dropTable(connectionSource, PodHistory.class, true);
TableUtils.createTableIfNotExists(connectionSource, PodHistory.class); TableUtils.createTableIfNotExists(connectionSource, PodHistory.class);
database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " + database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " +
"WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")"); "WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")");
@ -231,7 +228,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
VirtualPumpPlugin.getPlugin().setFakingStatus(true); VirtualPumpPlugin.Companion.getPlugin().setFakingStatus(true);
scheduleBgChange(null); // trigger refresh scheduleBgChange(null); // trigger refresh
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
scheduleExtendedBolusChange(); scheduleExtendedBolusChange();
@ -242,7 +239,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
new java.util.TimerTask() { new java.util.TimerTask() {
@Override @Override
public void run() { public void run() {
RxBus.INSTANCE.send(new EventRefreshOverview("resetDatabases")); RxBus.Companion.getINSTANCE().send(new EventRefreshOverview("resetDatabases", false));
} }
}, },
3000 3000
@ -267,7 +264,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
VirtualPumpPlugin.getPlugin().setFakingStatus(false); VirtualPumpPlugin.Companion.getPlugin().setFakingStatus(false);
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
} }
@ -415,7 +412,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing EventNewBg"); log.debug("Firing EventNewBg");
RxBus.INSTANCE.send(new EventNewBG(bgReading)); RxBus.Companion.getINSTANCE().send(new EventNewBG(bgReading));
scheduledBgPost = null; scheduledBgPost = null;
} }
} }
@ -429,40 +426,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
/*
* Return last BgReading from database or null if db is empty
*/
@Nullable
public static BgReading lastBg() {
List<BgReading> bgList = IobCobCalculatorPlugin.getPlugin().getBgReadings();
if (bgList == null)
return null;
for (int i = 0; i < bgList.size(); i++)
if (bgList.get(i).value >= 39)
return bgList.get(i);
return null;
}
/*
* Return bg reading if not old ( <9 min )
* or null if older
*/
@Nullable
public static BgReading actualBg() {
BgReading lastBg = lastBg();
if (lastBg == null)
return null;
if (lastBg.date > System.currentTimeMillis() - 9 * 60 * 1000)
return lastBg;
return null;
}
public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) { public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) {
try { try {
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings(); Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
@ -736,7 +699,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing EventTempTargetChange"); log.debug("Firing EventTempTargetChange");
RxBus.INSTANCE.send(new EventTempTargetChange()); RxBus.Companion.getINSTANCE().send(new EventTempTargetChange());
scheduledTemTargetPost = null; scheduledTemTargetPost = null;
} }
} }
@ -843,31 +806,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return historyList; return historyList;
} }
public void updateDanaRHistoryRecordId(JSONObject trJson) {
try {
QueryBuilder<DanaRHistoryRecord, String> queryBuilder = getDaoDanaRHistory().queryBuilder();
Where where = queryBuilder.where();
where.ge("bytes", trJson.get(DanaRNSHistorySync.DANARSIGNATURE));
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
List<DanaRHistoryRecord> list = getDaoDanaRHistory().query(preparedQuery);
if (list.size() == 0) {
// Record does not exists. Ignore
} else if (list.size() == 1) {
DanaRHistoryRecord record = list.get(0);
if (record._id == null || !record._id.equals(trJson.getString("_id"))) {
if (L.isEnabled(L.DATABASE))
log.debug("Updating _id in DanaR history database: " + trJson.getString("_id"));
record._id = trJson.getString("_id");
getDaoDanaRHistory().update(record);
} else {
// already set
}
}
} catch (SQLException | JSONException e) {
log.error("Unhandled exception: " + trJson.toString(), e);
}
}
// ------------ TemporaryBasal handling --------------- // ------------ TemporaryBasal handling ---------------
//return true if new record was created //return true if new record was created
@ -1033,10 +971,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing EventTempBasalChange"); log.debug("Firing EventTempBasalChange");
RxBus.INSTANCE.send(new EventReloadTempBasalData()); RxBus.Companion.getINSTANCE().send(new EventReloadTempBasalData());
RxBus.INSTANCE.send(new EventTempBasalChange()); RxBus.Companion.getINSTANCE().send(new EventTempBasalChange());
if (earliestDataChange != null) if (earliestDataChange != null)
RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange)); RxBus.Companion.getINSTANCE().send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null; earliestDataChange = null;
scheduledTemBasalsPost = null; scheduledTemBasalsPost = null;
} }
@ -1078,8 +1016,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
.insulin(trJson.getDouble("originalExtendedAmount")) .insulin(trJson.getDouble("originalExtendedAmount"))
._id(trJson.getString("_id")); ._id(trJson.getString("_id"));
// if faking found in NS, adapt AAPS to use it too // if faking found in NS, adapt AAPS to use it too
if (!VirtualPumpPlugin.getPlugin().getFakingStatus()) { if (!VirtualPumpPlugin.Companion.getPlugin().getFakingStatus()) {
VirtualPumpPlugin.getPlugin().setFakingStatus(true); VirtualPumpPlugin.Companion.getPlugin().setFakingStatus(true);
updateEarliestDataChange(0); updateEarliestDataChange(0);
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
} }
@ -1093,8 +1031,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
extendedBolus.insulin = 0; extendedBolus.insulin = 0;
extendedBolus._id = trJson.getString("_id"); extendedBolus._id = trJson.getString("_id");
// if faking found in NS, adapt AAPS to use it too // if faking found in NS, adapt AAPS to use it too
if (!VirtualPumpPlugin.getPlugin().getFakingStatus()) { if (!VirtualPumpPlugin.Companion.getPlugin().getFakingStatus()) {
VirtualPumpPlugin.getPlugin().setFakingStatus(true); VirtualPumpPlugin.Companion.getPlugin().setFakingStatus(true);
updateEarliestDataChange(0); updateEarliestDataChange(0);
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
} }
@ -1369,9 +1307,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing EventExtendedBolusChange"); log.debug("Firing EventExtendedBolusChange");
RxBus.INSTANCE.send(new EventReloadTreatmentData(new EventExtendedBolusChange())); RxBus.Companion.getINSTANCE().send(new EventReloadTreatmentData(new EventExtendedBolusChange()));
if (earliestDataChange != null) if (earliestDataChange != null)
RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange)); RxBus.Companion.getINSTANCE().send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null; earliestDataChange = null;
scheduledExtendedBolusPost = null; scheduledExtendedBolusPost = null;
} }
@ -1579,7 +1517,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing scheduleCareportalEventChange"); log.debug("Firing scheduleCareportalEventChange");
RxBus.INSTANCE.send(new EventCareportalEventChange()); RxBus.Companion.getINSTANCE().send(new EventCareportalEventChange());
scheduledCareportalEventPost = null; scheduledCareportalEventPost = null;
} }
} }
@ -1752,8 +1690,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void run() { public void run() {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Firing EventProfileNeedsUpdate"); log.debug("Firing EventProfileNeedsUpdate");
RxBus.INSTANCE.send(new EventReloadProfileSwitchData()); RxBus.Companion.getINSTANCE().send(new EventReloadProfileSwitchData());
RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); RxBus.Companion.getINSTANCE().send(new EventProfileNeedsUpdate());
scheduledProfileSwitchEventPost = null; scheduledProfileSwitchEventPost = null;
} }
} }
@ -1781,7 +1719,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) { public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) {
try { try {
ProfileSwitch profileSwitch = new ProfileSwitch(); ProfileSwitch profileSwitch = new ProfileSwitch(MainApp.instance().injector);
profileSwitch.date = trJson.getLong("mills"); profileSwitch.date = trJson.getLong("mills");
if (trJson.has("duration")) if (trJson.has("duration"))
profileSwitch.durationInMinutes = trJson.getInt("duration"); profileSwitch.durationInMinutes = trJson.getInt("duration");
@ -1796,8 +1734,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (trJson.has("profileJson")) if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson"); profileSwitch.profileJson = trJson.getString("profileJson");
else { else {
ProfileInterface profileInterface = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); ProfileInterface profileInterface = PluginStore.Companion.getInstance().getActiveProfileInterface();
if (profileInterface != null) {
ProfileStore store = profileInterface.getProfile(); ProfileStore store = profileInterface.getProfile();
if (store != null) { if (store != null) {
Profile profile = store.getSpecificProfile(profileSwitch.profileName); Profile profile = store.getSpecificProfile(profileSwitch.profileName);
@ -1817,11 +1754,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString()); log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString());
return; return;
} }
} else {
if (L.isEnabled(L.DATABASE))
log.debug("No active profile interface. Ignoring: " + trJson.toString());
return;
}
} }
if (trJson.has("profilePlugin")) if (trJson.has("profilePlugin"))
profileSwitch.profilePlugin = trJson.getString("profilePlugin"); profileSwitch.profilePlugin = trJson.getString("profilePlugin");

View file

@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
/** /**
@ -20,7 +21,7 @@ import info.nightscout.androidaps.utils.DateUtil;
*/ */
@DatabaseTable(tableName = DatabaseHelper.DATABASE_DBREQUESTS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_DBREQUESTS)
public class DbRequest { public class DbRequest {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public String nsClientID = null; public String nsClientID = null;

View file

@ -11,7 +11,6 @@ import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
@ -22,7 +21,8 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
@ -38,7 +38,7 @@ import info.nightscout.androidaps.utils.Round;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_EXTENDEDBOLUSES) @DatabaseTable(tableName = DatabaseHelper.DATABASE_EXTENDEDBOLUSES)
public class ExtendedBolus implements Interval, DataPointWithLabelInterface { public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;
@ -219,7 +219,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
public IobTotal iobCalc(long time) { public IobTotal iobCalc(long time) {
IobTotal result = new IobTotal(time); IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = PluginStore.Companion.getInstance().getActiveInsulin();
double realDuration = getDurationToTime(time); double realDuration = getDurationToTime(time);
@ -251,7 +251,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) { public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
IobTotal result = new IobTotal(time); IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = PluginStore.Companion.getInstance().getActiveInsulin();
double realDuration = getDurationToTime(time); double realDuration = getDurationToTime(time);
double netBasalAmount = 0d; double netBasalAmount = 0d;

View file

@ -9,18 +9,20 @@ import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus; 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.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
@ -30,10 +32,10 @@ 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.T; import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES) @DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
public class ProfileSwitch implements Interval, DataPointWithLabelInterface { public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;
@ -67,6 +69,22 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private Profile profile = null; private Profile profile = null;
HasAndroidInjector injector;
@Inject public TreatmentsPlugin treatmentsPlugin;
@Inject public AAPSLogger aapsLogger;
@Inject public RxBusWrapper rxBus;
@Inject public ResourceHelper resourceHelper;
public ProfileSwitch() {
this.injector = MainApp.instance().injector;
injector.androidInjector().inject(this);
}
public ProfileSwitch(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
this.injector = injector;
}
public ProfileSwitch date(long date) { public ProfileSwitch date(long date) {
this.date = date; this.date = date;
return this; return this;
@ -96,10 +114,10 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
public Profile getProfileObject() { public Profile getProfileObject() {
if (profile == null) if (profile == null)
try { try {
profile = new Profile(new JSONObject(profileJson), percentage, timeshift); profile = new Profile(injector, new JSONObject(profileJson), percentage, timeshift);
} catch (Exception e) { } catch (Exception e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
log.error("Unhandled exception", profileJson); aapsLogger.error("Unhandled exception: " + profileJson);
} }
return profile; return profile;
} }
@ -111,7 +129,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
*/ */
public String getCustomizedName() { public String getCustomizedName() {
String name = profileName; String name = profileName;
if (LocalProfilePlugin.LOCAL_PROFILE.equals(name)) { if (LocalProfilePlugin.Companion.getLOCAL_PROFILE().equals(name)) {
name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U "; name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U ";
} }
if (isCPP) { if (isCPP) {
@ -217,7 +235,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@Override @Override
public boolean isValid() { public boolean isValid() {
boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date)); boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date));
ProfileSwitch active = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()); ProfileSwitch active = treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now());
long activeProfileSwitchDate = active != null ? active.date : -1L; long activeProfileSwitchDate = active != null ? active.date : -1L;
if (!isValid && date == activeProfileSwitchDate) if (!isValid && date == activeProfileSwitchDate)
createNotificationInvalidProfile(DateUtil.dateAndTimeString(date)); createNotificationInvalidProfile(DateUtil.dateAndTimeString(date));
@ -225,23 +243,23 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
} }
private void createNotificationInvalidProfile(String detail) { private void createNotificationInvalidProfile(String detail) {
Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, String.format(MainApp.gs(R.string.zerovalueinprofile), detail), Notification.LOW, 5); Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, resourceHelper.gs(R.string.zerovalueinprofile, detail), Notification.LOW, 5);
RxBus.INSTANCE.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
} }
public static boolean isEvent5minBack(List<ProfileSwitch> list, long time, boolean zeroDurationOnly) { public static boolean isEvent5minBack(AAPSLogger aapsLogger, List<ProfileSwitch> list, long time, boolean zeroDurationOnly) {
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
ProfileSwitch event = list.get(i); ProfileSwitch event = list.get(i);
if (event.date <= time && event.date > (time - T.mins(5).msecs())) { if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
if (zeroDurationOnly) { if (zeroDurationOnly) {
if (event.durationInMinutes == 0) { if (event.durationInMinutes == 0) {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeFullString(time) + " " + event.toString()); aapsLogger.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
return true; return true;
} }
} else { } else {
if (L.isEnabled(L.DATABASE)) if (L.isEnabled(L.DATABASE))
log.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeFullString(time) + " " + event.toString()); aapsLogger.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
return true; return true;
} }
} }

View file

@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
@ -19,7 +20,7 @@ import info.nightscout.androidaps.utils.DateUtil;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS)
public class TDD { public class TDD {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;

View file

@ -14,12 +14,13 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS)
public class TempTarget implements Interval { public class TempTarget implements Interval {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;

View file

@ -4,7 +4,6 @@ import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
@ -15,8 +14,9 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
@ -29,7 +29,7 @@ import info.nightscout.androidaps.utils.SP;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS)
public class TemporaryBasal implements Interval, DbObjectBase { public class TemporaryBasal implements Interval, DbObjectBase {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
public long date; public long date;
@ -95,7 +95,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
public TemporaryBasal(ExtendedBolus extendedBolus) { public TemporaryBasal(ExtendedBolus extendedBolus) {
double basal = ProfileFunctions.getInstance().getProfile(extendedBolus.date).getBasal(extendedBolus.date); double basal = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile(extendedBolus.date).getBasal(extendedBolus.date);
this.date = extendedBolus.date; this.date = extendedBolus.date;
this.isValid = extendedBolus.isValid; this.isValid = extendedBolus.isValid;
this.source = extendedBolus.source; this.source = extendedBolus.source;
@ -236,7 +236,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
IobTotal result = new IobTotal(time); IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = PluginStore.Companion.getInstance().getActiveInsulin();
int realDuration = getDurationToTime(time); int realDuration = getDurationToTime(time);
double netBasalAmount = 0d; double netBasalAmount = 0d;
@ -291,7 +291,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
IobTotal result = new IobTotal(time); IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = PluginStore.Companion.getInstance().getActiveInsulin();
double realDuration = getDurationToTime(time); double realDuration = getDurationToTime(time);
double netBasalAmount = 0d; double netBasalAmount = 0d;
@ -404,7 +404,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
public String toStringFull() { public String toStringFull() {
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile();
if (profile == null) if (profile == null)
return "null"; return "null";
Double currentBasalRate = profile.getBasal(); Double currentBasalRate = profile.getBasal();
@ -428,7 +428,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
double rate; double rate;
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile();
if (profile == null) if (profile == null)
return "null"; return "null";
double currentBasalRate = profile.getBasal(); double currentBasalRate = profile.getBasal();
@ -438,7 +438,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) { if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile();
if (profile != null) { if (profile != null) {
double basal = profile.getBasal(); double basal = profile.getBasal();
if (basal != 0) { if (basal != 0) {
@ -453,7 +453,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
private String getCalcuatedPercentageIfNeeded() { private String getCalcuatedPercentageIfNeeded() {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile();
if (profile == null) if (profile == null)
return "null"; return "null";
@ -479,7 +479,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
public String toStringVeryShort() { public String toStringVeryShort() {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ConfigBuilderPlugin.getPlugin().getProfileFunction().getProfile();
if (profile == null) if (profile == null)
return "null"; return "null";

View file

@ -0,0 +1,51 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.MainActivity
import info.nightscout.androidaps.activities.*
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity
import info.nightscout.androidaps.plugins.pump.common.dialog.RileyLinkBLEScanActivity
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity
import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRHistoryActivity
import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRUserOptionsActivity
import info.nightscout.androidaps.plugins.pump.danaRS.activities.BLEScanActivity
import info.nightscout.androidaps.plugins.pump.danaRS.activities.PairingHelperActivity
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingActivity
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingInformationActivity
import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
@Module
@Suppress("unused")
abstract class ActivitiesModule {
@ContributesAndroidInjector abstract fun contributesBLEScanActivity(): BLEScanActivity
@ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity
@ContributesAndroidInjector abstract fun contributeDanaRHistoryActivity(): DanaRHistoryActivity
@ContributesAndroidInjector abstract fun contributeDanaRUserOptionsActivity(): DanaRUserOptionsActivity
@ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity
@ContributesAndroidInjector abstract fun contributesHistoryBrowseActivity(): HistoryBrowseActivity
@ContributesAndroidInjector abstract fun contributesInsightAlertActivity(): InsightAlertActivity
@ContributesAndroidInjector abstract fun contributesInsightPairingActivity(): InsightPairingActivity
@ContributesAndroidInjector abstract fun contributesInsightPairingInformationActivity(): InsightPairingInformationActivity
@ContributesAndroidInjector abstract fun contributesLogSettingActivity(): LogSettingActivity
@ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity
@ContributesAndroidInjector abstract fun contributesMedtronicHistoryActivity(): MedtronicHistoryActivity
@ContributesAndroidInjector abstract fun contributesPairingHelperActivity(): PairingHelperActivity
@ContributesAndroidInjector abstract fun contributesPreferencesActivity(): PreferencesActivity
@ContributesAndroidInjector abstract fun contributesQuickWizardListActivity(): QuickWizardListActivity
@ContributesAndroidInjector abstract fun contributesRequestDexcomPermissionActivity(): RequestDexcomPermissionActivity
@ContributesAndroidInjector abstract fun contributesRileyLinkStatusActivity(): RileyLinkStatusActivity
@ContributesAndroidInjector abstract fun contributesRileyLinkBLEScanActivity(): RileyLinkBLEScanActivity
@ContributesAndroidInjector abstract fun contributesSetupWizardActivity(): SetupWizardActivity
@ContributesAndroidInjector abstract fun contributesSingleFragmentActivity(): SingleFragmentActivity
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorOtpActivity(): SmsCommunicatorOtpActivity
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
}

View file

@ -0,0 +1,192 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.BindsInstance
import dagger.Component
import dagger.android.AndroidInjectionModule
import dagger.android.AndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.ProfileStore
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.BgReading
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
import info.nightscout.androidaps.plugins.general.automation.actions.*
import info.nightscout.androidaps.plugins.general.automation.elements.*
import info.nightscout.androidaps.plugins.general.automation.triggers.*
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.general.smsCommunicator.AuthRequest
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
import info.nightscout.androidaps.plugins.treatments.Treatment
import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.setupwizard.SWEventListener
import info.nightscout.androidaps.setupwizard.SWScreen
import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.utils.wizard.BolusWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import javax.inject.Singleton
@Singleton
@Component(
modules = [
AndroidInjectionModule::class,
ActivitiesModule::class,
FragmentsModule::class,
AppModule::class,
ReceiversModule::class,
ServicesModule::class
]
)
interface AppComponent : AndroidInjector<MainApp> {
fun injectProfileStore(profileStore: ProfileStore)
fun injectPumpEnactResult(pumpEnactResult: PumpEnactResult)
fun injectAPSResult(apsResult: APSResult)
fun injectDetermineBasalResultSMB(determineBasalResultSMB: DetermineBasalResultSMB)
fun injectDetermineBasalResultAMA(determineBasalResultAMA: DetermineBasalResultAMA)
fun injectDetermineBasalAdapterSMBJS(determineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS)
fun injectCommandQueue(commandQueue: CommandQueue)
fun injectCommandBolus(commandBolus: CommandBolus)
fun injectCommandCancelExtendedBolus(commandCancelExtendedBolus: CommandCancelExtendedBolus)
fun injectCommandCancelTempBasal(commandCancelTempBasal: CommandCancelTempBasal)
fun injectCommandExtendedBolus(commandExtendedBolus: CommandExtendedBolus)
fun injectCommandInsightSetTBROverNotification(commandInsightSetTBROverNotification: CommandInsightSetTBROverNotification)
fun injectCommandLoadEvents(commandLoadEvents: CommandLoadEvents)
fun injectCommandLoadHistory(commandLoadHistory: CommandLoadHistory)
fun injectCommandLoadTDDs(commandLoadTDDs: CommandLoadTDDs)
fun injectCommandReadStatus(commandReadStatus: CommandReadStatus)
fun injectCommandSetProfile(commandSetProfile: CommandSetProfile)
fun injectCommandCommandSMBBolus(commandSMBBolus: CommandSMBBolus)
fun injectCommandStartPump(commandStartPump: CommandStartPump)
fun injectCommandStopPump(commandStopPump: CommandStopPump)
fun injectCommandTempBasalAbsolute(commandTempBasalAbsolute: CommandTempBasalAbsolute)
fun injectCommandTempBasalPercent(commandTempBasalPercent: CommandTempBasalPercent)
fun injectCommandSetUserSettings(commandSetUserSettings: CommandSetUserSettings)
fun injectObjective(objective: Objective)
fun injectObjective0(objective0: Objective0)
fun injectObjective1(objective1: Objective1)
fun injectObjective2(objective2: Objective2)
fun injectObjective3(objective3: Objective3)
fun injectObjective4(objective4: Objective4)
fun injectObjective5(objective5: Objective5)
fun injectObjective6(objective6: Objective6)
fun injectObjective7(objective7: Objective7)
fun injectObjective8(objective8: Objective8)
fun injectObjective9(objective9: Objective9)
fun injectObjective10(objective10: Objective10)
fun injectAutomationEvent(automationEvent: AutomationEvent)
fun injectTrigger(trigger: Trigger)
fun injectTrigger(triggerAutosensValue: TriggerAutosensValue)
fun injectTrigger(triggerBg: TriggerBg)
fun injectTrigger(triggerBolusAgo: TriggerBolusAgo)
fun injectTrigger(triggerBTDevice: TriggerBTDevice)
fun injectTrigger(triggerCOB: TriggerCOB)
fun injectTrigger(triggerConnector: TriggerConnector)
fun injectTrigger(triggerDelta: TriggerDelta)
fun injectTrigger(triggerDummy: TriggerDummy)
fun injectTrigger(triggerIob: TriggerIob)
fun injectTrigger(triggerLocation: TriggerLocation)
fun injectTrigger(triggerProfilePercent: TriggerProfilePercent)
fun injectTrigger(triggerPumpLastConnection: TriggerPumpLastConnection)
fun injectTrigger(triggerRecurringTime: TriggerRecurringTime)
fun injectTrigger(triggerTempTarget: TriggerTempTarget)
fun injectTrigger(triggerTime: TriggerTime)
fun injectTrigger(triggerTimeRange: TriggerTimeRange)
fun injectTrigger(triggerWifiSsid: TriggerWifiSsid)
fun injectAction(action: Action)
fun injectActionDummy(action: ActionDummy)
fun injectActionLoopDisable(action: ActionLoopDisable)
fun injectActionLoopEnable(action: ActionLoopEnable)
fun injectActionLoopResume(action: ActionLoopResume)
fun injectAction(action: ActionLoopSuspend)
fun injectActionLoopSuspend(action: ActionNotification)
fun injectActionProfileSwitch(action: ActionProfileSwitch)
fun injectAction(action: ActionProfileSwitchPercent)
fun injectActionProfileSwitchPercent(action: ActionSendSMS)
fun injectActionStartTempTarget(action: ActionStartTempTarget)
fun injectActionStopTempTarget(action: ActionStopTempTarget)
fun injectElement(element: Element)
fun injectElement(inputBg: InputBg)
fun injectElement(inputButton: InputButton)
fun injectElement(comparator: Comparator)
fun injectElement(comparatorExists: ComparatorExists)
fun injectElement(comparatorConnect: ComparatorConnect)
fun injectElement(inputDateTime: InputDateTime)
fun injectElement(inputDelta: InputDelta)
fun injectElement(inputDropdownMenu: InputDropdownMenu)
fun injectElement(inputDouble: InputDouble)
fun injectElement(inputDuration: InputDuration)
fun injectElement(inputInsulin: InputInsulin)
fun injectElement(inputLocationMode: InputLocationMode)
fun injectElement(inputPercent: InputPercent)
fun injectElement(inputProfileName: InputProfileName)
fun injectElement(inputString: InputString)
fun injectElement(inputTempTarget: InputTempTarget)
fun injectElement(inputTimeRange: InputTimeRange)
fun injectElement(inputTime: InputTime)
fun injectElement(inputWeekDay: InputWeekDay)
fun injectElement(labelWithElement: LabelWithElement)
fun injectElement(staticLabel: StaticLabel)
fun injectAutosensDate(autosensData: AutosensData)
fun injectIobCobThread(iobCobThread: IobCobThread)
fun injectIobCobOref1Thread(iobCobOref1Thread: IobCobOref1Thread)
fun injectTreatment(treatment: Treatment)
fun injectBgReading(bgReading: BgReading)
fun injectProfileSwitch(profileSwitch: ProfileSwitch)
fun injectNotification(notificationWithAction: NotificationWithAction)
fun injectLoggerCallback(loggerCallback: LoggerCallback)
fun injectBolusWizard(bolusWizard: BolusWizard)
fun injectQuickWizardEntry(quickWizardEntry: QuickWizardEntry)
fun injectAuthRequest(authRequest: AuthRequest)
fun injectSWBreak(swBreak: SWBreak)
fun injectSWButton(swButton: SWButton)
fun injectSWEditNumberWithUnits(swEditNumberWithUnits: SWEditNumberWithUnits)
fun injectSWEditString(swEditString: SWEditString)
fun injectSWEditEncryptedPassword(swSWEditEncryptedPassword: SWEditEncryptedPassword)
fun injectSWEditUrl(swEditUrl: SWEditUrl)
fun injectSWFragment(swFragment: SWFragment)
fun injectSSWHtmlLink(swHtmlLink: SWHtmlLink)
fun injectSWInfotext(swInfotext: SWInfotext)
fun injectSWItem(swItem: SWItem)
fun injectSWPlugin(swPlugin: SWPlugin)
fun injectSWRadioButton(swRadioButton: SWRadioButton)
fun injectSWScreen(swScreen: SWScreen)
fun injectSWEventListener(swEventListener: SWEventListener)
fun injectProfile(profile: Profile)
fun injectGlucoseStatus(glucoseStatus: GlucoseStatus)
fun injectGraphData(graphData: GraphData)
@Component.Builder
interface Builder {
@BindsInstance
fun application(mainApp: MainApp): Builder
fun build(): AppComponent
}
}

View file

@ -0,0 +1,279 @@
package info.nightscout.androidaps.dependencyInjection
import android.content.Context
import androidx.preference.PreferenceManager
import dagger.Binds
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.android.ContributesAndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.ProfileStore
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.db.BgReading
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.AAPSLoggerProduction
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
import info.nightscout.androidaps.plugins.general.automation.actions.*
import info.nightscout.androidaps.plugins.general.automation.elements.*
import info.nightscout.androidaps.plugins.general.automation.triggers.*
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.general.smsCommunicator.AuthRequest
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
import info.nightscout.androidaps.plugins.treatments.Treatment
import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.setupwizard.SWEventListener
import info.nightscout.androidaps.setupwizard.SWScreen
import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.utils.CryptoUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.sharedPreferences.SPImplementation
import info.nightscout.androidaps.utils.storage.FileStorage
import info.nightscout.androidaps.utils.storage.Storage
import info.nightscout.androidaps.utils.wizard.BolusWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import javax.inject.Singleton
@Module(includes = [AppModule.AppBindings::class, PluginsModule::class])
open class AppModule {
@Provides
@Singleton
fun provideSharedPreferences(context: Context, resourceHelper: ResourceHelper): SP {
return SPImplementation(PreferenceManager.getDefaultSharedPreferences(context), resourceHelper)
}
@Provides
@Singleton
fun provideProfileFunction(injector: HasAndroidInjector, aapsLogger: AAPSLogger, sp: SP, resourceHelper: ResourceHelper, activePlugin: ActivePluginProvider, fabricPrivacy: FabricPrivacy): ProfileFunction {
return ProfileFunctionImplementation(injector, aapsLogger, sp, resourceHelper, activePlugin, fabricPrivacy)
}
@Provides
@Singleton
fun provideResources(mainApp: MainApp): ResourceHelper {
return ResourceHelperImplementation(mainApp)
}
@Provides
@Singleton
fun provideAAPSLogger(): AAPSLogger {
return AAPSLoggerProduction()
/* if (BuildConfig.DEBUG) {
AAPSLoggerDebug()
} else {
AAPSLoggerProduction()
}
*/
}
@Provides
fun providesPlugins(@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
@PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
@PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>): List<@JvmSuppressWildcards PluginBase> {
val plugins = allConfigs.toMutableMap()
if (Config.PUMPDRIVERS) plugins += pumpDrivers.get()
if (Config.APS) plugins += aps.get()
if (!Config.NSCLIENT) plugins += notNsClient.get()
return plugins.toList().sortedBy { it.first }.map { it.second }
}
@Provides
@Singleton
fun provideStorage(): Storage {
return FileStorage()
}
@Module
interface AppBindings {
@ContributesAndroidInjector fun profileStoreInjector(): ProfileStore
@ContributesAndroidInjector fun pumpEnactResultInjector(): PumpEnactResult
@ContributesAndroidInjector fun apsResultInjector(): APSResult
@ContributesAndroidInjector fun determineBasalResultSMBInjector(): DetermineBasalResultSMB
@ContributesAndroidInjector fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
@ContributesAndroidInjector
fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector fun commandQueueInjector(): CommandQueue
@ContributesAndroidInjector fun commandBolusInjector(): CommandBolus
@ContributesAndroidInjector
fun commandCancelExtendedBolusInjector(): CommandCancelExtendedBolus
@ContributesAndroidInjector fun commandCancelTempBasalInjector(): CommandCancelTempBasal
@ContributesAndroidInjector fun commandExtendedBolusInjector(): CommandExtendedBolus
@ContributesAndroidInjector
fun commandInsightSetTBROverNotificationInjector(): CommandInsightSetTBROverNotification
@ContributesAndroidInjector fun commandLoadEventsInjector(): CommandLoadEvents
@ContributesAndroidInjector fun commandLoadHistoryInjector(): CommandLoadHistory
@ContributesAndroidInjector fun commandLoadTDDsInjector(): CommandLoadTDDs
@ContributesAndroidInjector fun commandReadStatusInjector(): CommandReadStatus
@ContributesAndroidInjector fun commandSetProfileInjector(): CommandSetProfile
@ContributesAndroidInjector fun commandCommandSMBBolusInjector(): CommandSMBBolus
@ContributesAndroidInjector fun commandStartPumpInjector(): CommandStartPump
@ContributesAndroidInjector fun commandStopPumpInjector(): CommandStopPump
@ContributesAndroidInjector fun commandTempBasalAbsoluteInjector(): CommandTempBasalAbsolute
@ContributesAndroidInjector fun commandTempBasalPercentInjector(): CommandTempBasalPercent
@ContributesAndroidInjector fun commandSetUserSettingsInjector(): CommandSetUserSettings
@ContributesAndroidInjector fun objectiveInjector(): Objective
@ContributesAndroidInjector fun objective0Injector(): Objective0
@ContributesAndroidInjector fun objective1Injector(): Objective1
@ContributesAndroidInjector fun objective2Injector(): Objective2
@ContributesAndroidInjector fun objective3Injector(): Objective3
@ContributesAndroidInjector fun objective4Injector(): Objective4
@ContributesAndroidInjector fun objective5Injector(): Objective5
@ContributesAndroidInjector fun objective6Injector(): Objective6
@ContributesAndroidInjector fun objective7Injector(): Objective7
@ContributesAndroidInjector fun objective8Injector(): Objective8
@ContributesAndroidInjector fun objective9Injector(): Objective9
@ContributesAndroidInjector fun objective10Injector(): Objective10
@ContributesAndroidInjector fun automationEventInjector(): AutomationEvent
@ContributesAndroidInjector fun triggerInjector(): Trigger
@ContributesAndroidInjector fun triggerAutosensValueInjector(): TriggerAutosensValue
@ContributesAndroidInjector fun triggerBgInjector(): TriggerBg
@ContributesAndroidInjector fun triggerBolusAgoInjector(): TriggerBolusAgo
@ContributesAndroidInjector fun triggerCOBInjector(): TriggerCOB
@ContributesAndroidInjector fun triggerConnectorInjector(): TriggerConnector
@ContributesAndroidInjector fun triggerDeltaInjector(): TriggerDelta
@ContributesAndroidInjector fun triggerDummyInjector(): TriggerDummy
@ContributesAndroidInjector fun triggerIobInjector(): TriggerIob
@ContributesAndroidInjector fun triggerLocationInjector(): TriggerLocation
@ContributesAndroidInjector fun triggerProfilePercentInjector(): TriggerProfilePercent
@ContributesAndroidInjector
fun triggerPumpLastConnectionInjector(): TriggerPumpLastConnection
@ContributesAndroidInjector fun triggerBTDeviceInjector(): TriggerBTDevice
@ContributesAndroidInjector fun triggerRecurringTimeInjector(): TriggerRecurringTime
@ContributesAndroidInjector fun triggerTempTargetInjector(): TriggerTempTarget
@ContributesAndroidInjector fun triggerTime(): TriggerTime
@ContributesAndroidInjector fun triggerTimeRangeInjector(): TriggerTimeRange
@ContributesAndroidInjector fun triggerWifiSsidInjector(): TriggerWifiSsid
@ContributesAndroidInjector fun actionInjector(): Action
@ContributesAndroidInjector fun actionLoopDisableInjector(): ActionLoopDisable
@ContributesAndroidInjector fun actionLoopEnableInjector(): ActionLoopEnable
@ContributesAndroidInjector fun actionLoopResumeInjector(): ActionLoopResume
@ContributesAndroidInjector fun actionLoopSuspendInjector(): ActionLoopSuspend
@ContributesAndroidInjector fun actionNotificationInjector(): ActionNotification
@ContributesAndroidInjector fun actionProfileSwitchInjector(): ActionProfileSwitch
@ContributesAndroidInjector
fun actionProfileSwitchPercentInjector(): ActionProfileSwitchPercent
@ContributesAndroidInjector fun actionSendSMSInjector(): ActionSendSMS
@ContributesAndroidInjector fun actionStartTempTargetInjector(): ActionStartTempTarget
@ContributesAndroidInjector fun actionStopTempTargetInjector(): ActionStopTempTarget
@ContributesAndroidInjector fun actionDummyInjector(): ActionDummy
@ContributesAndroidInjector fun elementInjector(): Element
@ContributesAndroidInjector fun inputBgInjector(): InputBg
@ContributesAndroidInjector fun inputButtonInjector(): InputButton
@ContributesAndroidInjector fun comparatorInjector(): Comparator
@ContributesAndroidInjector fun comparatorConnectInjector(): ComparatorConnect
@ContributesAndroidInjector fun comparatorExistsInjector(): ComparatorExists
@ContributesAndroidInjector fun inputDateTimeInjector(): InputDateTime
@ContributesAndroidInjector fun inputDeltaInjector(): InputDelta
@ContributesAndroidInjector fun inputDoubleInjector(): InputDouble
@ContributesAndroidInjector fun inputDropdownMenuInjector(): InputDropdownMenu
@ContributesAndroidInjector fun inputDurationInjector(): InputDuration
@ContributesAndroidInjector fun inputInsulinInjector(): InputInsulin
@ContributesAndroidInjector fun inputLocationModeInjector(): InputLocationMode
@ContributesAndroidInjector fun inputPercentInjector(): InputPercent
@ContributesAndroidInjector fun inputProfileNameInjector(): InputProfileName
@ContributesAndroidInjector fun inputStringInjector(): InputString
@ContributesAndroidInjector fun inputTempTargetInjector(): InputTempTarget
@ContributesAndroidInjector fun inputTimeRangeInjector(): InputTimeRange
@ContributesAndroidInjector fun inputTimeInjector(): InputTime
@ContributesAndroidInjector fun inputWeekDayInjector(): InputWeekDay
@ContributesAndroidInjector fun labelWithElementInjector(): LabelWithElement
@ContributesAndroidInjector fun staticLabelInjector(): StaticLabel
@ContributesAndroidInjector fun autosensDataInjector(): AutosensData
@ContributesAndroidInjector fun iobCobThreadInjector(): IobCobThread
@ContributesAndroidInjector fun iobCobOref1ThreadInjector(): IobCobOref1Thread
@ContributesAndroidInjector fun bgReadingInjector(): BgReading
@ContributesAndroidInjector fun treatmentInjector(): Treatment
@ContributesAndroidInjector fun profileSwitchInjector(): ProfileSwitch
@ContributesAndroidInjector fun notificationWithActionInjector(): NotificationWithAction
@ContributesAndroidInjector fun loggerCallbackInjector(): LoggerCallback
@ContributesAndroidInjector fun loggerBolusWizard(): BolusWizard
@ContributesAndroidInjector fun loggerQuickWizardEntry(): QuickWizardEntry
@ContributesAndroidInjector fun authRequestInjector(): AuthRequest
@ContributesAndroidInjector fun swBreakInjector(): SWBreak
@ContributesAndroidInjector fun swButtonInjector(): SWButton
@ContributesAndroidInjector fun swEditNumberWithUnitsInjector(): SWEditNumberWithUnits
@ContributesAndroidInjector fun swEditStringInjector(): SWEditString
@ContributesAndroidInjector fun swEditEncryptedPasswordInjector(): SWEditEncryptedPassword
@ContributesAndroidInjector fun swEditUrlInjector(): SWEditUrl
@ContributesAndroidInjector fun swFragmentInjector(): SWFragment
@ContributesAndroidInjector fun swHtmlLinkInjector(): SWHtmlLink
@ContributesAndroidInjector fun swInfotextInjector(): SWInfotext
@ContributesAndroidInjector fun swItemInjector(): SWItem
@ContributesAndroidInjector fun swPluginInjector(): SWPlugin
@ContributesAndroidInjector fun swRadioButtonInjector(): SWRadioButton
@ContributesAndroidInjector fun swScreenInjector(): SWScreen
@ContributesAndroidInjector fun swEventListenerInjector(): SWEventListener
@ContributesAndroidInjector fun profileInjector(): Profile
@ContributesAndroidInjector fun glucoseStatusInjector(): GlucoseStatus
@ContributesAndroidInjector fun graphDataInjector(): GraphData
@ContributesAndroidInjector fun cryptoUtilInjector(): CryptoUtil
@ContributesAndroidInjector fun importExportPrefsInjector(): ImportExportPrefs
@ContributesAndroidInjector fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
@ContributesAndroidInjector fun classicPrefsFormatInjector(): ClassicPrefsFormat
@Binds fun bindContext(mainApp: MainApp): Context
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
@Binds
fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider
@Binds fun commandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider
}
}

View file

@ -0,0 +1,116 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.activities.MyPreferenceFragment
import info.nightscout.androidaps.dialogs.*
import info.nightscout.androidaps.plugins.aps.loop.LoopFragment
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAFragment
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBFragment
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderFragment
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
import info.nightscout.androidaps.plugins.constraints.objectives.dialogs.NtpProgressDialog
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseActionDialog
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditActionDialog
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditTriggerDialog
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment
import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog
import info.nightscout.androidaps.plugins.general.food.FoodFragment
import info.nightscout.androidaps.plugins.general.maintenance.MaintenanceFragment
import info.nightscout.androidaps.plugins.general.nsclient.NSClientFragment
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorFragment
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolFragment
import info.nightscout.androidaps.plugins.general.wear.WearFragment
import info.nightscout.androidaps.plugins.insulin.InsulinFragment
import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment
import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment
import info.nightscout.androidaps.plugins.pump.combo.ComboFragment
import info.nightscout.androidaps.plugins.pump.danaR.DanaRFragment
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightFragment
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
import info.nightscout.androidaps.plugins.source.BGSourceFragment
import info.nightscout.androidaps.plugins.treatments.TreatmentsFragment
import info.nightscout.androidaps.plugins.treatments.fragments.*
import info.nightscout.androidaps.utils.protection.PasswordCheck
@Module
@Suppress("unused")
abstract class FragmentsModule {
@ContributesAndroidInjector abstract fun contributesPreferencesFragment(): MyPreferenceFragment
@ContributesAndroidInjector abstract fun contributesActionsFragment(): ActionsFragment
@ContributesAndroidInjector abstract fun contributesAutomationFragment(): AutomationFragment
@ContributesAndroidInjector abstract fun contributesBGSourceFragment(): BGSourceFragment
@ContributesAndroidInjector abstract fun contributesCareportalFragment(): CareportalFragment
@ContributesAndroidInjector abstract fun contributesComboFragment(): ComboFragment
@ContributesAndroidInjector
abstract fun contributesConfigBuilderFragment(): ConfigBuilderFragment
@ContributesAndroidInjector abstract fun contributesDanaRFragment(): DanaRFragment
@ContributesAndroidInjector abstract fun contributesFoodFragment(): FoodFragment
@ContributesAndroidInjector abstract fun contributesInsulinFragment(): InsulinFragment
@ContributesAndroidInjector abstract fun contributesLocalProfileFragment(): LocalProfileFragment
@ContributesAndroidInjector abstract fun contributesObjectivesFragment(): ObjectivesFragment
@ContributesAndroidInjector abstract fun contributesOpenAPSAMAFragment(): OpenAPSAMAFragment
@ContributesAndroidInjector abstract fun contributesOpenAPSSMBFragment(): OpenAPSSMBFragment
@ContributesAndroidInjector abstract fun contributesOverviewFragment(): OverviewFragment
@ContributesAndroidInjector abstract fun contributesLocalInsightFragment(): LocalInsightFragment
@ContributesAndroidInjector abstract fun contributesLoopFragment(): LoopFragment
@ContributesAndroidInjector abstract fun contributesMaintenanceFragment(): MaintenanceFragment
@ContributesAndroidInjector abstract fun contributesMedtronicFragment(): MedtronicFragment
@ContributesAndroidInjector abstract fun contributesNSProfileFragment(): NSProfileFragment
@ContributesAndroidInjector abstract fun contributesNSClientFragment(): NSClientFragment
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorFragment(): SmsCommunicatorFragment
@ContributesAndroidInjector abstract fun contributesWearFragment(): WearFragment
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsCareportalFragment(): TreatmentsCareportalFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsProfileSwitchFragment(): TreatmentsProfileSwitchFragment
@ContributesAndroidInjector abstract fun contributesVirtualPumpFragment(): VirtualPumpFragment
@ContributesAndroidInjector abstract fun contributesBolusProgressDialog(): BolusProgressDialog
@ContributesAndroidInjector abstract fun contributesCalibrationDialog(): CalibrationDialog
@ContributesAndroidInjector abstract fun contributesCarbsDialog(): CarbsDialog
@ContributesAndroidInjector abstract fun contributesCareDialog(): CareDialog
@ContributesAndroidInjector abstract fun contributesEditActionDialog(): EditActionDialog
@ContributesAndroidInjector abstract fun contributesEditEventDialog(): EditEventDialog
@ContributesAndroidInjector abstract fun contributesEditTriggerDialog(): EditTriggerDialog
@ContributesAndroidInjector
abstract fun contributesEditQuickWizardDialog(): EditQuickWizardDialog
@ContributesAndroidInjector abstract fun contributesErrorDialog(): ErrorDialog
@ContributesAndroidInjector abstract fun contributesExtendedBolusDialog(): ExtendedBolusDialog
@ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog
@ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog
@ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog
@ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog
@ContributesAndroidInjector abstract fun contributesNewNSTreatmentDialog(): NewNSTreatmentDialog
@ContributesAndroidInjector abstract fun contributesNtpProgressDialog(): NtpProgressDialog
@ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog
@ContributesAndroidInjector abstract fun contributesProfileSwitchDialog(): ProfileSwitchDialog
@ContributesAndroidInjector abstract fun contributesProfileViewerDialog(): ProfileViewerDialog
@ContributesAndroidInjector abstract fun contributesTempBasalDialog(): TempBasalDialog
@ContributesAndroidInjector abstract fun contributesTempTargetDialog(): TempTargetDialog
@ContributesAndroidInjector abstract fun contributesTreatmentDialog(): TreatmentDialog
@ContributesAndroidInjector abstract fun contributesWizardDialog(): WizardDialog
@ContributesAndroidInjector abstract fun contributesWizardInfoDialog(): WizardInfoDialog
@ContributesAndroidInjector abstract fun contributesPasswordCheck(): PasswordCheck
}

View file

@ -0,0 +1,365 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Binds
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.multibindings.IntKey
import dagger.multibindings.IntoMap
import dagger.multibindings.IntoSet
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin
import info.nightscout.androidaps.plugins.general.dataBroadcaster.DataBroadcastPlugin
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.source.*
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import javax.inject.Qualifier
@Module
abstract class PluginsModule {
@Binds
@AllConfigs
@IntoMap
@IntKey(0)
abstract fun bindOverviewPlugin(plugin: OverviewPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(10)
abstract fun bindIobCobCalculatorPlugin(plugin: IobCobCalculatorPlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(20)
abstract fun bindActionsPlugin(plugin: ActionsPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(30)
abstract fun bindInsulinOrefRapidActingPlugin(plugin: InsulinOrefRapidActingPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(40)
abstract fun bindInsulinOrefUltraRapidActingPlugin(plugin: InsulinOrefUltraRapidActingPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(50)
abstract fun bindInsulinOrefFreePeakPlugin(plugin: InsulinOrefFreePeakPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(60)
abstract fun bindSensitivityAAPSPlugin(plugin: SensitivityAAPSPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(70)
abstract fun bindSensitivityWeightedAveragePlugin(plugin: SensitivityWeightedAveragePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(80)
abstract fun bindSensitivityOref1Plugin(plugin: SensitivityOref1Plugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(90)
abstract fun bindDanaRPlugin(plugin: DanaRPlugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(100)
abstract fun bindDanaRKoreanPlugin(plugin: DanaRKoreanPlugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(110)
abstract fun bindDanaRv2Plugin(plugin: DanaRv2Plugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(120)
abstract fun bindDanaRSPlugin(plugin: DanaRSPlugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(130)
abstract fun bindLocalInsightPlugin(plugin: LocalInsightPlugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(140)
abstract fun bindComboPlugin(plugin: ComboPlugin): PluginBase
@Binds
@PumpDriver
@IntoMap
@IntKey(150)
abstract fun bindMedtronicPumpPlugin(plugin: MedtronicPumpPlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(160)
abstract fun bindMDIPlugin(plugin: MDIPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(170)
abstract fun bindVirtualPumpPlugin(plugin: VirtualPumpPlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(180)
abstract fun bindCareportalPlugin(plugin: CareportalPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(190)
abstract fun bindLoopPlugin(plugin: LoopPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(210)
abstract fun bindOpenAPSAMAPlugin(plugin: OpenAPSAMAPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(220)
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(230)
abstract fun bindNSProfilePlugin(plugin: NSProfilePlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(240)
abstract fun bindLocalProfilePlugin(plugin: LocalProfilePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(250)
abstract fun bindAutomationPlugin(plugin: AutomationPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(260)
abstract fun bindTreatmentsPlugin(plugin: TreatmentsPlugin): PluginBase
@Binds
@NotNSClient
@IntoSet
abstract fun bindSafetyPlugin(plugin: SafetyPlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(270)
abstract fun bindVersionCheckerPlugin(plugin: VersionCheckerPlugin): PluginBase
@Binds
@NotNSClient
@IntoMap
@IntKey(280)
abstract fun bindSmsCommunicatorPlugin(plugin: SmsCommunicatorPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(290)
abstract fun bindStorageConstraintPlugin(plugin: StorageConstraintPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(300)
abstract fun bindSignatureVerifierPlugin(plugin: SignatureVerifierPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(310)
abstract fun bindObjectivesPlugin(plugin: ObjectivesPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(320)
abstract fun bindFoodPlugin(plugin: FoodPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(330)
abstract fun bindWearPlugin(plugin: WearPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(340)
abstract fun bindStatusLinePlugin(plugin: StatusLinePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(350)
abstract fun bindPersistentNotificationPlugin(plugin: PersistentNotificationPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(360)
abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(370)
abstract fun bindMaintenancePlugin(plugin: MaintenancePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(380)
abstract fun bindDstHelperPlugin(plugin: DstHelperPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(390)
abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(400)
abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(410)
abstract fun bindNSClientSourcePlugin(plugin: NSClientSourcePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(420)
abstract fun bindMM640gPlugin(plugin: MM640gPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(430)
abstract fun bindGlimpPlugin(plugin: GlimpPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(440)
abstract fun bindDexcomPlugin(plugin: DexcomPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(450)
abstract fun bindPoctechPlugin(plugin: PoctechPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(460)
abstract fun bindTomatoPlugin(plugin: TomatoPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(470)
abstract fun bindRandomBgPlugin(plugin: RandomBgPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(480)
abstract fun bindConfigBuilderPlugin(plugin: ConfigBuilderPlugin): PluginBase
@Qualifier
annotation class AllConfigs
@Qualifier
annotation class PumpDriver
@Qualifier
annotation class NotNSClient
@Qualifier
annotation class APS
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
import info.nightscout.androidaps.receivers.*
@Module
@Suppress("unused")
abstract class ReceiversModule {
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
@ContributesAndroidInjector abstract fun contributesNetworkChangeReceiver(): NetworkChangeReceiver
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
}

View file

@ -0,0 +1,42 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
import info.nightscout.androidaps.plugins.general.overview.notifications.DismissNotificationService
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService
import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService
import info.nightscout.androidaps.plugins.pump.danaR.services.DanaRExecutionService
import info.nightscout.androidaps.plugins.pump.danaRKorean.services.DanaRKoreanExecutionService
import info.nightscout.androidaps.plugins.pump.danaRS.services.DanaRSService
import info.nightscout.androidaps.plugins.pump.danaRv2.services.DanaRv2ExecutionService
import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService
import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService
import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService
import info.nightscout.androidaps.services.AlarmSoundService
import info.nightscout.androidaps.services.DataService
import info.nightscout.androidaps.services.LocationService
@Module
@Suppress("unused")
abstract class ServicesModule {
@ContributesAndroidInjector abstract fun contributesAbstractDanaRExecutionService(): AbstractDanaRExecutionService
@ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService
@ContributesAndroidInjector abstract fun contributesDataService(): DataService
@ContributesAndroidInjector abstract fun contributesDismissNotificationService(): DismissNotificationService
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
@ContributesAndroidInjector abstract fun contributesNSClientService(): NSClientService
@ContributesAndroidInjector abstract fun contributesDanaRSService(): DanaRSService
@ContributesAndroidInjector abstract fun contributesDanaRv2ExecutionService(): DanaRv2ExecutionService
@ContributesAndroidInjector abstract fun contributesDanaRExecutionService(): DanaRExecutionService
@ContributesAndroidInjector abstract fun contributesDanaRKoreanExecutionService(): DanaRKoreanExecutionService
@ContributesAndroidInjector abstract fun contributesWatchUpdaterService(): WatchUpdaterService
@ContributesAndroidInjector abstract fun contributesInsightAlertService(): InsightAlertService
@ContributesAndroidInjector abstract fun contributesInsightConnectionService(): InsightConnectionService
@ContributesAndroidInjector abstract fun contributesRileyLinkService(): RileyLinkService
@ContributesAndroidInjector abstract fun contributesRileyLinkMedtronicService(): RileyLinkMedtronicService
}

View file

@ -0,0 +1,16 @@
PreferenceActivity is an Example how to make an Activity injectable.
We might undo that as we don't actually have us inject things.
MyPreferencesFragment is an injectable Fragment. Here we actually have Dagger2 provide us an InsulinOrefFreePeakPlugin instance.
If we use multiple Fragments, we should generate a base-class. Then we only have to add a "provides***Fragment" to the FragmentsModule and derive from that class.
InsulinOrefFreePeakPlugin is an example how to get things injected via the constructor.
You could call "new InsulinOrefFreePeakPlugin(new SPImpl(SPImpl(PreferenceManager.getDefaultSharedPreferences(context))), new ResourceHelper())"... but Dagger will resolve that for you in MainApp. :)
SPImpl is an example how to bind an implementation to an Interface via Dagger.
ResourceHelper is an example how to generate simple classes that Dagger can auto-resolve how to inject them. No need for a provider here.
ResourceHelper might have a weak reference at some point and not a static dependency on MainApp... but at least we reduced the static dependencies within a plugin.
In order to Test: Any dependency of InsulinOrefFreePeakPlugin is passed via the constructor. Instead of static mocking MainApp you now can Mock ResourceHelper with a very small interface.

View file

@ -8,29 +8,33 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import androidx.fragment.app.DialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.MainApp
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.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.dialog_bolusprogress.* import kotlinx.android.synthetic.main.dialog_bolusprogress.*
import org.slf4j.LoggerFactory import javax.inject.Inject
class BolusProgressDialog : DaggerDialogFragment() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var fabricPrivacy: FabricPrivacy
class BolusProgressDialog : DialogFragment() {
private val log = LoggerFactory.getLogger(L.UI)
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
companion object { companion object {
private val DEFAULT_STATE = MainApp.gs(R.string.waitingforpump)
@JvmField @JvmField
var bolusEnded = false var bolusEnded = false
@ -67,16 +71,17 @@ class BolusProgressDialog : DialogFragment() {
savedInstanceState?.let { savedInstanceState?.let {
amount = it.getDouble("amount") amount = it.getDouble("amount")
} }
overview_bolusprogress_title.text = String.format(MainApp.gs(R.string.overview_bolusprogress_goingtodeliver), amount) overview_bolusprogress_title.text = resourceHelper.gs(R.string.overview_bolusprogress_goingtodeliver, amount)
overview_bolusprogress_stop.setOnClickListener { overview_bolusprogress_stop.setOnClickListener {
if (L.isEnabled(L.UI)) log.debug("Stop bolus delivery button pressed") aapsLogger.debug(LTag.UI, "Stop bolus delivery button pressed")
stopPressed = true stopPressed = true
overview_bolusprogress_stoppressed.visibility = View.VISIBLE overview_bolusprogress_stoppressed.visibility = View.VISIBLE
overview_bolusprogress_stop.visibility = View.INVISIBLE overview_bolusprogress_stop.visibility = View.INVISIBLE
ConfigBuilderPlugin.getPlugin().commandQueue.cancelAllBoluses() commandQueue.cancelAllBoluses()
} }
val defaultState = resourceHelper.gs(R.string.waitingforpump)
overview_bolusprogress_progressbar.max = 100 overview_bolusprogress_progressbar.max = 100
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE state = savedInstanceState?.getString("state", defaultState) ?: defaultState
overview_bolusprogress_status.text = state overview_bolusprogress_status.text = state
stopPressed = false stopPressed = false
} }
@ -88,25 +93,28 @@ class BolusProgressDialog : DialogFragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (L.isEnabled(L.UI)) log.debug("onResume") aapsLogger.debug(LTag.UI, "onResume")
if (!ConfigBuilderPlugin.getPlugin().commandQueue.bolusInQueue()) if (!commandQueue.bolusInQueue())
bolusEnded = true bolusEnded = true
if (bolusEnded) dismiss() if (bolusEnded) dismiss()
else running = true else running = true
disposable.add(toObservable(EventPumpStatusChanged::class.java) disposable.add(rxBus
.toObservable(EventPumpStatusChanged::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ overview_bolusprogress_status.text = it.getStatus() }) { FabricPrivacy.logException(it) } .subscribe({ overview_bolusprogress_status.text = it.getStatus(resourceHelper) }) { fabricPrivacy.logException(it) }
) )
disposable.add(toObservable(EventDismissBolusProgressIfRunning::class.java) disposable.add(rxBus
.toObservable(EventDismissBolusProgressIfRunning::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ if (running) dismiss() }) { FabricPrivacy.logException(it) } .subscribe({ if (running) dismiss() }) { fabricPrivacy.logException(it) }
) )
disposable.add(toObservable(EventOverviewBolusProgress::class.java) disposable.add(rxBus
.toObservable(EventOverviewBolusProgress::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ .subscribe({
if (L.isEnabled(L.UI)) log.debug("Status: " + it.status + " Percent: " + it.percent) aapsLogger.debug(LTag.UI, "Status: ${it.status} Percent: ${it.percent}")
overview_bolusprogress_status.text = it.status overview_bolusprogress_status.text = it.status
overview_bolusprogress_progressbar.progress = it.percent overview_bolusprogress_progressbar.progress = it.percent
if (it.percent == 100) { if (it.percent == 100) {
@ -114,26 +122,26 @@ class BolusProgressDialog : DialogFragment() {
scheduleDismiss() scheduleDismiss()
} }
state = it.status state = it.status
}) { FabricPrivacy.logException(it) } }) { fabricPrivacy.logException(it) }
) )
} }
override fun dismiss() { override fun dismiss() {
if (L.isEnabled(L.UI)) log.debug("dismiss") aapsLogger.debug(LTag.UI, "dismiss")
try { try {
super.dismiss() super.dismiss()
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
// dialog not running yet. onResume will try again. Set bolusEnded to make extra // dialog not running yet. onResume will try again. Set bolusEnded to make extra
// sure onResume will catch this // sure onResume will catch this
bolusEnded = true bolusEnded = true
log.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
} }
helpActivity?.finish() helpActivity?.finish()
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
if (L.isEnabled(L.UI)) log.debug("onPause") aapsLogger.debug(LTag.UI, "onPause")
running = false running = false
disposable.clear() disposable.clear()
} }
@ -145,18 +153,18 @@ class BolusProgressDialog : DialogFragment() {
} }
private fun scheduleDismiss() { private fun scheduleDismiss() {
if (L.isEnabled(L.UI)) log.debug("scheduleDismiss") aapsLogger.debug(LTag.UI, "scheduleDismiss")
Thread(Runnable { Thread(Runnable {
SystemClock.sleep(5000) SystemClock.sleep(5000)
bolusEnded = true bolusEnded = true
val activity: Activity? = activity val activity: Activity? = activity
activity?.runOnUiThread { activity?.runOnUiThread {
if (running) { if (running) {
if (L.isEnabled(L.UI)) log.debug("executing") aapsLogger.debug(LTag.UI, "executing")
try { try {
dismiss() dismiss()
} catch (e: Exception) { } catch (e: Exception) {
log.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
} }
} }
} }

View file

@ -5,22 +5,29 @@ 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 dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.XdripCalibrations import info.nightscout.androidaps.utils.XdripCalibrations
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_calibration.* import kotlinx.android.synthetic.main.dialog_calibration.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
class CalibrationDialog : DialogFragmentWithDate() { class CalibrationDialog : DialogFragmentWithDate() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var xdripCalibrations: XdripCalibrations
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value) savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value)
@ -35,8 +42,8 @@ class CalibrationDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).glucoseStatusData?.glucose
?: 0.0, units) ?: 0.0, units)
if (units == Constants.MMOL) if (units == Constants.MMOL)
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg") overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
@ -44,25 +51,25 @@ class CalibrationDialog : DialogFragmentWithDate() {
else else
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg") overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok) ?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok)
overview_calibration_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl) overview_calibration_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
} }
override fun submit(): Boolean { override fun submit(): Boolean {
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl) val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val bg = overview_calibration_bg.value val bg = overview_calibration_bg.value
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(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, MainApp.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
log.debug("USER ENTRY: CALIBRATION $bg") aapsLogger.debug("USER ENTRY: CALIBRATION $bg")
XdripCalibrations.sendIntent(bg) xdripCalibrations.sendIntent(bg)
}) })
} }
} else } else
activity?.let { activity -> activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.overview_calibration), MainApp.gs(R.string.no_action_selected)) OKDialog.show(activity, resourceHelper.gs(R.string.overview_calibration), resourceHelper.gs(R.string.no_action_selected))
} }
return true return true
} }

View file

@ -12,23 +12,35 @@ import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.DatabaseHelper
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_carbs.* import kotlinx.android.synthetic.main.dialog_carbs.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
class CarbsDialog : DialogFragmentWithDate() { class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var mainApp: MainApp
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Inject lateinit var carbsGenerator: CarbsGenerator
companion object { companion object {
private const val FAV1_DEFAULT = 5 private const val FAV1_DEFAULT = 5
@ -36,8 +48,6 @@ class CarbsDialog : DialogFragmentWithDate() {
private const val FAV3_DEFAULT = 20 private const val FAV3_DEFAULT = 20
} }
private val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) { override fun afterTextChanged(s: Editable) {
validateInputs() validateInputs()
@ -48,18 +58,19 @@ class CarbsDialog : DialogFragmentWithDate() {
} }
private fun validateInputs() { private fun validateInputs() {
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
val time = overview_carbs_time.value.toInt() val time = overview_carbs_time.value.toInt()
if (time > 12 * 60 || time < -12 * 60) { if (time > 12 * 60 || time < -12 * 60) {
overview_carbs_time.value = 0.0 overview_carbs_time.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
} }
if (overview_carbs_duration.value > 10) { if (overview_carbs_duration.value > 10) {
overview_carbs_duration.value = 0.0 overview_carbs_duration.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
} }
if (overview_carbs_carbs.value.toInt() > maxCarbs) { if (overview_carbs_carbs.value.toInt() > maxCarbs) {
overview_carbs_carbs.value = 0.0 overview_carbs_carbs.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
} }
} }
@ -79,6 +90,7 @@ class CarbsDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time") overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time")
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
@ -88,30 +100,30 @@ class CarbsDialog : DialogFragmentWithDate() {
overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs") overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
overview_carbs_plus1.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)) overview_carbs_plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
overview_carbs_plus1.setOnClickListener { overview_carbs_plus1.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)) + sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
validateInputs() validateInputs()
} }
overview_carbs_plus2.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)) overview_carbs_plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
overview_carbs_plus2.setOnClickListener { overview_carbs_plus2.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)) + sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
validateInputs() validateInputs()
} }
overview_carbs_plus3.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)) overview_carbs_plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
overview_carbs_plus3.setOnClickListener { overview_carbs_plus3.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)) + sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
validateInputs() validateInputs()
} }
DatabaseHelper.actualBg()?.let { bgReading -> iobCobCalculatorPlugin.actualBg()?.let { bgReading ->
if (bgReading.value < 72) if (bgReading.value < 72)
overview_carbs_hypo_tt.setChecked(true) overview_carbs_hypo_tt.isChecked = true
} }
overview_carbs_hypo_tt.setOnClickListener { overview_carbs_hypo_tt.setOnClickListener {
overview_carbs_activity_tt.isChecked = false overview_carbs_activity_tt.isChecked = false
@ -133,95 +145,102 @@ class CarbsDialog : DialogFragmentWithDate() {
override fun submit(): Boolean { override fun submit(): Boolean {
val carbs = overview_carbs_carbs.value.toInt() val carbs = overview_carbs_carbs.value.toInt()
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value() val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
val activityTTDuration = DefaultValueHelper.determineActivityTTDuration() val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
val activityTT = DefaultValueHelper.determineActivityTT() val activityTT = defaultValueHelper.determineActivityTT()
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration() val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT() val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
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) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl) val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val activitySelected = overview_carbs_activity_tt.isChecked val activitySelected = overview_carbs_activity_tt.isChecked
if (activitySelected) if (activitySelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>") actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + "<font color='" + resourceHelper.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " " + resourceHelper.gs(R.string.unit_minute_short) + ")</font>")
val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked
if (eatingSoonSelected) if (eatingSoonSelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>") actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + "<font color='" + resourceHelper.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + resourceHelper.gs(R.string.unit_minute_short) + ")</font>")
val hypoSelected = overview_carbs_hypo_tt.isChecked val hypoSelected = overview_carbs_hypo_tt.isChecked
if (hypoSelected) if (hypoSelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + hypoTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>") actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + "<font color='" + resourceHelper.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + hypoTTDuration + " " + resourceHelper.gs(R.string.unit_minute_short) + ")</font>")
val timeOffset = overview_carbs_time.value.toInt() val timeOffset = overview_carbs_time.value.toInt()
eventTime -= eventTime % 1000
val time = eventTime + timeOffset * 1000 * 60 val time = eventTime + timeOffset * 1000 * 60
if (timeOffset != 0) if (timeOffset != 0)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
val duration = overview_carbs_duration.value.toInt() val duration = overview_carbs_duration.value.toInt()
if (duration > 0) if (duration > 0)
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour)) actions.add(resourceHelper.gs(R.string.duration) + ": " + duration + resourceHelper.gs(R.string.shorthour))
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>") actions.add(resourceHelper.gs(R.string.carbs) + ": " + "<font color='" + resourceHelper.gc(R.color.carbs) + "'>" + resourceHelper.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
if (carbsAfterConstraints != carbs) if (carbsAfterConstraints != carbs)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.carbsconstraintapplied) + "</font>")
} }
val notes = notes.text.toString() val notes = notes.text.toString()
if (notes.isNotEmpty()) if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (eventTimeChanged) if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) { if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (activitySelected) { when {
log.debug("USER ENTRY: TEMPTARGET ACTIVITY $activityTT duration: $activityTTDuration") activitySelected -> {
aapsLogger.debug("USER ENTRY: TEMPTARGET ACTIVITY $activityTT duration: $activityTTDuration")
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(eventTime) .date(System.currentTimeMillis())
.duration(activityTTDuration) .duration(activityTTDuration)
.reason(MainApp.gs(R.string.activity)) .reason(resourceHelper.gs(R.string.activity))
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits())) .low(Profile.toMgdl(activityTT, profileFunction.getUnits()))
.high(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits())) .high(Profile.toMgdl(activityTT, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) treatmentsPlugin.addToHistoryTempTarget(tempTarget)
} else if (eatingSoonSelected) { }
log.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
eatingSoonSelected -> {
aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(eventTime) .date(System.currentTimeMillis())
.duration(eatingSoonTTDuration) .duration(eatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon)) .reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits())) .low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits())) .high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) treatmentsPlugin.addToHistoryTempTarget(tempTarget)
} else if (hypoSelected) { }
log.debug("USER ENTRY: TEMPTARGET HYPO $hypoTT duration: $hypoTTDuration")
hypoSelected -> {
aapsLogger.debug("USER ENTRY: TEMPTARGET HYPO $hypoTT duration: $hypoTTDuration")
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(eventTime) .date(System.currentTimeMillis())
.duration(hypoTTDuration) .duration(hypoTTDuration)
.reason(MainApp.gs(R.string.hypo)) .reason(resourceHelper.gs(R.string.hypo))
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits())) .low(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
.high(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits())) .high(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) treatmentsPlugin.addToHistoryTempTarget(tempTarget)
}
} }
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
if (duration == 0) { if (duration == 0) {
log.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time") aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time")
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes) carbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
} else { } else {
log.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time duration: $duration") aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time duration: $duration")
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes) carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
NSUpload.uploadEvent(CareportalEvent.NOTE, time - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset)) NSUpload.uploadEvent(CareportalEvent.NOTE, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
} }
} }
}, null) }, null)
} }
} else } else
activity?.let { activity -> activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.carbs), MainApp.gs(R.string.no_action_selected)) OKDialog.show(activity, resourceHelper.gs(R.string.carbs), resourceHelper.gs(R.string.no_action_selected))
} }
return true return true
} }

View file

@ -6,31 +6,36 @@ import android.text.TextWatcher
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button
import androidx.annotation.StringRes import androidx.annotation.StringRes
import com.google.common.base.Joiner import com.google.common.base.Joiner
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_care.* import kotlinx.android.synthetic.main.dialog_care.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import org.json.JSONObject import org.json.JSONObject
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
class CareDialog : DialogFragmentWithDate() { class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var mainApp: MainApp
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
enum class EventType { enum class EventType {
BGCHECK, BGCHECK,
@ -79,7 +84,7 @@ class CareDialog : DialogFragmentWithDate() {
EventType.NOTE -> R.drawable.icon_cp_note EventType.NOTE -> R.drawable.icon_cp_note
EventType.EXERCISE -> R.drawable.icon_cp_exercise EventType.EXERCISE -> R.drawable.icon_cp_exercise
}) })
actions_care_title.text = MainApp.gs(when (options) { actions_care_title.text = resourceHelper.gs(when (options) {
EventType.BGCHECK -> R.string.careportal_bgcheck EventType.BGCHECK -> R.string.careportal_bgcheck
EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert
EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange
@ -91,12 +96,14 @@ class CareDialog : DialogFragmentWithDate() {
EventType.BGCHECK -> { EventType.BGCHECK -> {
action_care_duration_layout.visibility = View.GONE action_care_duration_layout.visibility = View.GONE
} }
EventType.SENSOR_INSERT, EventType.SENSOR_INSERT,
EventType.BATTERY_CHANGE -> { EventType.BATTERY_CHANGE -> {
action_care_bg_layout.visibility = View.GONE action_care_bg_layout.visibility = View.GONE
actions_care_bgsource.visibility = View.GONE actions_care_bgsource.visibility = View.GONE
action_care_duration_layout.visibility = View.GONE action_care_duration_layout.visibility = View.GONE
} }
EventType.NOTE, EventType.NOTE,
EventType.EXERCISE -> { EventType.EXERCISE -> {
action_care_bg_layout.visibility = View.GONE action_care_bg_layout.visibility = View.GONE
@ -104,8 +111,8 @@ class CareDialog : DialogFragmentWithDate() {
} }
} }
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).getGlucoseStatusData()?.glucose
?: 0.0, ProfileFunctions.getSystemUnits()) ?: 0.0, profileFunction.getUnits())
val bgTextWatcher: TextWatcher = object : TextWatcher { val bgTextWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {} override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
@ -114,12 +121,12 @@ class CareDialog : DialogFragmentWithDate() {
} }
} }
if (ProfileFunctions.getSystemUnits() == Constants.MMOL) { if (profileFunction.getUnits() == Constants.MMOL) {
actions_care_bgunits.text = MainApp.gs(R.string.mmol) actions_care_bgunits.text = resourceHelper.gs(R.string.mmol)
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg") actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, bgTextWatcher) ?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, bgTextWatcher)
} else { } else {
actions_care_bgunits.text = MainApp.gs(R.string.mgdl) actions_care_bgunits.text = resourceHelper.gs(R.string.mgdl)
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg") actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok, bgTextWatcher) ?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok, bgTextWatcher)
} }
@ -130,8 +137,8 @@ class CareDialog : DialogFragmentWithDate() {
} }
override fun submit(): Boolean { override fun submit(): Boolean {
val enteredBy = SP.getString("careportal_enteredby", "") val enteredBy = sp.getString("careportal_enteredby", "")
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
val json = JSONObject() val json = JSONObject()
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
@ -142,24 +149,24 @@ class CareDialog : DialogFragmentWithDate() {
actions_care_sensor.isChecked -> "Sensor" actions_care_sensor.isChecked -> "Sensor"
else -> "Manual" else -> "Manual"
} }
actions.add(MainApp.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + Translator.translate(type)) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + Translator.translate(type))
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(actions_care_bg.value) + " " + MainApp.gs(unitResId)) actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, actions_care_bg.value) + " " + resourceHelper.gs(unitResId))
json.put("glucose", actions_care_bg.value) json.put("glucose", actions_care_bg.value)
json.put("glucoseType", type) json.put("glucoseType", type)
} }
if (options == EventType.NOTE || options == EventType.EXERCISE) { if (options == EventType.NOTE || options == EventType.EXERCISE) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_duration_label) + ": " + MainApp.gs(R.string.format_mins, actions_care_duration.value.toInt())) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, actions_care_duration.value.toInt()))
json.put("duration", actions_care_duration.value.toInt()) json.put("duration", actions_care_duration.value.toInt())
} }
val notes = notes.text.toString() val notes = notes.text.toString()
if (notes.isNotEmpty()) { if (notes.isNotEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
json.put("notes", notes) json.put("notes", notes)
} }
eventTime -= eventTime % 1000 eventTime -= eventTime % 1000
if (eventTimeChanged) if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
json.put("created_at", DateUtil.toISOString(eventTime)) json.put("created_at", DateUtil.toISOString(eventTime))
json.put("mills", eventTime) json.put("mills", eventTime)
@ -170,12 +177,12 @@ class CareDialog : DialogFragmentWithDate() {
EventType.NOTE -> CareportalEvent.NOTE EventType.NOTE -> CareportalEvent.NOTE
EventType.EXERCISE -> CareportalEvent.EXERCISE EventType.EXERCISE -> CareportalEvent.EXERCISE
}) })
json.put("units", ProfileFunctions.getSystemUnits()) json.put("units", profileFunction.getUnits())
if (enteredBy.isNotEmpty()) if (enteredBy.isNotEmpty())
json.put("enteredBy", enteredBy) json.put("enteredBy", enteredBy)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
val careportalEvent = CareportalEvent() val careportalEvent = CareportalEvent()
careportalEvent.date = eventTime careportalEvent.date = eventTime
careportalEvent.source = Source.USER careportalEvent.source = Source.USER
@ -187,7 +194,7 @@ class CareDialog : DialogFragmentWithDate() {
EventType.EXERCISE -> CareportalEvent.EXERCISE EventType.EXERCISE -> CareportalEvent.EXERCISE
} }
careportalEvent.json = json.toString() careportalEvent.json = json.toString()
log.debug("USER ENTRY: CAREPORTAL ${careportalEvent.eventType} json: ${careportalEvent.json}") aapsLogger.debug("USER ENTRY: CAREPORTAL ${careportalEvent.eventType} json: ${careportalEvent.json}")
MainApp.getDbHelper().createOrUpdate(careportalEvent) MainApp.getDbHelper().createOrUpdate(careportalEvent)
NSUpload.uploadCareportalEntryToNS(json) NSUpload.uploadCareportalEntryToNS(json)
}, null) }, null)

View file

@ -8,19 +8,22 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import androidx.fragment.app.DialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import kotlinx.android.synthetic.main.datetime.* import kotlinx.android.synthetic.main.datetime.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import org.slf4j.LoggerFactory
import java.util.* import java.util.*
import javax.inject.Inject
abstract class DialogFragmentWithDate : DialogFragment() { abstract class DialogFragmentWithDate : DaggerDialogFragment() {
val log = LoggerFactory.getLogger(DialogFragmentWithDate::class.java) @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
var eventTime = DateUtil.now() var eventTime = DateUtil.now()
var eventTimeChanged = false var eventTimeChanged = false
@ -104,12 +107,12 @@ abstract class DialogFragmentWithDate : DialogFragment() {
} }
} }
notes_layout?.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility() notes_layout?.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
ok.setOnClickListener { ok.setOnClickListener {
synchronized(okClicked) { synchronized(okClicked) {
if (okClicked) { if (okClicked) {
log.debug("guarding: ok already clicked") aapsLogger.warn(LTag.UI, "guarding: ok already clicked")
} else { } else {
okClicked = true okClicked = true
if (submit()) dismiss() if (submit()) dismiss()

View file

@ -1,8 +1,5 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -11,23 +8,23 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import androidx.fragment.app.DialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
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.logging.AAPSLogger
import info.nightscout.androidaps.services.AlarmSoundService import info.nightscout.androidaps.services.AlarmSoundService
import kotlinx.android.synthetic.main.dialog_error.* import kotlinx.android.synthetic.main.dialog_error.*
import org.slf4j.LoggerFactory import javax.inject.Inject
import java.util.*
class ErrorDialog : DialogFragment() { class ErrorDialog : DaggerDialogFragment() {
private val log = LoggerFactory.getLogger(ErrorDialog::class.java) @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var mainApp: MainApp
var helperActivity: ErrorHelperActivity? = null var helperActivity: ErrorHelperActivity? = null
var status: String = "" var status: String = ""
var title: String = "" var title: String = ""
var sound: Int = 0 var sound: Int = 0
var clipboardContent: String = ""
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? { savedInstanceState: Bundle?): View? {
@ -41,7 +38,7 @@ class ErrorDialog : DialogFragment() {
bundle.getString("title")?.let { title = it } bundle.getString("title")?.let { title = it }
sound = bundle.getInt("sound", R.raw.error) sound = bundle.getInt("sound", R.raw.error)
} }
log.debug("Error dialog displayed") aapsLogger.debug("Error dialog displayed")
return inflater.inflate(R.layout.dialog_error, container, false) return inflater.inflate(R.layout.dialog_error, container, false)
} }
@ -50,25 +47,16 @@ class ErrorDialog : DialogFragment() {
error_title.text = title error_title.text = title
overview_error_ok.setOnClickListener { overview_error_ok.setOnClickListener {
log.debug("USER ENTRY: Error dialog ok button pressed") aapsLogger.debug("USER ENTRY: Error dialog ok button pressed")
dismiss() dismiss()
} }
overview_error_mute.setOnClickListener { overview_error_mute.setOnClickListener {
log.debug("USER ENTRY: Error dialog mute button pressed") aapsLogger.debug("USER ENTRY: Error dialog mute button pressed")
stopAlarm() stopAlarm()
} }
copyToClipboard()
startAlarm() startAlarm()
} }
private fun copyToClipboard() {
if (clipboardContent.length > 0) {
val clipboard = MainApp.instance().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(UUID.randomUUID().toString(), clipboardContent)
clipboard.primaryClip = clip
}
}
override fun onSaveInstanceState(bundle: Bundle) { override fun onSaveInstanceState(bundle: Bundle) {
super.onSaveInstanceState(bundle) super.onSaveInstanceState(bundle)
bundle.putString("status", status) bundle.putString("status", status)
@ -94,16 +82,16 @@ class ErrorDialog : DialogFragment() {
private fun startAlarm() { private fun startAlarm() {
if (sound != 0) { if (sound != 0) {
val alarm = Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java) val alarm = Intent(mainApp, AlarmSoundService::class.java)
alarm.putExtra("soundid", sound) alarm.putExtra("soundid", sound)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MainApp.instance().startForegroundService(alarm) mainApp.startForegroundService(alarm)
} else { } else {
MainApp.instance().startService(alarm) mainApp.startService(alarm)
} }
} }
} }
private fun stopAlarm() = private fun stopAlarm() =
MainApp.instance().stopService(Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java)) mainApp.stopService(Intent(mainApp, AlarmSoundService::class.java))
} }

View file

@ -9,19 +9,28 @@ import com.google.common.base.Joiner
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
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.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_extendedbolus.* import kotlinx.android.synthetic.main.dialog_extendedbolus.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
class ExtendedBolusDialog : DialogFragmentWithDate() { class ExtendedBolusDialog : DialogFragmentWithDate() {
@Inject lateinit var mainApp: MainApp
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
@ -38,9 +47,9 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return val pumpDescription = activePlugin.activePump.pumpDescription
val maxInsulin = MainApp.getConstraintChecker().maxExtendedBolusAllowed.value() val maxInsulin = constraintChecker.getMaxExtendedBolusAllowed().value()
val extendedStep = pumpDescription.extendedBolusStep val extendedStep = pumpDescription.extendedBolusStep
actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin") actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin")
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok) ?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok)
@ -55,24 +64,24 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text) val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text)
val durationInMinutes = SafeParse.stringToInt(actions_extendedbolus_duration.text) val durationInMinutes = SafeParse.stringToInt(actions_extendedbolus_duration.text)
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
val insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value()
actions.add(MainApp.gs(R.string.formatinsulinunits, insulinAfterConstraint)) actions.add(resourceHelper.gs(R.string.formatinsulinunits, insulinAfterConstraint))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
if (abs(insulinAfterConstraint - insulin) > 0.01) if (abs(insulinAfterConstraint - insulin) > 0.01)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.constraintapllied) + "</font>")
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
log.debug("USER ENTRY: EXTENDED BOLUS $insulinAfterConstraint duration: $durationInMinutes") aapsLogger.debug("USER ENTRY: EXTENDED BOLUS $insulinAfterConstraint duration: $durationInMinutes")
ConfigBuilderPlugin.getPlugin().commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() { commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) val i = Intent(mainApp, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror) i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment) i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i) mainApp.startActivity(i)
} }
} }
}) })

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -12,24 +13,37 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_fill.* import kotlinx.android.synthetic.main.dialog_fill.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
class FillDialog : DialogFragmentWithDate() { class FillDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var ctx: Context
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("fill_insulinamount", fill_insulinamount.value) savedInstanceState.putDouble("fill_insulin_amount", fill_insulinamount.value)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
@ -41,30 +55,30 @@ class FillDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value() val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulinamount") fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulin_amount")
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), true, ok) ?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), true, ok)
val amount1 = SP.getDouble("fill_button1", 0.3) val amount1 = sp.getDouble("fill_button1", 0.3)
if (amount1 > 0) { if (amount1 > 0) {
fill_preset_button1.visibility = View.VISIBLE fill_preset_button1.visibility = View.VISIBLE
fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1) // + "U"); fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1, activePlugin.activePump) // + "U");
fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 } fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 }
} else { } else {
fill_preset_button1.visibility = View.GONE fill_preset_button1.visibility = View.GONE
} }
val amount2 = SP.getDouble("fill_button2", 0.0) val amount2 = sp.getDouble("fill_button2", 0.0)
if (amount2 > 0) { if (amount2 > 0) {
fill_preset_button2.visibility = View.VISIBLE fill_preset_button2.visibility = View.VISIBLE
fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2) // + "U"); fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2, activePlugin.activePump) // + "U");
fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 } fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 }
} else { } else {
fill_preset_button2.visibility = View.GONE fill_preset_button2.visibility = View.GONE
} }
val amount3 = SP.getDouble("fill_button3", 0.0) val amount3 = sp.getDouble("fill_button3", 0.0)
if (amount3 > 0) { if (amount3 > 0) {
fill_preset_button3.visibility = View.VISIBLE fill_preset_button3.visibility = View.VISIBLE
fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3) // + "U"); fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3, activePlugin.activePump) // + "U");
fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 } fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 }
} else { } else {
fill_preset_button3.visibility = View.GONE fill_preset_button3.visibility = View.GONE
@ -76,49 +90,49 @@ class FillDialog : DialogFragmentWithDate() {
val insulin = SafeParse.stringToDouble(fill_insulinamount.text) val insulin = SafeParse.stringToDouble(fill_insulinamount.text)
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.fillwarning)) actions.add(resourceHelper.gs(R.string.fillwarning))
actions.add("") actions.add("")
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorInsulinButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>") actions.add(resourceHelper.gs(R.string.bolus) + ": " + "<font color='" + resourceHelper.gc(R.color.colorInsulinButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump) + resourceHelper.gs(R.string.insulin_unit_shortname) + "</font>")
if (abs(insulinAfterConstraints - insulin) > 0.01) if (abs(insulinAfterConstraints - insulin) > 0.01)
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints)) actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarning, resourceHelper.gc(R.color.warning), insulin, insulinAfterConstraints))
} }
val siteChange = fill_catheter_change.isChecked val siteChange = fill_catheter_change.isChecked
if (siteChange) if (siteChange)
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>") actions.add("" + "<font color='" + resourceHelper.gc(R.color.actionsConfirm) + "'>" + resourceHelper.gs(R.string.record_pump_site_change) + "</font>")
val insulinChange = fill_cartridge_change.isChecked val insulinChange = fill_cartridge_change.isChecked
if (insulinChange) if (insulinChange)
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>") actions.add("" + "<font color='" + resourceHelper.gc(R.color.actionsConfirm) + "'>" + resourceHelper.gs(R.string.record_insulin_cartridge_change) + "</font>")
val notes = notes.text.toString() val notes = notes.text.toString()
if (notes.isNotEmpty()) if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
eventTime -= eventTime % 1000 eventTime -= eventTime % 1000
if (eventTimeChanged) if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) { if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
log.debug("USER ENTRY: PRIME BOLUS $insulinAfterConstraints") aapsLogger.debug("USER ENTRY: PRIME BOLUS $insulinAfterConstraints")
requestPrimeBolus(insulinAfterConstraints, notes) requestPrimeBolus(insulinAfterConstraints, notes)
} }
if (siteChange) { if (siteChange) {
log.debug("USER ENTRY: SITE CHANGE") aapsLogger.debug("USER ENTRY: SITE CHANGE")
generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes) generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes)
} }
if (insulinChange) { if (insulinChange) {
// add a second for case of both checked // add a second for case of both checked
log.debug("USER ENTRY: INSULIN CHANGE") aapsLogger.debug("USER ENTRY: INSULIN CHANGE")
generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes) generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
} }
}, null) }, null)
} }
} else { } else {
activity?.let { activity -> activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.primefill), MainApp.gs(R.string.no_action_selected)) OKDialog.show(activity, resourceHelper.gs(R.string.primefill), resourceHelper.gs(R.string.no_action_selected))
} }
} }
dismiss() dismiss()
@ -132,15 +146,15 @@ class FillDialog : DialogFragmentWithDate() {
detailedBolusInfo.source = Source.USER detailedBolusInfo.source = Source.USER
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history) detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) val i = Intent(ctx, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror) i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment) i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i) ctx.startActivity(i)
} }
} }
}) })
@ -162,7 +176,7 @@ class FillDialog : DialogFragmentWithDate() {
data.put("eventType", careportalEvent) data.put("eventType", careportalEvent)
data.put("created_at", DateUtil.toISOString(time)) data.put("created_at", DateUtil.toISOString(time))
data.put("mills", time) data.put("mills", time)
data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name))) data.put("enteredBy", sp.getString("careportal_enteredby", resourceHelper.gs(R.string.app_name)))
if (notes.isNotEmpty()) data.put("notes", notes) if (notes.isNotEmpty()) data.put("notes", notes)
} catch (ignored: JSONException) { } catch (ignored: JSONException) {
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
@ -9,7 +10,6 @@ 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.Constants
import info.nightscout.androidaps.MainApp
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
@ -17,21 +17,34 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toSignedString
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_insulin.* import kotlinx.android.synthetic.main.dialog_insulin.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
class InsulinDialog : DialogFragmentWithDate() { class InsulinDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var ctx: Context
companion object { companion object {
private const val PLUS1_DEFAULT = 0.5 private const val PLUS1_DEFAULT = 0.5
@ -39,8 +52,6 @@ class InsulinDialog : DialogFragmentWithDate() {
private const val PLUS3_DEFAULT = 2.0 private const val PLUS3_DEFAULT = 2.0
} }
private val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) { override fun afterTextChanged(s: Editable) {
validateInputs() validateInputs()
@ -51,13 +62,14 @@ class InsulinDialog : DialogFragmentWithDate() {
} }
private fun validateInputs() { private fun validateInputs() {
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) { if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
overview_insulin_time.value = 0.0 overview_insulin_time.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.constraintapllied))
} }
if (overview_insulin_amount.value > maxInsulin) { if (overview_insulin_amount.value > maxInsulin) {
overview_insulin_amount.value = 0.0 overview_insulin_amount.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied)) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.bolusconstraintapplied))
} }
} }
@ -76,27 +88,29 @@ class InsulinDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time") overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time")
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount") overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount")
?: 0.0, 0.0, maxInsulin, ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher) ?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
overview_insulin_plus05.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)) overview_insulin_plus05.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
overview_insulin_plus05.setOnClickListener { overview_insulin_plus05.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)) + sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs() validateInputs()
} }
overview_insulin_plus10.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)) overview_insulin_plus10.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
overview_insulin_plus10.setOnClickListener { overview_insulin_plus10.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)) + sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs() validateInputs()
} }
overview_insulin_plus20.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)) overview_insulin_plus20.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
overview_insulin_plus20.setOnClickListener { overview_insulin_plus20.setOnClickListener {
overview_insulin_amount.value = Math.max(0.0, overview_insulin_amount.value overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)) + sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs() validateInputs()
} }
@ -106,56 +120,50 @@ class InsulinDialog : DialogFragmentWithDate() {
} }
} }
private fun toSignedString(value: Double): String {
val formatted = DecimalFormatter.toPumpSupportedBolus(value)
return if (value > 0) "+$formatted" else formatted
}
override fun submit(): Boolean { override fun submit(): Boolean {
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription val pumpDescription = activePlugin.activePump.pumpDescription
?: return false
val insulin = SafeParse.stringToDouble(overview_insulin_amount.text) val insulin = SafeParse.stringToDouble(overview_insulin_amount.text)
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl) val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val recordOnlyChecked = overview_insulin_record_only.isChecked val recordOnlyChecked = overview_insulin_record_only.isChecked
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>") actions.add(resourceHelper.gs(R.string.bolus) + ": " + "<font color='" + resourceHelper.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump) + resourceHelper.gs(R.string.insulin_unit_shortname) + "</font>")
if (recordOnlyChecked) if (recordOnlyChecked)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.bolusrecordedonly) + "</font>")
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints)) actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarning, resourceHelper.gc(R.color.warning), insulin, insulinAfterConstraints))
} }
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration() val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT() val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
if (eatingSoonChecked) if (eatingSoonChecked)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>") actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + "<font color='" + resourceHelper.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + resourceHelper.gs(R.string.unit_minute_short) + ")</font>")
val timeOffset = overview_insulin_time.value.toInt() val timeOffset = overview_insulin_time.value.toInt()
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs() val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
if (timeOffset != 0) if (timeOffset != 0)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
val notes = notes.text.toString() val notes = notes.text.toString()
if (notes.isNotEmpty()) if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (insulinAfterConstraints > 0 || eatingSoonChecked) { if (insulinAfterConstraints > 0 || eatingSoonChecked) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (eatingSoonChecked) { if (eatingSoonChecked) {
log.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration") aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
.duration(eatingSoonTTDuration) .duration(eatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon)) .reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits())) .low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits())) .high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
} }
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
@ -165,21 +173,21 @@ class InsulinDialog : DialogFragmentWithDate() {
detailedBolusInfo.source = Source.USER detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
if (recordOnlyChecked) { if (recordOnlyChecked) {
log.debug("USER ENTRY: BOLUS RECORD ONLY $insulinAfterConstraints") aapsLogger.debug("USER ENTRY: BOLUS RECORD ONLY $insulinAfterConstraints")
detailedBolusInfo.date = time detailedBolusInfo.date = time
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false) activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
} else { } else {
log.debug("USER ENTRY: BOLUS $insulinAfterConstraints") aapsLogger.debug("USER ENTRY: BOLUS $insulinAfterConstraints")
detailedBolusInfo.date = DateUtil.now() detailedBolusInfo.date = DateUtil.now()
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) val i = Intent(ctx, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror) i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment) i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i) ctx.startActivity(i)
} }
} }
}) })
@ -189,7 +197,7 @@ class InsulinDialog : DialogFragmentWithDate() {
} }
} else } else
activity?.let { activity -> activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.bolus), MainApp.gs(R.string.no_action_selected)) OKDialog.show(activity, resourceHelper.gs(R.string.bolus), resourceHelper.gs(R.string.no_action_selected))
} }
return true return true
} }

View file

@ -7,21 +7,26 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter 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.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_profileswitch.* import kotlinx.android.synthetic.main.dialog_profileswitch.*
import kotlinx.android.synthetic.main.notes.* import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
class ProfileSwitchDialog : DialogFragmentWithDate() { class ProfileSwitchDialog : DialogFragmentWithDate() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
@ -48,21 +53,21 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
// profile // profile
context?.let { context -> context?.let { context ->
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile val profileStore = activePlugin.activeProfileInterface.profile
?: return ?: return
val profileList = profileStore.getProfileList() val profileList = profileStore.getProfileList()
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
overview_profileswitch_profile.adapter = adapter overview_profileswitch_profile.adapter = adapter
// set selected to actual profile // set selected to actual profile
for (p in profileList.indices) for (p in profileList.indices)
if (profileList[p] == ProfileFunctions.getInstance().getProfileName(false)) if (profileList[p] == profileFunction.getProfileName(false))
overview_profileswitch_profile.setSelection(p) overview_profileswitch_profile.setSelection(p)
} ?: return } ?: return
TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now())?.let { ps -> treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
if (ps.isCPP) { if (ps.isCPP) {
overview_profileswitch_reuselayout.visibility = View.VISIBLE overview_profileswitch_reuselayout.visibility = View.VISIBLE
overview_profileswitch_reusebutton.text = MainApp.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h" overview_profileswitch_reusebutton.text = resourceHelper.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h"
overview_profileswitch_reusebutton.setOnClickListener { overview_profileswitch_reusebutton.setOnClickListener {
overview_profileswitch_percentage.value = ps.percentage.toDouble() overview_profileswitch_percentage.value = ps.percentage.toDouble()
overview_profileswitch_timeshift.value = ps.timeshift.toDouble() overview_profileswitch_timeshift.value = ps.timeshift.toDouble()
@ -74,31 +79,31 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
} }
override fun submit(): Boolean { override fun submit(): Boolean {
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile val profileStore = activePlugin.activeProfileInterface.profile
?: return false ?: return false
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
val duration = overview_profileswitch_duration.value.toInt() val duration = overview_profileswitch_duration.value.toInt()
if (duration > 0) if (duration > 0)
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, duration)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
val profile = overview_profileswitch_profile.selectedItem.toString() val profile = overview_profileswitch_profile.selectedItem.toString()
actions.add(MainApp.gs(R.string.profile) + ": " + profile) actions.add(resourceHelper.gs(R.string.profile) + ": " + profile)
val percent = overview_profileswitch_percentage.value.toInt() val percent = overview_profileswitch_percentage.value.toInt()
if (percent != 100) if (percent != 100)
actions.add(MainApp.gs(R.string.percent) + ": " + percent + "%") actions.add(resourceHelper.gs(R.string.percent) + ": " + percent + "%")
val timeShift = overview_profileswitch_timeshift.value.toInt() val timeShift = overview_profileswitch_timeshift.value.toInt()
if (timeShift != 0) if (timeShift != 0)
actions.add(MainApp.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + MainApp.gs(R.string.format_hours, timeShift.toDouble())) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + resourceHelper.gs(R.string.format_hours, timeShift.toDouble()))
val notes = notes.text.toString() val notes = notes.text.toString()
if (notes.isNotEmpty()) if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (eventTimeChanged) if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
log.debug("USER ENTRY: PROFILE SWITCH $profile percent: $percent timeshift: $timeShift duration: $duration") aapsLogger.debug("USER ENTRY: PROFILE SWITCH $profile percent: $percent timeshift: $timeShift duration: $duration")
ProfileFunctions.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime) treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
}) })
} }
return true return true

View file

@ -6,18 +6,24 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import androidx.fragment.app.DialogFragment import dagger.android.HasAndroidInjector
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.close.* import kotlinx.android.synthetic.main.close.*
import kotlinx.android.synthetic.main.dialog_profileviewer.* import kotlinx.android.synthetic.main.dialog_profileviewer.*
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject
class ProfileViewerDialog : DaggerDialogFragment() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
class ProfileViewerDialog : DialogFragment() {
private var time: Long = 0 private var time: Long = 0
enum class Mode(val i: Int) { enum class Mode(val i: Int) {
@ -59,15 +65,15 @@ class ProfileViewerDialog : DialogFragment() {
val date: String? val date: String?
when (mode) { when (mode) {
Mode.RUNNING_PROFILE -> { Mode.RUNNING_PROFILE -> {
profile = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.profileObject profile = treatmentsPlugin.getProfileSwitchFromHistory(time)?.profileObject
profileName = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.customizedName profileName = treatmentsPlugin.getProfileSwitchFromHistory(time)?.customizedName
date = DateUtil.dateAndTimeString(TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.date date = DateUtil.dateAndTimeString(treatmentsPlugin.getProfileSwitchFromHistory(time)?.date
?: 0) ?: 0)
profileview_datelayout.visibility = View.VISIBLE profileview_datelayout.visibility = View.VISIBLE
} }
Mode.CUSTOM_PROFILE -> { Mode.CUSTOM_PROFILE -> {
profile = Profile(JSONObject(customProfileJson), customProfileUnits) profile = Profile(injector, JSONObject(customProfileJson), customProfileUnits)
profileName = customProfileName profileName = customProfileName
date = "" date = ""
profileview_datelayout.visibility = View.GONE profileview_datelayout.visibility = View.GONE
@ -77,7 +83,7 @@ class ProfileViewerDialog : DialogFragment() {
profile?.let { profile?.let {
profileview_units.text = it.units profileview_units.text = it.units
profileview_dia.text = MainApp.gs(R.string.format_hours, it.dia) profileview_dia.text = resourceHelper.gs(R.string.format_hours, it.dia)
profileview_activeprofile.text = profileName profileview_activeprofile.text = profileName
profileview_date.text = date profileview_date.text = date
profileview_ic.text = it.icList profileview_ic.text = it.icList

View file

@ -1,29 +1,40 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater 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.MainApp
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.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_tempbasal.* import kotlinx.android.synthetic.main.dialog_tempbasal.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
class TempBasalDialog : DialogFragmentWithDate() { class TempBasalDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var ctx: Context
private var isPercentPump = true private var isPercentPump = true
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
@ -42,8 +53,8 @@ class TempBasalDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return val pumpDescription = activePlugin.activePump.pumpDescription
val profile = ProfileFunctions.getInstance().profile ?: return val profile = profileFunction.getProfile() ?: return
val maxTempPercent = pumpDescription.maxTempPercent.toDouble() val maxTempPercent = pumpDescription.maxTempPercent.toDouble()
val tempPercentStep = pumpDescription.tempPercentStep.toDouble() val tempPercentStep = pumpDescription.tempPercentStep.toDouble()
@ -73,42 +84,42 @@ class TempBasalDialog : DialogFragmentWithDate() {
var percent = 0 var percent = 0
var absolute = 0.0 var absolute = 0.0
val durationInMinutes = SafeParse.stringToInt(actions_tempbasal_duration.text) val durationInMinutes = SafeParse.stringToInt(actions_tempbasal_duration.text)
val profile = ProfileFunctions.getInstance().profile ?: return false val profile = profileFunction.getProfile() ?: return false
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
if (isPercentPump) { if (isPercentPump) {
val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text) val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text)
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value() percent = constraintChecker.applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": $percent%") actions.add(resourceHelper.gs(R.string.pump_tempbasal_label) + ": $percent%")
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
if (percent != basalPercentInput) actions.add(MainApp.gs(R.string.constraintapllied)) if (percent != basalPercentInput) actions.add(resourceHelper.gs(R.string.constraintapllied))
} else { } else {
val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text) val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text)
absolute = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value() absolute = constraintChecker.applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": " + MainApp.gs(R.string.pump_basebasalrate, absolute)) actions.add(resourceHelper.gs(R.string.pump_tempbasal_label) + ": " + resourceHelper.gs(R.string.pump_basebasalrate, absolute))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
if (abs(absolute - basalAbsoluteInput) > 0.01) if (abs(absolute - basalAbsoluteInput) > 0.01)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.constraintapllied) + "</font>")
} }
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.pump_tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.pump_tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
val callback: Callback = object : Callback() { val callback: Callback = object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) val i = Intent(ctx, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror) i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment) i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)) i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i) ctx.startActivity(i)
} }
} }
} }
if (isPercentPump) { if (isPercentPump) {
log.debug("USER ENTRY: TEMP BASAL $percent% duration: $durationInMinutes") aapsLogger.debug("USER ENTRY: TEMP BASAL $percent% duration: $durationInMinutes")
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback) commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
} else { } else {
log.debug("USER ENTRY: TEMP BASAL $absolute duration: $durationInMinutes") aapsLogger.debug("USER ENTRY: TEMP BASAL $absolute duration: $durationInMinutes")
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback) commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
} }
}) })
} }

View file

@ -9,24 +9,30 @@ import android.widget.ArrayAdapter
import com.google.common.base.Joiner 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.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
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.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_temptarget.* import kotlinx.android.synthetic.main.dialog_temptarget.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
class TempTargetDialog : DialogFragmentWithDate() { class TempTargetDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState) super.onSaveInstanceState(savedInstanceState)
@ -46,7 +52,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
overview_temptarget_duration.setParams(savedInstanceState?.getDouble("overview_temptarget_duration") overview_temptarget_duration.setParams(savedInstanceState?.getDouble("overview_temptarget_duration")
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok) ?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
if (ProfileFunctions.getSystemUnits() == Constants.MMOL) if (profileFunction.getUnits() == Constants.MMOL)
overview_temptarget_temptarget.setParams( overview_temptarget_temptarget.setParams(
savedInstanceState?.getDouble("overview_temptarget_temptarget") savedInstanceState?.getDouble("overview_temptarget_temptarget")
?: Constants.MIN_TT_MMOL, ?: Constants.MIN_TT_MMOL,
@ -57,16 +63,16 @@ class TempTargetDialog : DialogFragmentWithDate() {
?: Constants.MIN_TT_MGDL, ?: Constants.MIN_TT_MGDL,
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, ok) Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, ok)
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
overview_temptarget_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl) overview_temptarget_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
// temp target // temp target
context?.let { context -> context?.let { context ->
val reasonList: List<String> = Lists.newArrayList( val reasonList: List<String> = Lists.newArrayList(
MainApp.gs(R.string.manual), resourceHelper.gs(R.string.manual),
MainApp.gs(R.string.cancel), resourceHelper.gs(R.string.cancel),
MainApp.gs(R.string.eatingsoon), resourceHelper.gs(R.string.eatingsoon),
MainApp.gs(R.string.activity), resourceHelper.gs(R.string.activity),
MainApp.gs(R.string.hypo) resourceHelper.gs(R.string.hypo)
) )
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList) val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
overview_temptarget_reason.adapter = adapterReason overview_temptarget_reason.adapter = adapterReason
@ -75,22 +81,22 @@ class TempTargetDialog : DialogFragmentWithDate() {
val defaultDuration: Double val defaultDuration: Double
val defaultTarget: Double val defaultTarget: Double
when (reasonList[position]) { when (reasonList[position]) {
MainApp.gs(R.string.eatingsoon) -> { resourceHelper.gs(R.string.eatingsoon) -> {
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration().toDouble() defaultDuration = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineEatingSoonTT() defaultTarget = defaultValueHelper.determineEatingSoonTT()
} }
MainApp.gs(R.string.activity) -> { resourceHelper.gs(R.string.activity) -> {
defaultDuration = DefaultValueHelper.determineActivityTTDuration().toDouble() defaultDuration = defaultValueHelper.determineActivityTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineActivityTT() defaultTarget = defaultValueHelper.determineActivityTT()
} }
MainApp.gs(R.string.hypo) -> { resourceHelper.gs(R.string.hypo) -> {
defaultDuration = DefaultValueHelper.determineHypoTTDuration().toDouble() defaultDuration = defaultValueHelper.determineHypoTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineHypoTT() defaultTarget = defaultValueHelper.determineHypoTT()
} }
MainApp.gs(R.string.cancel) -> { resourceHelper.gs(R.string.cancel) -> {
defaultDuration = 0.0 defaultDuration = 0.0
defaultTarget = 0.0 defaultTarget = 0.0
} }
@ -112,40 +118,40 @@ class TempTargetDialog : DialogFragmentWithDate() {
override fun submit(): Boolean { override fun submit(): Boolean {
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
val reason = overview_temptarget_reason.selectedItem.toString() val reason = overview_temptarget_reason.selectedItem.toString()
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
val target = overview_temptarget_temptarget.value val target = overview_temptarget_temptarget.value
val duration = overview_temptarget_duration.value.toInt() val duration = overview_temptarget_duration.value.toInt()
if (target != 0.0 && duration != 0) { if (target != 0.0 && duration != 0) {
actions.add(MainApp.gs(R.string.reason) + ": " + reason) actions.add(resourceHelper.gs(R.string.reason) + ": " + reason)
actions.add(MainApp.gs(R.string.nsprofileview_target_label) + ": " + Profile.toCurrentUnitsString(target) + " " + MainApp.gs(unitResId)) actions.add(resourceHelper.gs(R.string.nsprofileview_target_label) + ": " + Profile.toCurrentUnitsString(profileFunction, target) + " " + resourceHelper.gs(unitResId))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, duration)) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
} else { } else {
actions.add(MainApp.gs(R.string.stoptemptarget)) actions.add(resourceHelper.gs(R.string.stoptemptarget))
} }
if (eventTimeChanged) if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime)) actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
log.debug("USER ENTRY: TEMP TARGET $target duration: $duration") aapsLogger.debug("USER ENTRY: TEMP TARGET $target duration: $duration")
if (target == 0.0 || duration == 0) { if (target == 0.0 || duration == 0) {
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(eventTime) .date(eventTime)
.duration(0) .duration(0)
.low(0.0).high(0.0) .low(0.0).high(0.0)
.source(Source.USER) .source(Source.USER)
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) treatmentsPlugin.addToHistoryTempTarget(tempTarget)
} else { } else {
val tempTarget = TempTarget() val tempTarget = TempTarget()
.date(eventTime) .date(eventTime)
.duration(duration.toInt()) .duration(duration)
.reason(reason) .reason(reason)
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(target, ProfileFunctions.getSystemUnits())) .low(Profile.toMgdl(target, profileFunction.getUnits()))
.high(Profile.toMgdl(target, ProfileFunctions.getSystemUnits())) .high(Profile.toMgdl(target, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) treatmentsPlugin.addToHistoryTempTarget(tempTarget)
} }
if (duration == 10) SP.putBoolean(R.string.key_objectiveusetemptarget, true) if (duration == 10) sp.putBoolean(R.string.key_objectiveusetemptarget, true)
}) })
} }
return true return true

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
@ -8,30 +9,35 @@ 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.MainApp
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.db.CareportalEvent import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_treatment.* import kotlinx.android.synthetic.main.dialog_treatment.*
import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
class TreatmentDialog : DialogFragmentWithDate() { class TreatmentDialog : DialogFragmentWithDate() {
private var maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble() @Inject lateinit var constraintChecker: ConstraintChecker
private var maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value() @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var ctx: Context
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {} override fun afterTextChanged(s: Editable) {}
@ -42,13 +48,15 @@ class TreatmentDialog : DialogFragmentWithDate() {
} }
private fun validateInputs() { private fun validateInputs() {
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) { if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) {
overview_treatment_carbs.value = 0.0 overview_treatment_carbs.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.carbsconstraintapplied))
} }
if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) { if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) {
overview_treatment_insulin.value = 0.0 overview_treatment_insulin.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied)) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.bolusconstraintapplied))
} }
} }
@ -67,39 +75,40 @@ class TreatmentDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
val pumpDescription = activePlugin.activePump.pumpDescription
overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs") overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
overview_treatment_insulin.setParams(savedInstanceState?.getDouble("overview_treatment_insulin") overview_treatment_insulin.setParams(savedInstanceState?.getDouble("overview_treatment_insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher) ?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
} }
override fun submit(): Boolean { override fun submit(): Boolean {
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription val pumpDescription = activePlugin.activePump.pumpDescription
?: return false
val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text) val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text)
val carbs = SafeParse.stringToInt(overview_treatment_carbs.text) val carbs = SafeParse.stringToInt(overview_treatment_carbs.text)
val recordOnlyChecked = overview_treatment_record_only.isChecked val recordOnlyChecked = overview_treatment_record_only.isChecked
val actions: LinkedList<String?> = LinkedList() val actions: LinkedList<String?> = LinkedList()
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value() val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>") actions.add(resourceHelper.gs(R.string.bolus) + ": " + "<font color='" + resourceHelper.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump) + resourceHelper.gs(R.string.insulin_unit_shortname) + "</font>")
if (recordOnlyChecked) if (recordOnlyChecked)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.bolusrecordedonly) + "</font>")
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints)) actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarning, resourceHelper.gc(R.color.warning), insulin, insulinAfterConstraints))
} }
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>") actions.add(resourceHelper.gs(R.string.carbs) + ": " + "<font color='" + resourceHelper.gc(R.color.carbs) + "'>" + resourceHelper.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
if (carbsAfterConstraints != carbs) if (carbsAfterConstraints != carbs)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>") actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.carbsconstraintapplied) + "</font>")
} }
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) { if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
log.debug("USER ENTRY: BOLUS insulin $insulin carbs: $carbs") aapsLogger.debug("USER ENTRY: BOLUS insulin $insulin carbs: $carbs")
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
@ -108,25 +117,25 @@ class TreatmentDialog : DialogFragmentWithDate() {
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER detailedBolusInfo.source = Source.USER
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) { if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) {
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) val i = Intent(ctx, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror) i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment) i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i) ctx.startActivity(i)
} }
} }
}) })
} else } else
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false) activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
}) })
} }
} else } else
activity?.let { activity -> activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.overview_treatment_label), MainApp.gs(R.string.no_action_selected)) OKDialog.show(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.no_action_selected))
} }
return true return true
} }

View file

@ -12,31 +12,51 @@ import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.CompoundButton import android.widget.CompoundButton
import androidx.fragment.app.DialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.db.BgReading
import info.nightscout.androidaps.db.DatabaseHelper import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.wizard.BolusWizard
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.dialog_wizard.* import kotlinx.android.synthetic.main.dialog_wizard.*
import org.slf4j.LoggerFactory
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
class WizardDialog : DialogFragment() { class WizardDialog : DaggerDialogFragment() {
private val log = LoggerFactory.getLogger(WizardDialog::class.java)
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var mainApp: MainApp
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
private var wizard: BolusWizard? = null private var wizard: BolusWizard? = null
@ -79,29 +99,28 @@ class WizardDialog : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
loadCheckedStates() loadCheckedStates()
processCobCheckBox() processCobCheckBox()
treatments_wizard_sbcheckbox.visibility = SP.getBoolean(R.string.key_usesuperbolus, false).toVisibility() treatments_wizard_sbcheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
treatments_wizard_notes_layout.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility() treatments_wizard_notes_layout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value() val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value() val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input") treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
?: 0.0, 0.0, 500.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher) ?: 0.0, 0.0, 500.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher)
treatments_wizard_carbs_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carbs_input") treatments_wizard_carbs_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carbs_input")
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher)
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
?: 0.1
treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input") treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input")
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher) ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input") treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input")
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
initDialog() initDialog()
treatments_wizard_percent_used.text = MainApp.gs(R.string.format_percent, SP.getInt(R.string.key_boluswizard_percentage, 100)) treatments_wizard_percent_used.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
// ok button // ok button
ok.setOnClickListener { ok.setOnClickListener {
if (okClicked) { if (okClicked) {
log.debug("guarding: ok already clicked") aapsLogger.debug(LTag.UI, "guarding: ok already clicked")
} else { } else {
okClicked = true okClicked = true
calculateInsulin() calculateInsulin()
@ -122,13 +141,13 @@ class WizardDialog : DialogFragment() {
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged) treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged) treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
val showCalc = SP.getBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), false) val showCalc = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), false)
treatments_wizard_delimiter.visibility = showCalc.toVisibility() treatments_wizard_delimiter.visibility = showCalc.toVisibility()
treatments_wizard_resulttable.visibility = showCalc.toVisibility() treatments_wizard_resulttable.visibility = showCalc.toVisibility()
treatments_wizard_calculationcheckbox.isChecked = showCalc treatments_wizard_calculationcheckbox.isChecked = showCalc
treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked -> treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
run { run {
SP.putBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), isChecked) sp.putBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), isChecked)
treatments_wizard_delimiter.visibility = isChecked.toVisibility() treatments_wizard_delimiter.visibility = isChecked.toVisibility()
treatments_wizard_resulttable.visibility = isChecked.toVisibility() treatments_wizard_resulttable.visibility = isChecked.toVisibility()
} }
@ -136,7 +155,7 @@ class WizardDialog : DialogFragment() {
// profile spinner // profile spinner
treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener { treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofileselected)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected))
ok.visibility = View.GONE ok.visibility = View.GONE
} }
@ -146,14 +165,12 @@ class WizardDialog : DialogFragment() {
} }
} }
// bus // bus
disposable.add(RxBus disposable.add(rxBus
.toObservable(EventAutosensCalculationFinished::class.java) .toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ .subscribe({
activity?.runOnUiThread { calculateInsulin() } activity?.runOnUiThread { calculateInsulin() }
}, { }, { fabricPrivacy.logException(it) })
FabricPrivacy.logException(it)
})
) )
} }
@ -165,7 +182,7 @@ class WizardDialog : DialogFragment() {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) { private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
saveCheckedStates() saveCheckedStates()
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null
if (buttonView.id == treatments_wizard_cobcheckbox.id) if (buttonView.id == treatments_wizard_cobcheckbox.id)
processCobCheckBox() processCobCheckBox()
calculateInsulin() calculateInsulin()
@ -184,34 +201,34 @@ class WizardDialog : DialogFragment() {
} }
private fun saveCheckedStates() { private fun saveCheckedStates() {
SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked) sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked)
SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked) sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked)
} }
private fun loadCheckedStates() { private fun loadCheckedStates() {
treatments_wizard_bgtrendcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false) treatments_wizard_bgtrendcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), false)
treatments_wizard_cobcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false) treatments_wizard_cobcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), false)
} }
private fun initDialog() { private fun initDialog() {
val profile = ProfileFunctions.getInstance().profile val profile = profileFunction.getProfile()
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile val profileStore = activePlugin.activeProfileInterface.profile
if (profile == null || profileStore == null) { if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofile)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofile))
dismiss() dismiss()
return return
} }
val profileList: ArrayList<CharSequence> val profileList: ArrayList<CharSequence>
profileList = profileStore.getProfileList() profileList = profileStore.getProfileList()
profileList.add(0, MainApp.gs(R.string.active)) profileList.add(0, resourceHelper.gs(R.string.active))
context?.let { context -> context?.let { context ->
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
treatments_wizard_profile.adapter = adapter treatments_wizard_profile.adapter = adapter
} ?: return } ?: return
val units = ProfileFunctions.getSystemUnits() val units = profileFunction.getUnits()
treatments_wizard_bgunits.text = units treatments_wizard_bgunits.text = units
if (units == Constants.MGDL) if (units == Constants.MGDL)
treatments_wizard_bg_input.setStep(1.0) treatments_wizard_bg_input.setStep(1.0)
@ -219,38 +236,38 @@ class WizardDialog : DialogFragment() {
treatments_wizard_bg_input.setStep(0.1) treatments_wizard_bg_input.setStep(0.1)
// Set BG if not old // Set BG if not old
val lastBg = DatabaseHelper.actualBg() val lastBg = iobCobCalculatorPlugin.actualBg()
if (lastBg != null) { if (lastBg != null) {
treatments_wizard_bg_input.value = lastBg.valueToUnits(units) treatments_wizard_bg_input.value = lastBg.valueToUnits(units)
} else { } else {
treatments_wizard_bg_input.value = 0.0 treatments_wizard_bg_input.value = 0.0
} }
treatments_wizard_ttcheckbox.isEnabled = TreatmentsPlugin.getPlugin().tempTargetFromHistory != null treatments_wizard_ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null
// IOB calculation // IOB calculation
TreatmentsPlugin.getPlugin().updateTotalIOBTreatments() treatmentsPlugin.updateTotalIOBTreatments()
val bolusIob = TreatmentsPlugin.getPlugin().lastCalculationTreatments.round() val bolusIob = treatmentsPlugin.lastCalculationTreatments.round()
TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals() treatmentsPlugin.updateTotalIOBTempBasals()
val basalIob = TreatmentsPlugin.getPlugin().lastCalculationTempBasals.round() val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(-bolusIob.iob) treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob)
treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(-basalIob.basaliob) treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob)
calculateInsulin() calculateInsulin()
treatments_wizard_percent_used.visibility = (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility() treatments_wizard_percent_used.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
} }
private fun calculateInsulin() { private fun calculateInsulin() {
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile val profileStore = activePlugin.activeProfileInterface.profile
if (treatments_wizard_profile.selectedItem == null || profileStore == null) if (treatments_wizard_profile.selectedItem == null || profileStore == null)
return // not initialized yet return // not initialized yet
var profileName = treatments_wizard_profile.selectedItem.toString() var profileName = treatments_wizard_profile.selectedItem.toString()
val specificProfile: Profile? val specificProfile: Profile?
if (profileName == MainApp.gs(R.string.active)) { if (profileName == resourceHelper.gs(R.string.active)) {
specificProfile = ProfileFunctions.getInstance().profile specificProfile = profileFunction.getProfile()
profileName = ProfileFunctions.getInstance().profileName profileName = profileFunction.getProfileName()
} else } else
specificProfile = profileStore.getSpecificProfile(profileName) specificProfile = profileStore.getSpecificProfile(profileName)
@ -260,27 +277,27 @@ class WizardDialog : DialogFragment() {
var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text) var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text)
val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text) val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text)
val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text) val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text)
val carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value() val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
if (abs(carbs - carbsAfterConstraint) > 0.01) { if (abs(carbs - carbsAfterConstraint) > 0.01) {
treatments_wizard_carbs_input.value = 0.0 treatments_wizard_carbs_input.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
return return
} }
bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0 bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0
val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) TreatmentsPlugin.getPlugin().tempTargetFromHistory else null val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null
// COB // COB
var cob = 0.0 var cob = 0.0
if (treatments_wizard_cobcheckbox.isChecked) { if (treatments_wizard_cobcheckbox.isChecked) {
val cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB") val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard COB")
cobInfo.displayCob?.let { cob = it } cobInfo.displayCob?.let { cob = it }
} }
val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text) val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text)
wizard = BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, wizard = BolusWizard(mainApp).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(), sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
treatments_wizard_bgcheckbox.isChecked, treatments_wizard_bgcheckbox.isChecked,
treatments_wizard_cobcheckbox.isChecked, treatments_wizard_cobcheckbox.isChecked,
treatments_wizard_bolusiobcheckbox.isChecked, treatments_wizard_bolusiobcheckbox.isChecked,
@ -291,47 +308,47 @@ class WizardDialog : DialogFragment() {
treatment_wizard_notes.text.toString(), carbTime) treatment_wizard_notes.text.toString(), carbTime)
wizard?.let { wizard -> wizard?.let { wizard ->
treatments_wizard_bg.text = String.format(MainApp.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, ProfileFunctions.getSystemUnits())).valueToUnitsToString(ProfileFunctions.getSystemUnits()), wizard.sens) treatments_wizard_bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens)
treatments_wizard_bginsulin.text = StringUtils.formatInsulin(wizard.insulinFromBG) treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
treatments_wizard_carbs.text = String.format(MainApp.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) treatments_wizard_carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
treatments_wizard_carbsinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCarbs) treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBolusIOB) treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB)
treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBasalsIOB) treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalsIOB)
treatments_wizard_correctioninsulin.text = StringUtils.formatInsulin(wizard.insulinFromCorrection) treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection)
// Superbolus // Superbolus
treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) MainApp.gs(R.string.twohours) else "" treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else ""
treatments_wizard_sbinsulin.text = StringUtils.formatInsulin(wizard.insulinFromSuperBolus) treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus)
// Trend // Trend
if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) { if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "") treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "")
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, ProfileFunctions.getSystemUnits()) + Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, profileFunction.getUnits())
+ " " + ProfileFunctions.getSystemUnits()) + " " + profileFunction.getUnits())
} else { } else {
treatments_wizard_bgtrend.text = "" treatments_wizard_bgtrend.text = ""
} }
treatments_wizard_bgtrendinsulin.text = StringUtils.formatInsulin(wizard.insulinFromTrend) treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend)
// COB // COB
if (treatments_wizard_cobcheckbox.isChecked) { if (treatments_wizard_cobcheckbox.isChecked) {
treatments_wizard_cob.text = String.format(MainApp.gs(R.string.format_cob_ic), cob, wizard.ic) treatments_wizard_cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic)
treatments_wizard_cobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCOB) treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
} else { } else {
treatments_wizard_cob.text = "" treatments_wizard_cob.text = ""
treatments_wizard_cobinsulin.text = "" treatments_wizard_cobinsulin.text = ""
} }
if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) { if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) MainApp.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else "" val insulinText = if (wizard.calculatedTotalInsulin > 0.0) resourceHelper.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else ""
val carbsText = if (carbsAfterConstraint > 0.0) MainApp.gs(R.string.format_carbs, carbsAfterConstraint) else "" val carbsText = if (carbsAfterConstraint > 0.0) resourceHelper.gs(R.string.format_carbs, carbsAfterConstraint) else ""
treatments_wizard_total.text = MainApp.gs(R.string.result_insulin_carbs, insulinText, carbsText) treatments_wizard_total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText)
ok.visibility = View.VISIBLE ok.visibility = View.VISIBLE
} else { } else {
treatments_wizard_total.text = MainApp.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()) treatments_wizard_total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
ok.visibility = View.INVISIBLE ok.visibility = View.INVISIBLE
} }
} }

View file

@ -0,0 +1,88 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_wizardinfo.*
import org.json.JSONObject
import javax.inject.Inject
class WizardInfoDialog : DaggerDialogFragment() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
private var json: JSONObject? = null
fun setData(json: JSONObject) {
this.json = json
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
return inflater.inflate(R.layout.dialog_wizardinfo, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits()
val bgString =
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "bg"))
else DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg"))
// BG
treatments_wizard_bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf"))
treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg"))
treatments_wizard_bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused")
treatments_wizard_ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused")
// Trend
treatments_wizard_bgtrend.text = JsonHelper.safeGetString(json, "trend")
treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend"))
treatments_wizard_bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused")
// COB
treatments_wizard_cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic"))
treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob"))
treatments_wizard_cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused")
// Bolus IOB
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob"))
treatments_wizard_bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused")
// Basal IOB
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob"))
treatments_wizard_basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused")
// Superbolus
treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus"))
treatments_wizard_sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused")
// Carbs
treatments_wizard_carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic"))
treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs"))
// Correction
treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection"))
// Profile
treatments_wizard_profile.text = JsonHelper.safeGetString(json, "profile")
// Notes
treatments_wizard_notes.text = JsonHelper.safeGetString(json, "notes")
// Percentage
treatments_wizard_percent_used.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "percentageCorrection", 100.0)) + "%"
// Total
treatments_wizard_totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin"))
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events
class EventBTChange constructor(val state: Change, val deviceName: String) : Event() {
enum class Change {
CONNECT,
DISCONNECT
}
}

View file

@ -6,9 +6,11 @@ class EventNetworkChange : Event() {
var mobileConnected = false var mobileConnected = false
var wifiConnected = false var wifiConnected = false
var vpnConnected = false
var ssid = "" var ssid = ""
var roaming = false var roaming = false
var metered = false
fun connectedSsid(): String { fun connectedSsid(): String {
return StringUtils.removeSurroundingQuotes(ssid) return StringUtils.removeSurroundingQuotes(ssid)

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
import android.os.Bundle import org.json.JSONArray
/** /**
* Event which is published with data fetched from NightScout specific for the * Event which is published with data fetched from NightScout specific for the
@ -10,7 +10,8 @@ import android.os.Bundle
* subscriber. * subscriber.
*/ */
class EventNsFood(val mode: Int, val payload: Bundle) : Event() { class EventNsFood(val mode: Int, val foods: JSONArray) : Event() {
companion object { companion object {
val ADD = 0 val ADD = 0
val UPDATE = 1 val UPDATE = 1

View file

@ -1,6 +1,8 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
import android.content.res.Resources
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.utils.resources.ResourceHelper
class EventPreferenceChange : Event { class EventPreferenceChange : Event {
private var changedKey: String? = null private var changedKey: String? = null
@ -9,11 +11,11 @@ class EventPreferenceChange : Event {
changedKey = key changedKey = key
} }
constructor(resourceID: Int) { constructor(resourceHelper: ResourceHelper, resourceID: Int) {
changedKey = MainApp.gs(resourceID) changedKey = resourceHelper.gs(resourceID)
} }
fun isChanged(id: Int): Boolean { fun isChanged(resourceHelper: ResourceHelper, id: Int): Boolean {
return changedKey == MainApp.gs(id) return changedKey == resourceHelper.gs(id)
} }
} }

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.resources.ResourceHelper
class EventPumpStatusChanged : EventStatus { class EventPumpStatusChanged : EventStatus {
@ -14,49 +14,44 @@ class EventPumpStatusChanged : EventStatus {
DISCONNECTED DISCONNECTED
} }
var sStatus: Status = Status.DISCONNECTED var status: Status = Status.DISCONNECTED
var sSecondsElapsed = 0 var secondsElapsed = 0
var sPerfomingAction = "" private var performingAction = ""
var error = "" var error = ""
constructor(status: Status) { constructor(status: Status) {
sStatus = status this.status = status
sSecondsElapsed = 0 secondsElapsed = 0
error = "" error = ""
} }
constructor(status: Status, secondsElapsed: Int) { constructor(status: Status, secondsElapsed: Int) {
sStatus = status this.status = status
sSecondsElapsed = secondsElapsed this.secondsElapsed = secondsElapsed
error = "" error = ""
} }
constructor(status: Status, error: String) { constructor(status: Status, error: String) {
sStatus = status this.status = status
sSecondsElapsed = 0 secondsElapsed = 0
this.error = error this.error = error
} }
constructor(action: String) { constructor(action: String) {
sStatus = Status.PERFORMING status = Status.PERFORMING
sSecondsElapsed = 0 secondsElapsed = 0
sPerfomingAction = action performingAction = action
} }
// status for startup wizard // status for startup wizard
override fun getStatus(): String { override fun getStatus(resourceHelper: ResourceHelper): String {
if (sStatus == Status.CONNECTING) return when (status) {
return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed) Status.CONNECTING -> String.format(resourceHelper.gs(R.string.danar_history_connectingfor), secondsElapsed)
else if (sStatus == Status.HANDSHAKING) Status.HANDSHAKING -> resourceHelper.gs(R.string.handshaking)
return MainApp.gs(R.string.handshaking) Status.CONNECTED -> resourceHelper.gs(R.string.connected)
else if (sStatus == Status.CONNECTED) Status.PERFORMING -> performingAction
return MainApp.gs(R.string.connected) Status.DISCONNECTING -> resourceHelper.gs(R.string.disconnecting)
else if (sStatus == Status.PERFORMING) Status.DISCONNECTED -> ""
return sPerfomingAction }
else if (sStatus == Status.DISCONNECTING)
return MainApp.gs(R.string.disconnecting)
else if (sStatus == Status.DISCONNECTED)
return ""
return ""
} }
} }

View file

@ -1,3 +1,3 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
class EventRefreshOverview(var from: String) : Event() class EventRefreshOverview(var from: String, val now : Boolean = false) : Event()

View file

@ -1,6 +1,8 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
import info.nightscout.androidaps.utils.resources.ResourceHelper
// pass string to startup wizard // pass string to startup wizard
abstract class EventStatus :Event() { abstract class EventStatus :Event() {
abstract fun getStatus() : String abstract fun getStatus(resourceHelper: ResourceHelper) : String
} }

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.activities; package info.nightscout.androidaps.historyBrowser;
import android.os.Bundle; import android.os.Bundle;
import android.os.SystemClock; import android.os.SystemClock;
@ -18,35 +18,52 @@ import androidx.core.content.res.ResourcesCompat;
import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.GraphView;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.MainApp; import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventCustomCalculationFinished; import info.nightscout.androidaps.events.EventCustomCalculationFinished;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; 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.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.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.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
public class HistoryBrowseActivity extends NoSplashAppCompatActivity { public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class); @Inject HasAndroidInjector injector;
@Inject AAPSLogger aapsLogger;
@Inject RxBusWrapper rxBus;
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject ProfileFunction profileFunction;
@Inject DefaultValueHelper defaultValueHelper;
@Inject IobCobStaticCalculatorPlugin iobCobStaticCalculatorPlugin;
@Inject ActivePluginProvider activePlugin;
@Inject BuildHelper buildHelper;
@Inject FabricPrivacy fabricPrivacy;
@Inject OverviewMenus overviewMenus;
private CompositeDisposable disposable = new CompositeDisposable(); private CompositeDisposable disposable = new CompositeDisposable();
ImageButton chartButton; ImageButton chartButton;
@ -66,14 +83,9 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
private int rangeToDisplay = 24; // for graph private int rangeToDisplay = 24; // for graph
private long start = 0; private long start = 0;
IobCobCalculatorPlugin iobCobCalculatorPlugin;
EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished(); EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished();
public HistoryBrowseActivity() {
iobCobCalculatorPlugin = new IobCobCalculatorPlugin();
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -153,47 +165,52 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
dpd.show(getSupportFragmentManager(), "Datepickerdialog"); dpd.show(getSupportFragmentManager(), "Datepickerdialog");
}); });
bgGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid)); bgGraph.getGridLabelRenderer().setGridColor(resourceHelper.gc(R.color.graphgrid));
bgGraph.getGridLabelRenderer().reloadStyles(); bgGraph.getGridLabelRenderer().reloadStyles();
iobGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid)); iobGraph.getGridLabelRenderer().setGridColor(resourceHelper.gc(R.color.graphgrid));
iobGraph.getGridLabelRenderer().reloadStyles(); iobGraph.getGridLabelRenderer().reloadStyles();
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false); iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50); bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50); iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5); iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
setupChartMenu(); overviewMenus.setupChartMenu(findViewById(R.id.overview_chartMenuButton));
} }
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
disposable.clear(); disposable.clear();
iobCobCalculatorPlugin.stopCalculation("onPause"); iobCobStaticCalculatorPlugin.stopCalculation("onPause");
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventAutosensCalculationFinished.class) .toObservable(EventAutosensCalculationFinished.class)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> { .subscribe(event -> {
if (event.getCause() == eventCustomCalculationFinished) { if (event.getCause() == eventCustomCalculationFinished) {
log.debug("EventAutosensCalculationFinished"); aapsLogger.debug(LTag.AUTOSENS, "EventAutosensCalculationFinished");
synchronized (HistoryBrowseActivity.this) { synchronized (HistoryBrowseActivity.this) {
updateGUI("EventAutosensCalculationFinished"); updateGUI("EventAutosensCalculationFinished");
} }
} }
}, FabricPrivacy::logException) }, fabricPrivacy::logException)
); );
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventIobCalculationProgress.class) .toObservable(EventIobCalculationProgress.class)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> { .subscribe(event -> {
if (iobCalculationProgressView != null) if (iobCalculationProgressView != null)
iobCalculationProgressView.setText(event.getProgress()); iobCalculationProgressView.setText(event.getProgress());
}, FabricPrivacy::logException) }, exception -> fabricPrivacy.logException(exception))
);
disposable.add(rxBus
.toObservable(EventRefreshOverview.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> updateGUI("EventRefreshOverview") , fabricPrivacy::logException)
); );
// set start of current day // set start of current day
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
@ -210,19 +227,19 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
private void runCalculation(String from) { private void runCalculation(String from) {
long end = start + T.hours(rangeToDisplay).msecs(); long end = start + T.hours(rangeToDisplay).msecs();
iobCobCalculatorPlugin.stopCalculation(from); iobCobStaticCalculatorPlugin.stopCalculation(from);
iobCobCalculatorPlugin.clearCache(); iobCobStaticCalculatorPlugin.clearCache();
iobCobCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished); iobCobStaticCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished);
} }
void updateGUI(String from) { void updateGUI(String from) {
log.debug("updateGUI from: " + from); aapsLogger.debug(LTag.UI, "updateGUI from: " + from);
if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null) if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null)
return; return;
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final PumpInterface pump = activePlugin.getActivePump();
final Profile profile = ProfileFunctions.getInstance().getProfile(); final Profile profile = profileFunction.getProfile();
if (profile == null) { if (profile == null) {
noProfile.setVisibility(View.VISIBLE); noProfile.setVisibility(View.VISIBLE);
@ -231,24 +248,24 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
noProfile.setVisibility(View.GONE); noProfile.setVisibility(View.GONE);
} }
final double lowLine = OverviewPlugin.INSTANCE.determineLowLine(); final double lowLine = defaultValueHelper.determineLowLine();
final double highLine = OverviewPlugin.INSTANCE.determineHighLine(); final double highLine = defaultValueHelper.determineHighLine();
buttonDate.setText(DateUtil.dateAndTimeString(start)); buttonDate.setText(DateUtil.dateAndTimeString(start));
buttonZoom.setText(String.valueOf(rangeToDisplay)); buttonZoom.setText(String.valueOf(rangeToDisplay));
final boolean showPrediction = false; final boolean showPrediction = false;
showBasal = SP.getBoolean("hist_showbasals", true); showBasal = sp.getBoolean("hist_showbasals", true);
showIob = SP.getBoolean("hist_showiob", true); showIob = sp.getBoolean("hist_showiob", true);
showCob = SP.getBoolean("hist_showcob", true); showCob = sp.getBoolean("hist_showcob", true);
showDev = SP.getBoolean("hist_showdeviations", false); showDev = sp.getBoolean("hist_showdeviations", false);
showRat = SP.getBoolean("hist_showratios", false); showRat = sp.getBoolean("hist_showratios", false);
showActPrim = SP.getBoolean("hist_showactivityprimary", false); showActPrim = sp.getBoolean("hist_showactivityprimary", false);
showActSec = SP.getBoolean("hist_showactivitysecondary", false); showActSec = sp.getBoolean("hist_showactivitysecondary", false);
showDevslope = SP.getBoolean("hist_showdevslope", false); showDevslope = sp.getBoolean("hist_showdevslope", false);
int hoursToFetch; //int hoursToFetch;
final long toTime; final long toTime;
final long fromTime; final long fromTime;
//if (showPrediction) { //if (showPrediction) {
@ -264,13 +281,13 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
toTime = start + T.hours(rangeToDisplay).msecs(); toTime = start + T.hours(rangeToDisplay).msecs();
//} //}
log.debug("Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime)); aapsLogger.debug(LTag.UI, "Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime));
final long pointer = System.currentTimeMillis(); final long pointer = System.currentTimeMillis();
// ------------------ 1st graph // ------------------ 1st graph
final GraphData graphData = new GraphData(bgGraph, iobCobCalculatorPlugin); final GraphData graphData = new GraphData(injector, bgGraph, iobCobStaticCalculatorPlugin);
// **** In range Area **** // **** In range Area ****
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine); graphData.addInRangeArea(fromTime, toTime, lowLine, highLine);
@ -294,7 +311,7 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
// add basal data // add basal data
if (pump.getPumpDescription().isTempBasalCapable && showBasal) { if (pump.getPumpDescription().isTempBasalCapable && showBasal) {
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d); graphData.addBasals(fromTime, toTime, lowLine / graphData.getMaxY() / 1.2d);
} }
// **** NOW line **** // **** NOW line ****
@ -303,7 +320,7 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
// ------------------ 2nd graph // ------------------ 2nd graph
new Thread(() -> { new Thread(() -> {
final GraphData secondGraphData = new GraphData(iobGraph, iobCobCalculatorPlugin); final GraphData secondGraphData = new GraphData(injector, iobGraph, iobCobStaticCalculatorPlugin);
boolean useIobForScale = false; boolean useIobForScale = false;
boolean useCobForScale = false; boolean useCobForScale = false;
@ -358,124 +375,4 @@ public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
}); });
}).start(); }).start();
} }
private void setupChartMenu() {
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
chartButton.setOnClickListener(v -> {
MenuItem item, dividerItem;
CharSequence title;
int titleMaxChars = 0;
SpannableString s;
PopupMenu popup = new PopupMenu(v.getContext(), v);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showBasal);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTPRIM.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showActPrim);
dividerItem = popup.getMenu().add("");
dividerItem.setEnabled(false);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showIob);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showCob);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showDev);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showRat);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTSEC.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity));
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showActSec);
if (MainApp.devBranch) {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
title = item.getTitle();
if (titleMaxChars < title.length()) titleMaxChars = title.length();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showDevslope);
}
// Fairly good guestimate for required divider text size...
title = new String(new char[titleMaxChars + 10]).replace("\0", "_");
dividerItem.setTitle(title);
popup.setOnMenuItemClickListener(item1 -> {
if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
SP.putBoolean("hist_showbasals", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) {
SP.putBoolean("hist_showiob", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) {
SP.putBoolean("hist_showcob", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) {
SP.putBoolean("hist_showdeviations", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
SP.putBoolean("hist_showratios", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) {
SP.putBoolean("hist_showactivityprimary", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) {
SP.putBoolean("hist_showactivitysecondary", !item1.isChecked());
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
SP.putBoolean("hist_showdevslope", !item1.isChecked());
}
updateGUI("onGraphCheckboxesCheckedChanged");
return true;
});
chartButton.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
popup.setOnDismissListener(menu -> chartButton.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp));
popup.show();
});
}
} }

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.historyBrowser
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class IobCobStaticCalculatorPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
rxBus: RxBusWrapper,
sp: SP,
resourceHelper: ResourceHelper,
profileFunction: ProfileFunction,
activePlugin: ActivePluginProvider,
treatmentsPlugin: TreatmentsPlugin,
sensitivityOref1Plugin: SensitivityOref1Plugin,
sensitivityAAPSPlugin: SensitivityAAPSPlugin,
sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
fabricPrivacy: FabricPrivacy
) : IobCobCalculatorPlugin(injector, aapsLogger, rxBus, sp, resourceHelper, profileFunction,
activePlugin, treatmentsPlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy) {
override fun onStart() { // do not attach to rxbus
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.interfaces;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public interface ActivePluginProvider {
@NotNull BgSourceInterface getActiveBgSource(); // Forced to Dexcom
@NotNull ProfileInterface getActiveProfileInterface(); // Forced to LocalProfile if not changed
@NotNull InsulinInterface getActiveInsulin(); // Forced to RapidActing if not changed
@NotNull APSInterface getActiveAPS(); // Forced to SMB
@NotNull PumpInterface getActivePump(); // Use in places not reachable without active pump. Otherwise IllegalStateException is thrown
@NotNull SensitivityInterface getActiveSensitivity(); // Forced to oref1 if not changed
@NotNull TreatmentsInterface getActiveTreatments(); // Forced to treatments
@NotNull ArrayList<PluginBase> getPluginsList();
@NotNull ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, PluginType type);
@NotNull ArrayList<PluginBase> getSpecificPluginsVisibleInList(PluginType type);
@NotNull ArrayList<PluginBase> getSpecificPluginsListByInterface(Class interfaceClass);
// @NotNull ArrayList<PluginBase> getSpecificPluginsVisibleInList(Class interfaceClass);
void verifySelectionInCategories();
}

View file

@ -0,0 +1,38 @@
package info.nightscout.androidaps.interfaces
import android.text.Spanned
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
interface CommandQueueProvider {
fun isRunning(type: Command.CommandType): Boolean
fun pickup()
fun clear()
fun size(): Int
fun performing(): Command?
fun resetPerforming()
fun independentConnect(reason: String, callback: Callback?)
fun bolusInQueue(): Boolean
fun bolus(detailedBolusInfo: DetailedBolusInfo, callback: Callback?): Boolean
fun cancelAllBoluses()
fun stopPump(callback: Callback?)
fun startPump(callback: Callback?)
fun setTBROverNotification(callback: Callback?, enable: Boolean)
fun tempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean
fun tempBasalPercent(percent: Int, durationInMinutes: Int, enforceNew: Boolean, profile: Profile, callback: Callback?): Boolean
fun extendedBolus(insulin: Double, durationInMinutes: Int, callback: Callback?): Boolean
fun cancelTempBasal(enforceNew: Boolean, callback: Callback?): Boolean
fun cancelExtended(callback: Callback?): Boolean
fun setProfile(profile: Profile, callback: Callback?): Boolean
fun readStatus(reason: String, callback: Callback?): Boolean
fun statusInQueue(): Boolean
fun loadHistory(type: Byte, callback: Callback?): Boolean
fun setUserOptions(callback: Callback?): Boolean
fun loadTDDs(callback: Callback?): Boolean
fun loadEvents(callback: Callback?): Boolean
fun spannedStatus(): Spanned
fun isThisProfileSet(profile: Profile): Boolean
}

View file

@ -1,25 +1,21 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
/** /**
* Created by mike on 19.03.2018. * Created by mike on 19.03.2018.
*/ */
public class Constraint<T extends Comparable> { public class Constraint<T extends Comparable> {
private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); private T value;
private T originalValue;
T value; private List<String> reasons = new ArrayList<>();
T originalValue; private List<String> mostLimiting = new ArrayList<>();
List<String> reasons = new ArrayList<>();
List<String> mostLimiting = new ArrayList<>();
public Constraint(T value) { public Constraint(T value) {
this.value = value; this.value = value;
@ -34,27 +30,24 @@ public class Constraint<T extends Comparable> {
return originalValue; return originalValue;
} }
public Constraint<T> set(T value) { public Constraint<T> set(AAPSLogger aapsLogger, T value) {
this.value = value; this.value = value;
this.originalValue = value; this.originalValue = value;
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Setting value " + value);
log.debug("Setting value " + value);
return this; return this;
} }
public Constraint<T> set(T value, String reason, Object from) { public Constraint<T> set(AAPSLogger aapsLogger, T value, String reason, Object from) {
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Setting value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
log.debug("Setting value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
this.value = value; this.value = value;
addReason(reason, from); addReason(reason, from);
addMostLimingReason(reason, from); addMostLimingReason(reason, from);
return this; return this;
} }
public Constraint<T> setIfDifferent(T value, String reason, Object from) { public Constraint<T> setIfDifferent(AAPSLogger aapsLogger, T value, String reason, Object from) {
if (!this.value.equals(value)) { if (!this.value.equals(value)) {
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Setting because of different value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
log.debug("Setting because of different value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
this.value = value; this.value = value;
addReason(reason, from); addReason(reason, from);
addMostLimingReason(reason, from); addMostLimingReason(reason, from);
@ -62,10 +55,9 @@ public class Constraint<T extends Comparable> {
return this; return this;
} }
public Constraint<T> setIfSmaller(T value, String reason, Object from) { public Constraint<T> setIfSmaller(AAPSLogger aapsLogger, T value, String reason, Object from) {
if (value.compareTo(this.value) < 0) { if (value.compareTo(this.value) < 0) {
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Setting because of smaller value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
log.debug("Setting because of smaller value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
this.value = value; this.value = value;
mostLimiting.clear(); mostLimiting.clear();
addMostLimingReason(reason, from); addMostLimingReason(reason, from);
@ -76,10 +68,9 @@ public class Constraint<T extends Comparable> {
return this; return this;
} }
public Constraint<T> setIfGreater(T value, String reason, Object from) { public Constraint<T> setIfGreater(AAPSLogger aapsLogger, T value, String reason, Object from) {
if (value.compareTo(this.value) > 0) { if (value.compareTo(this.value) > 0) {
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Setting because of greater value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
log.debug("Setting because of greater value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
this.value = value; this.value = value;
mostLimiting.clear(); mostLimiting.clear();
addMostLimingReason(reason, from); addMostLimingReason(reason, from);
@ -104,15 +95,14 @@ public class Constraint<T extends Comparable> {
return this; return this;
} }
public String getReasons() { public String getReasons(AAPSLogger aapsLogger) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int count = 0; int count = 0;
for (String r : reasons) { for (String r : reasons) {
if (count++ != 0) sb.append("\n"); if (count++ != 0) sb.append("\n");
sb.append(r); sb.append(r);
} }
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
return sb.toString(); return sb.toString();
} }
@ -120,15 +110,14 @@ public class Constraint<T extends Comparable> {
return reasons; return reasons;
} }
public String getMostLimitedReasons() { public String getMostLimitedReasons(AAPSLogger aapsLogger) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int count = 0; int count = 0;
for (String r : mostLimiting) { for (String r : mostLimiting) {
if (count++ != 0) sb.append("\n"); if (count++ != 0) sb.append("\n");
sb.append(r); sb.append(r);
} }
if (L.isEnabled(L.CONSTRAINTS)) aapsLogger.debug(LTag.CONSTRAINTS, "Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
return sb.toString(); return sb.toString();
} }

View file

@ -1,66 +0,0 @@
package info.nightscout.androidaps.interfaces;
import info.nightscout.androidaps.data.Profile;
/**
* Created by mike on 15.06.2016.
*/
public interface ConstraintsInterface {
default Constraint<Boolean> isLoopInvocationAllowed(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isUAMEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Boolean> isSuperBolusEnabled(Constraint<Boolean> value) {
return value;
}
default Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
return absoluteRate;
}
default Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
return percentRate;
}
default Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
return insulin;
}
default Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
return insulin;
}
default Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
return carbs;
}
default Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
return maxIob;
}
}

View file

@ -0,0 +1,84 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.Profile
/**
* Created by mike on 15.06.2016.
*/
interface ConstraintsInterface {
@JvmDefault
fun isLoopInvocationAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isClosedLoopAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isAutosensModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isAMAModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isSMBModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isUAMEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isAdvancedFilteringEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun isSuperBolusEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
@JvmDefault
fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
return absoluteRate
}
@JvmDefault
fun applyBasalPercentConstraints(percentRate: Constraint<Int>, profile: Profile): Constraint<Int> {
return percentRate
}
@JvmDefault
fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
return insulin
}
@JvmDefault
fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
return insulin
}
@JvmDefault
fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> {
return carbs
}
@JvmDefault
fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> {
return maxIob
}
@JvmDefault
fun isAutomationEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
return value
}
}

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import dagger.android.HasAndroidInjector;
/** /**
* Created by mike on 21.05.2017. * Created by mike on 21.05.2017.
*/ */

View file

@ -1,223 +0,0 @@
package info.nightscout.androidaps.interfaces;
import android.os.SystemClock;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import androidx.fragment.app.FragmentActivity;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.EventConfigBuilderUpdateGui;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 09.06.2016.
*/
public abstract class PluginBase {
private static Logger log = LoggerFactory.getLogger(L.CORE);
public enum State {
NOT_INITIALIZED,
ENABLED,
DISABLED
}
private State state = State.NOT_INITIALIZED;
private boolean isFragmentVisible = false;
public PluginDescription pluginDescription;
// Specific plugin with more Interfaces
protected boolean isProfileInterfaceEnabled = false;
public PluginBase(PluginDescription pluginDescription) {
this.pluginDescription = pluginDescription;
}
// Default always calls invoke
// Plugins that have special constraints if they get switched to may override this method
public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) {
performPluginSwitch(newState, type);
}
protected void confirmPumpPluginActivation(boolean newState, FragmentActivity activity, PluginType type) {
if (type == PluginType.PUMP) {
boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
if (allowHardwarePump || activity == null) {
performPluginSwitch(newState, type);
} else {
OKDialog.showConfirmation(activity, MainApp.gs(R.string.allow_hardware_pump_text), () -> {
performPluginSwitch(newState, type);
SP.putBoolean("allow_hardware_pump", true);
if (L.isEnabled(L.PUMP))
log.debug("First time HW pump allowed!");
}, () -> {
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
if (L.isEnabled(L.PUMP))
log.debug("User does not allow switching to HW pump!");
});
}
} else {
performPluginSwitch(newState, type);
}
}
public void performPluginSwitch(boolean enabled, PluginType type) {
setPluginEnabled(type, enabled);
setFragmentVisible(type, enabled);
ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(this, getType());
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
RxBus.INSTANCE.send(new EventRebuildTabs());
RxBus.INSTANCE.send(new EventConfigBuilderChange());
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
ConfigBuilderPlugin.getPlugin().logPluginStatus();
}
public String getName() {
if (pluginDescription.pluginName == -1)
return "UKNOWN";
else
return MainApp.gs(pluginDescription.pluginName);
}
public String getNameShort() {
if (pluginDescription.shortName == -1)
return getName();
String name = MainApp.gs(pluginDescription.shortName);
if (!name.trim().isEmpty()) //only if translation exists
return name;
// use long name as fallback
return getName();
}
public String getDescription() {
if (pluginDescription.description == -1) return null;
else return MainApp.gs(pluginDescription.description);
}
public PluginType getType() {
return pluginDescription.mainType;
}
public int getPreferencesId() {
return pluginDescription.preferencesId;
}
public boolean isEnabled(PluginType type) {
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType)
return true;
if (pluginDescription.mainType == PluginType.CONSTRAINTS && type == PluginType.CONSTRAINTS)
return true;
if (type == pluginDescription.mainType)
return state == State.ENABLED && specialEnableCondition();
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP))
return true;
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.APS && isEnabled(PluginType.APS))
return true;
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
return isProfileInterfaceEnabled;
return false;
}
public boolean hasFragment() {
return pluginDescription.fragmentClass != null;
}
/**
* So far plugin can have it's main type + ConstraintInterface + ProfileInterface
* ConstraintInterface is enabled if main plugin is enabled
* ProfileInterface can be enabled only if main iterface is enable
*/
public void setPluginEnabled(PluginType type, boolean newState) {
if (type == pluginDescription.mainType) {
if (newState == true) { // enabling plugin
if (state != State.ENABLED) {
onStateChange(type, state, State.ENABLED);
state = State.ENABLED;
if (L.isEnabled(L.CORE))
log.debug("Starting: " + getName());
onStart();
}
} else { // disabling plugin
if (state == State.ENABLED) {
onStateChange(type, state, State.DISABLED);
state = State.DISABLED;
onStop();
if (L.isEnabled(L.CORE))
log.debug("Stopping: " + getName());
}
}
} else if (type == PluginType.PROFILE) {
isProfileInterfaceEnabled = newState;
}
}
public void setFragmentVisible(PluginType type, boolean fragmentVisible) {
if (type == pluginDescription.mainType) {
isFragmentVisible = fragmentVisible && specialEnableCondition();
}
}
public boolean isFragmentVisible() {
if (pluginDescription.alwaysVisible)
return true;
if (pluginDescription.neverVisible)
return false;
return isFragmentVisible;
}
public boolean showInList(PluginType type) {
if (pluginDescription.mainType == type)
return pluginDescription.showInList && specialShowInListCondition();
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
return isEnabled(PluginType.PUMP);
return false;
}
public boolean specialEnableCondition() {
return true;
}
public boolean specialShowInListCondition() {
return true;
}
protected void onStart() {
if (getType() == PluginType.PUMP) {
new Thread(() -> {
SystemClock.sleep(3000);
CommandQueue commandQueue = ConfigBuilderPlugin.getPlugin().getCommandQueue();
if (commandQueue != null)
commandQueue.readStatus("Pump driver changed.", null);
}).start();
}
}
protected void onStop() {
}
protected void onStateChange(PluginType type, State oldState, State newState) {
}
public void preprocessPreferences(@NotNull final PreferenceFragment preferenceFragment) {
}
public void updatePreferenceSummary(@NotNull final Preference pref) {
}
}

View file

@ -0,0 +1,119 @@
package info.nightscout.androidaps.interfaces
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.resources.ResourceHelper
/**
* Created by mike on 09.06.2016.
*/
abstract class PluginBase(
val pluginDescription: PluginDescription,
val aapsLogger: AAPSLogger,
val resourceHelper: ResourceHelper,
val injector: HasAndroidInjector
) {
enum class State {
NOT_INITIALIZED, ENABLED, DISABLED
}
private var state = State.NOT_INITIALIZED
private var fragmentVisible = false
open val name: String
get() = if (pluginDescription.pluginName == -1) "UNKNOWN" else resourceHelper.gs(pluginDescription.pluginName)
//only if translation exists
// use long name as fallback
val nameShort: String
get() {
if (pluginDescription.shortName == -1) return name
val translatedName = resourceHelper.gs(pluginDescription.shortName)
return if (!translatedName.trim { it <= ' ' }.isEmpty()) translatedName else name
// use long name as fallback
}
val description: String?
get() = if (pluginDescription.description == -1) null else resourceHelper.gs(pluginDescription.description)
fun getType(): PluginType = pluginDescription.mainType
open val preferencesId: Int
get() = pluginDescription.preferencesId
fun isEnabled() = isEnabled(pluginDescription.mainType)
fun isEnabled(type: PluginType): Boolean {
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType) return true
if (pluginDescription.mainType == PluginType.CONSTRAINTS && type == PluginType.CONSTRAINTS) return true
if (type == pluginDescription.mainType) return state == State.ENABLED && specialEnableCondition()
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP)) return true
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.APS && isEnabled(PluginType.APS)) return true
return false
}
fun hasFragment(): Boolean {
return pluginDescription.fragmentClass != null
}
fun isDefault() = pluginDescription.defaultPlugin
/**
* So far plugin can have it's main type + ConstraintInterface + ProfileInterface
* ConstraintInterface is enabled if main plugin is enabled
* ProfileInterface can be enabled only if main iterface is enable
*/
fun setPluginEnabled(type: PluginType, newState: Boolean) {
if (type == pluginDescription.mainType) {
if (newState) { // enabling plugin
if (state != State.ENABLED) {
onStateChange(type, state, State.ENABLED)
state = State.ENABLED
aapsLogger.debug(LTag.CORE, "Starting: $name")
onStart()
}
} else { // disabling plugin
if (state == State.ENABLED) {
onStateChange(type, state, State.DISABLED)
state = State.DISABLED
onStop()
aapsLogger.debug(LTag.CORE, "Stopping: $name")
}
}
}
}
fun setFragmentVisible(type: PluginType, fragmentVisible: Boolean) {
if (type == pluginDescription.mainType) {
this.fragmentVisible = fragmentVisible && specialEnableCondition()
}
}
fun isFragmentVisible(): Boolean {
if (pluginDescription.alwaysVisible) return true
return if (pluginDescription.neverVisible) false else fragmentVisible
}
fun showInList(type: PluginType): Boolean {
if (pluginDescription.mainType == type) return pluginDescription.showInList && specialShowInListCondition()
return if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP) isEnabled(PluginType.PUMP) else false
}
open fun specialEnableCondition(): Boolean {
return true
}
open fun specialShowInListCondition(): Boolean {
return true
}
protected open fun onStart() {}
protected open fun onStop() {}
protected open fun onStateChange(type: PluginType?, oldState: State?, newState: State?) {}
open fun preprocessPreferences(preferenceFragment: PreferenceFragmentCompat) {}
open fun updatePreferenceSummary(pref: Preference) {}
}

View file

@ -13,6 +13,7 @@ public class PluginDescription {
int preferencesId = -1; int preferencesId = -1;
public boolean enableByDefault = false; public boolean enableByDefault = false;
public boolean visibleByDefault = false; public boolean visibleByDefault = false;
boolean defaultPlugin = false;
public PluginDescription mainType(PluginType mainType) { public PluginDescription mainType(PluginType mainType) {
this.mainType = mainType; this.mainType = mainType;
@ -74,6 +75,11 @@ public class PluginDescription {
return this; return this;
} }
public PluginDescription setDefault() {
defaultPlugin = true;
return this;
}
public String getFragmentClass() { public String getFragmentClass() {
return fragmentClass; return fragmentClass;
} }

View file

@ -1,9 +1,12 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
@ -41,6 +44,7 @@ public interface PumpInterface {
void getPumpStatus(); void getPumpStatus();
// Upload to pump new basal profile // Upload to pump new basal profile
@NotNull
PumpEnactResult setNewBasalProfile(Profile profile); PumpEnactResult setNewBasalProfile(Profile profile);
boolean isThisProfileSet(Profile profile); boolean isThisProfileSet(Profile profile);
@ -53,43 +57,57 @@ public interface PumpInterface {
int getBatteryLevel(); // in percent as integer int getBatteryLevel(); // in percent as integer
@NotNull
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering(); void stopBolusDelivering();
@NotNull
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew); PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
@NotNull
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
@NotNull
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy //some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
//when the cancel request is requested by the user (forced), the pump should always do a real cancel //when the cancel request is requested by the user (forced), the pump should always do a real cancel
@NotNull
PumpEnactResult cancelTempBasal(boolean enforceNew); PumpEnactResult cancelTempBasal(boolean enforceNew);
@NotNull
PumpEnactResult cancelExtendedBolus(); PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS // Status to be passed to NS
@NotNull
JSONObject getJSONStatus(Profile profile, String profileName); JSONObject getJSONStatus(Profile profile, String profileName);
@NotNull
ManufacturerType manufacturer(); ManufacturerType manufacturer();
@NotNull
PumpType model(); PumpType model();
@NotNull
String serialNumber(); String serialNumber();
// Pump capabilities // Pump capabilities
@NotNull
PumpDescription getPumpDescription(); PumpDescription getPumpDescription();
// Short info for SMS, Wear etc // Short info for SMS, Wear etc
@NotNull
String shortStatus(boolean veryShort); String shortStatus(boolean veryShort);
boolean isFakingTempsByExtendedBoluses(); boolean isFakingTempsByExtendedBoluses();
@NotNull
PumpEnactResult loadTDDs(); PumpEnactResult loadTDDs();
boolean canHandleDST(); boolean canHandleDST();
@Nullable
List<CustomAction> getCustomActions(); List<CustomAction> getCustomActions();
void executeCustomAction(CustomActionType customActionType); void executeCustomAction(CustomActionType customActionType);
@ -97,7 +115,6 @@ public interface PumpInterface {
/** /**
* This method will be called when time or Timezone changes, and pump driver can then do a specific action (for * This method will be called when time or Timezone changes, and pump driver can then do a specific action (for
* example update clock on pump). * example update clock on pump).
* @param timeChangeType
*/ */
void timezoneOrDSTChanged(TimeChangeType timeChangeType); void timezoneOrDSTChanged(TimeChangeType timeChangeType);
@ -105,5 +122,4 @@ public interface PumpInterface {
default boolean isUnreachableAlertTimeoutExceeded(long alertTimeoutMilliseconds) { default boolean isUnreachableAlertTimeoutExceeded(long alertTimeoutMilliseconds) {
return false; return false;
} }
} }

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.interfaces
import android.os.SystemClock
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.utils.resources.ResourceHelper
abstract class PumpPluginBase(
pluginDescription: PluginDescription,
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
resourceHelper: ResourceHelper,
val commandQueue: CommandQueueProvider
) : PluginBase(pluginDescription, aapsLogger, resourceHelper, injector) {
override fun onStart() {
super.onStart()
if (getType() == PluginType.PUMP) {
Thread(Runnable {
SystemClock.sleep(3000)
commandQueue.readStatus("Pump driver changed.", null)
}).start()
}
}
}

View file

@ -1,19 +1,21 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Intervals;
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.NonOverlappingIntervals; import info.nightscout.androidaps.data.NonOverlappingIntervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.ProfileIntervals;
/** /**
* Created by mike on 14.06.2016. * Created by mike on 14.06.2016.
@ -28,8 +30,6 @@ public interface TreatmentsInterface {
IobTotal getLastCalculationTempBasals(); IobTotal getLastCalculationTempBasals();
IobTotal getCalculationToTimeTempBasals(long time); IobTotal getCalculationToTimeTempBasals(long time);
MealData getMealData();
List<Treatment> getTreatmentsFromHistory(); List<Treatment> getTreatmentsFromHistory();
List<Treatment> getCarbTreatments5MinBackFromHistory(long time); List<Treatment> getCarbTreatments5MinBackFromHistory(long time);
List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp); List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp);
@ -62,6 +62,8 @@ public interface TreatmentsInterface {
ProfileSwitch getProfileSwitchFromHistory(long time); ProfileSwitch getProfileSwitchFromHistory(long time);
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory(); ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();
void addToHistoryProfileSwitch(ProfileSwitch profileSwitch); void addToHistoryProfileSwitch(ProfileSwitch profileSwitch);
void doProfileSwitch(@NotNull final ProfileStore profileStore, @NotNull final String profileName, final int duration, final int percentage, final int timeShift, final long date);
void doProfileSwitch(final int duration, final int percentage, final int timeShift);
long oldestDataAvailable(); long oldestDataAvailable();

View file

@ -0,0 +1,22 @@
package info.nightscout.androidaps.logging
/**
* Created by adrian on 2019-12-27.
*/
interface AAPSLogger {
fun debug(message: String)
fun debug(enable: Boolean, tag: LTag, message: String)
fun debug(tag: LTag, message: String)
fun debug(tag: LTag, format: String, vararg arguments: Any?)
fun warn(tag: LTag, message: String)
fun info(tag: LTag, message: String)
fun info(tag: LTag, format: String, vararg arguments: Any?)
fun error(tag: LTag, message: String)
fun error(tag: LTag, message: String, throwable: Throwable)
fun error(tag: LTag, format: String, vararg arguments: Any?)
fun error(message: String)
fun error(message: String, throwable: Throwable)
fun error(format: String, vararg arguments: Any?)
}

View file

@ -0,0 +1,64 @@
package info.nightscout.androidaps.logging
import android.util.Log
/**
* Created by adrian on 2019-12-27.
*/
class AAPSLoggerDebug : AAPSLogger {
override fun debug(message: String) {
Log.d(LTag.CORE.tag, message)
}
override fun debug(enable: Boolean, tag: LTag, message: String) {
if (enable) Log.d(LTag.CORE.tag, message)
}
override fun debug(tag: LTag, message: String) {
Log.d(tag.tag, message)
}
override fun debug(tag: LTag, format: String, vararg arguments: Any?) {
Log.d(tag.tag, String.format(format, arguments))
}
override fun warn(tag: LTag, message: String) {
Log.w(tag.tag, message)
}
override fun info(tag: LTag, message: String) {
Log.i(tag.tag, message)
}
override fun info(tag: LTag, format: String, vararg arguments: Any?) {
Log.i(tag.tag, String.format(format, arguments))
}
override fun error(tag: LTag, message: String) {
Log.e(tag.tag, message)
}
override fun error(message: String) {
Log.e(LTag.CORE.tag, message)
}
override fun error(message: String, throwable: Throwable) {
Log.e(LTag.CORE.tag, message, throwable)
}
override fun error(format: String, vararg arguments: Any?) {
Log.e(LTag.CORE.tag, String.format(format, arguments))
}
override fun error(tag: LTag, message: String, throwable: Throwable) {
Log.e(tag.tag, message, throwable)
}
override fun error(tag: LTag, format: String, vararg arguments: Any?) {
Log.e(tag.tag, String.format(format, arguments))
}
}

View file

@ -0,0 +1,84 @@
package info.nightscout.androidaps.logging
import org.slf4j.LoggerFactory
/**
* Created by adrian on 2019-12-27.
*/
class AAPSLoggerProduction : AAPSLogger {
override fun debug(message: String) {
LoggerFactory.getLogger(LTag.CORE.tag).debug(stackLogMarker() + message)
}
override fun debug(enable: Boolean, tag: LTag, message: String) {
if (enable && L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).debug(stackLogMarker() + message)
}
}
override fun debug(tag: LTag, message: String) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).debug(stackLogMarker() + message)
}
}
override fun debug(tag: LTag, format: String, vararg arguments: Any?) {
if (L.isEnabled(tag.tag))
LoggerFactory.getLogger(tag.tag).debug(stackLogMarker() + String.format(format, arguments))
}
override fun warn(tag: LTag, message: String) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).warn(stackLogMarker() + message)
}
}
override fun info(tag: LTag, message: String) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).info(stackLogMarker() + message)
}
}
override fun info(tag: LTag, format: String, vararg arguments: Any?) {
LoggerFactory.getLogger(tag.tag).info(stackLogMarker() + String.format(format, arguments))
}
override fun error(tag: LTag, message: String) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).error(stackLogMarker() + message)
}
}
override fun error(message: String) {
LoggerFactory.getLogger(LTag.CORE.tag).error(stackLogMarker() + message)
}
override fun error(message: String, throwable: Throwable) {
LoggerFactory.getLogger(LTag.CORE.tag).error(stackLogMarker() + message, throwable)
}
override fun error(format: String, vararg arguments: Any?) {
LoggerFactory.getLogger(LTag.CORE.tag).error(stackLogMarker() + String.format(format, arguments))
}
override fun error(tag: LTag, message: String, throwable: Throwable) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).error(stackLogMarker() + message, throwable)
}
}
override fun error(tag: LTag, format: String, vararg arguments: Any?) {
if (L.isEnabled(tag.tag)) {
LoggerFactory.getLogger(tag.tag).error(stackLogMarker() + String.format(format, arguments))
}
}
}
fun StackTraceElement.toLogString(): String = "[${this.className.substringAfterLast(".")}.${this.methodName}():${this.lineNumber}]: "
/* Needs to be inline. Don't remove even if IDE suggests it. */
@Suppress("NOTHING_TO_INLINE")
inline fun stackLogMarker() = Throwable().stackTrace[1].toLogString()

View file

@ -0,0 +1,60 @@
package info.nightscout.androidaps.logging
/**
* Created by adrian on 2019-12-27.
*/
class AAPSLoggerTest : AAPSLogger {
override fun debug(message: String) {
println("DEBUG: $message")
}
override fun debug(enable: Boolean, tag: LTag, message: String) {
println("DEBUG: " + message)
}
override fun debug(tag: LTag, message: String) {
println("DEBUG: : " + tag.tag + " " + message)
}
override fun debug(tag: LTag, format: String, vararg arguments: Any?) {
println("DEBUG: : " + tag.tag + " " + String.format(format, arguments))
}
override fun warn(tag: LTag, message: String) {
println("WARN: " + tag.tag + " " + message)
}
override fun info(tag: LTag, message: String) {
println("INFO: " + tag.tag + " " + message)
}
override fun info(tag: LTag, format: String, vararg arguments: Any?) {
println("INFO: : " + tag.tag + " " + String.format(format, arguments))
}
override fun error(tag: LTag, message: String) {
println("ERROR: " + tag.tag + " " + message)
}
override fun error(message: String) {
println("ERROR: " + message)
}
override fun error(message: String, throwable: Throwable) {
println("ERROR: " + message + " " + throwable)
}
override fun error(format: String, vararg arguments: Any?) {
println("ERROR: : " + String.format(format, arguments))
}
override fun error(tag: LTag, message: String, throwable: Throwable) {
println("ERROR: " + tag.tag + " " + message + " " + throwable)
}
override fun error(tag: LTag, format: String, vararg arguments: Any?) {
println("ERROR: : " + tag.tag + " " + String.format(format, arguments))
}
}

View file

@ -1,133 +0,0 @@
package info.nightscout.androidaps.logging;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.utils.SP;
public class L {
public static class LogElement {
public String name;
boolean defaultValue;
public boolean enabled;
boolean requiresRestart = false;
LogElement(String name, boolean defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
enabled = SP.getBoolean(getSPName(), defaultValue);
}
LogElement(String name, boolean defaultValue, boolean requiresRestart) {
this.name = name;
this.defaultValue = defaultValue;
this.requiresRestart = requiresRestart;
enabled = SP.getBoolean(getSPName(), defaultValue);
}
LogElement(boolean defaultValue) {
this.name = "NONEXISTING";
this.defaultValue = defaultValue;
enabled = defaultValue;
}
private String getSPName() {
return "log_" + name;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
SP.putBoolean(getSPName(), enabled);
}
void resetToDefault() {
setEnabled(defaultValue);
}
}
private static List<LogElement> logElements;
static {
initialize();
}
private static LogElement findByName(String name) {
for (LogElement element : logElements) {
if (element.name.equals(name))
return element;
}
return new LogElement(false);
}
public static boolean isEnabled(String name) {
return findByName(name).enabled;
}
public static List<LogElement> getLogElements() {
return logElements;
}
public static void resetToDefaults() {
for (LogElement element : logElements) {
element.resetToDefault();
}
}
public static final String CORE = "CORE";
public static final String AUTOSENS = "AUTOSENS";
public static final String AUTOMATION = "AUTOMATION";
public static final String EVENTS = "EVENTS";
public static final String GLUCOSE = "GLUCOSE";
public static final String BGSOURCE = "BGSOURCE";
public static final String OVERVIEW = "OVERVIEW";
public static final String NOTIFICATION = "NOTIFICATION";
public static final String DATASERVICE = "DATASERVICE";
public static final String DATABASE = "DATABASE";
public static final String DATAFOOD = "DATAFOOD";
public static final String DATATREATMENTS = "DATATREATMENTS";
public static final String NSCLIENT = "NSCLIENT";
public static final String TIDEPOOL = "TIDEPOOL";
public static final String CONSTRAINTS = "CONSTRAINTS";
public static final String PUMP = "PUMP";
public static final String PUMPQUEUE = "PUMPQUEUE";
public static final String PUMPCOMM = "PUMPCOMM";
public static final String PUMPBTCOMM = "PUMPBTCOMM";
public static final String APS = "APS";
public static final String PROFILE = "PROFILE";
public static final String CONFIGBUILDER = "CONFIGBUILDER";
public static final String UI = "UI";
public static final String LOCATION = "LOCATION";
public static final String SMS = "SMS";
private static void initialize() {
logElements = new ArrayList<>();
logElements.add(new LogElement(APS, true));
logElements.add(new LogElement(AUTOMATION, true));
logElements.add(new LogElement(AUTOSENS, false));
logElements.add(new LogElement(BGSOURCE, true));
logElements.add(new LogElement(GLUCOSE, false));
logElements.add(new LogElement(CONFIGBUILDER, false));
logElements.add(new LogElement(CONSTRAINTS, true));
logElements.add(new LogElement(CORE, true));
logElements.add(new LogElement(DATABASE, true));
logElements.add(new LogElement(DATAFOOD, false));
logElements.add(new LogElement(DATASERVICE, true));
logElements.add(new LogElement(DATATREATMENTS, true));
logElements.add(new LogElement(EVENTS, false, true));
logElements.add(new LogElement(LOCATION, true));
logElements.add(new LogElement(NOTIFICATION, true));
logElements.add(new LogElement(NSCLIENT, true));
logElements.add(new LogElement(TIDEPOOL, true));
logElements.add(new LogElement(OVERVIEW, true));
logElements.add(new LogElement(PROFILE, true));
logElements.add(new LogElement(PUMP, true));
logElements.add(new LogElement(PUMPBTCOMM, false));
logElements.add(new LogElement(PUMPCOMM, true));
logElements.add(new LogElement(PUMPQUEUE, true));
logElements.add(new LogElement(SMS, true));
logElements.add(new LogElement(UI, true));
}
}

View file

@ -0,0 +1,80 @@
package info.nightscout.androidaps.logging
import androidx.preference.PreferenceManager
import info.nightscout.androidaps.MainApp
import java.util.*
object L {
private var logElements: MutableList<LogElement> = ArrayList()
const val CORE = "CORE"
const val BGSOURCE = "BGSOURCE"
const val DATASERVICE = "DATASERVICE"
const val DATABASE = "DATABASE"
const val DATAFOOD = "DATAFOOD"
const val DATATREATMENTS = "DATATREATMENTS"
const val NSCLIENT = "NSCLIENT"
const val PUMP = "PUMP"
const val PUMPCOMM = "PUMPCOMM"
const val PUMPBTCOMM = "PUMPBTCOMM"
init {
LTag.values().forEach { logElements.add(LogElement(it)) }
}
private fun findByName(name: String): LogElement {
for (element in logElements) {
if (element.name == name) return element
}
return LogElement(false)
}
@JvmStatic
fun isEnabled(name: String): Boolean {
return findByName(name).enabled
}
fun getLogElements(): List<LogElement> {
return logElements
}
fun resetToDefaults() {
for (element in logElements) {
element.resetToDefault()
}
}
class LogElement {
var name: String
var defaultValue: Boolean
var enabled: Boolean
private var requiresRestart = false
internal constructor(tag: LTag) {
this.name = tag.tag
this.defaultValue = tag.defaultValue
this.requiresRestart = tag.requiresRestart
//TODO: remove after getting rid of old logging style "if (L.isEnabled(...))"
@Suppress("DEPRECATION")
enabled = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()).getBoolean(getSPName(), defaultValue)
}
internal constructor(defaultValue: Boolean) {
name = "NONEXISTING"
this.defaultValue = defaultValue
enabled = defaultValue
}
private fun getSPName(): String = "log_$name"
fun enable(enabled: Boolean) {
this.enabled = enabled
@Suppress("DEPRECATION")
PreferenceManager.getDefaultSharedPreferences(MainApp.instance()).edit().putBoolean(getSPName(), enabled).apply()
}
fun resetToDefault() {
enable(defaultValue)
}
}
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.logging
enum class LTag(val tag: String, val defaultValue : Boolean = true, val requiresRestart: Boolean = false) {
CORE("CORE"),
APS("APS"),
AUTOSENS("AUTOSENS", defaultValue = false),
AUTOMATION("AUTOMATION"),
BGSOURCE("BGSOURCE"),
CONFIGBUILDER("CONFIGBUILDER"),
CONSTRAINTS("CONSTRAINTS"),
DATABASE("DATABASE"),
DATAFOOD("DATAFOOD", defaultValue = false),
DATASERVICE("DATASERVICE"),
DATATREATMENTS("DATATREATMENTS"),
EVENTS("EVENTS", defaultValue = false, requiresRestart = true),
GLUCOSE("GLUCOSE"),
LOCATION("LOCATION"),
NOTIFICATION("NOTIFICATION"),
NSCLIENT("NSCLIENT"),
PUMP("PUMP"),
PUMPBTCOMM("PUMPBTCOMM", defaultValue = false),
PUMPCOMM("PUMPCOMM"),
PUMPQUEUE("PUMPQUEUE"),
PROFILE("PROFILE"),
SMS("SMS"),
TIDEPOOL("TIDEPOOL"),
UI("UI", defaultValue = false),
WEAR("WEAR", defaultValue = false)
}

View file

@ -0,0 +1,43 @@
package info.nightscout.androidaps.logging
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* Created by adrian on 2020-01-13.
*/
class StacktraceLoggerWrapper(private val delegate: Logger) : Logger by delegate {
override fun debug(msg: String?) {
delegate.debug(stackLogMarker() + msg)
}
override fun debug(format: String?, arg: Any?) {
delegate.debug(stackLogMarker() + format, arg)
}
override fun info(msg: String?) {
delegate.info(stackLogMarker() + msg)
}
override fun error(msg: String?) {
delegate.error(stackLogMarker() + msg)
}
override fun warn(msg: String?) {
delegate.warn(stackLogMarker() + msg)
}
// all other methods will be implemented by delegate
companion object {
@JvmStatic
@Deprecated("please inject AAPSLogger")
fun getLogger(name: String) = StacktraceLoggerWrapper(LoggerFactory.getLogger(name))
@JvmStatic
@Deprecated("please inject AAPSLogger")
fun getLogger(clazz: Class<*>) = StacktraceLoggerWrapper(LoggerFactory.getLogger(clazz))
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.aps.openAPSMA.events package info.nightscout.androidaps.plugins.aps.events
import info.nightscout.androidaps.events.EventUpdateGui import info.nightscout.androidaps.events.EventUpdateGui

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.aps.openAPSMA.events package info.nightscout.androidaps.plugins.aps.events
import info.nightscout.androidaps.events.EventUpdateGui import info.nightscout.androidaps.events.EventUpdateGui

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.aps.openAPSMA; package info.nightscout.androidaps.plugins.aps.logger;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L; import javax.inject.Inject;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
/** /**
* Created by adrian on 15/10/17. * Created by adrian on 15/10/17.
@ -13,7 +15,8 @@ import info.nightscout.androidaps.logging.L;
public class LoggerCallback extends ScriptableObject { public class LoggerCallback extends ScriptableObject {
private static Logger log = LoggerFactory.getLogger(L.APS); @Inject
AAPSLogger aapsLogger;
private static StringBuffer errorBuffer = new StringBuffer(); private static StringBuffer errorBuffer = new StringBuffer();
private static StringBuffer logBuffer = new StringBuffer(); private static StringBuffer logBuffer = new StringBuffer();
@ -23,6 +26,7 @@ public class LoggerCallback extends ScriptableObject {
//empty constructor needed for Rhino //empty constructor needed for Rhino
errorBuffer = new StringBuffer(); errorBuffer = new StringBuffer();
logBuffer = new StringBuffer(); logBuffer = new StringBuffer();
MainApp.instance().androidInjector().inject(this);
} }
@Override @Override
@ -35,14 +39,12 @@ public class LoggerCallback extends ScriptableObject {
} }
public void jsFunction_log(Object obj1) { public void jsFunction_log(Object obj1) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, obj1.toString().trim());
log.debug(obj1.toString().trim());
logBuffer.append(obj1.toString()); logBuffer.append(obj1.toString());
} }
public void jsFunction_error(Object obj1) { public void jsFunction_error(Object obj1) {
if (L.isEnabled(L.APS)) aapsLogger.error(LTag.APS, obj1.toString().trim());
log.error(obj1.toString().trim());
errorBuffer.append(obj1.toString()); errorBuffer.append(obj1.toString());
} }

View file

@ -6,33 +6,48 @@ import android.text.Spanned;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.MainApp; import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
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.data.Profile;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/** /**
* Created by mike on 09.06.2016. * Created by mike on 09.06.2016.
*/ */
public class APSResult { public class APSResult {
private static Logger log = LoggerFactory.getLogger(L.APS); @Inject HasAndroidInjector injector;
@Inject public AAPSLogger aapsLogger;
@Inject ConstraintChecker constraintChecker;
@Inject SP sp;
@Inject ActivePluginProvider activePlugin;
@Inject TreatmentsPlugin treatmentsPlugin;
@Inject ProfileFunction profileFunction;
@Inject ResourceHelper resourceHelper;
@Inject
public APSResult(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
}
public long date = 0; public long date = 0;
public String reason; public String reason;
@ -86,68 +101,65 @@ public class APSResult {
@Override @Override
public String toString() { public String toString() {
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final PumpInterface pump = activePlugin.getActivePump();
if (isChangeRequested()) { if (isChangeRequested()) {
String ret; String ret;
// rate // rate
if (rate == 0 && duration == 0) if (rate == 0 && duration == 0)
ret = MainApp.gs(R.string.canceltemp) + "\n"; ret = resourceHelper.gs(R.string.canceltemp) + "\n";
else if (rate == -1) else if (rate == -1)
ret = MainApp.gs(R.string.let_temp_basal_run) + "\n"; ret = resourceHelper.gs(R.string.let_temp_basal_run) + "\n";
else if (usePercent) else if (usePercent)
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " + ret = resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " +
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)\n" + "(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)\n" +
MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n"; resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
else else
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + ret = resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n"; resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
// smb // smb
if (smb != 0) if (smb != 0)
ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U\n"); ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump()) + " U\n");
// reason // reason
ret += MainApp.gs(R.string.reason) + ": " + reason; ret += resourceHelper.gs(R.string.reason) + ": " + reason;
return ret; return ret;
} else } else
return MainApp.gs(R.string.nochangerequested); return resourceHelper.gs(R.string.nochangerequested);
} }
public Spanned toSpanned() { public Spanned toSpanned() {
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final PumpInterface pump = activePlugin.getActivePump();
if (isChangeRequested()) { if (isChangeRequested()) {
String ret; String ret;
// rate // rate
if (rate == 0 && duration == 0) if (rate == 0 && duration == 0)
ret = MainApp.gs(R.string.canceltemp) + "<br>"; ret = resourceHelper.gs(R.string.canceltemp) + "<br>";
else if (rate == -1) else if (rate == -1)
ret = MainApp.gs(R.string.let_temp_basal_run) + "<br>"; ret = resourceHelper.gs(R.string.let_temp_basal_run) + "<br>";
else if (usePercent) else if (usePercent)
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(percent) + "% " + ret = "<b>" + resourceHelper.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(percent) + "% " +
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)<br>" + "(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)<br>" +
"<b>" + MainApp.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>"; "<b>" + resourceHelper.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
else else
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " + ret = "<b>" + resourceHelper.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100d) + "%) <br>" + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100d) + "%) <br>" +
"<b>" + MainApp.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>"; "<b>" + resourceHelper.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
// smb // smb
if (smb != 0) if (smb != 0)
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U<br>"); ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump()) + " U<br>");
// reason // reason
ret += "<b>" + MainApp.gs(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;"); ret += "<b>" + resourceHelper.gs(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;");
return Html.fromHtml(ret); return Html.fromHtml(ret);
} else } else
return Html.fromHtml(MainApp.gs(R.string.nochangerequested)); return Html.fromHtml(resourceHelper.gs(R.string.nochangerequested));
} }
public APSResult() { public APSResult newAndClone(HasAndroidInjector injector) {
} APSResult newResult = new APSResult(injector);
public APSResult clone() {
APSResult newResult = new APSResult();
doClone(newResult); doClone(newResult);
return newResult; return newResult;
} }
@ -163,7 +175,7 @@ public class APSResult {
try { try {
newResult.json = new JSONObject(json.toString()); newResult.json = new JSONObject(json.toString());
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
newResult.hasPredictions = hasPredictions; newResult.hasPredictions = hasPredictions;
newResult.smb = smb; newResult.smb = smb;
@ -184,7 +196,7 @@ public class APSResult {
json.put("reason", reason); json.put("reason", reason);
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
return json; return json;
} }
@ -247,7 +259,7 @@ public class APSResult {
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
return array; return array;
} }
@ -280,66 +292,60 @@ public class APSResult {
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
return latest; return latest;
} }
public boolean isChangeRequested() { public boolean isChangeRequested() {
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed(); Constraint<Boolean> closedLoopEnabled = constraintChecker.isClosedLoopAllowed();
// closed loop mode: handle change at driver level // closed loop mode: handle change at driver level
if (closedLoopEnabled.value()) { if (closedLoopEnabled.value()) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "DEFAULT: Closed mode");
log.debug("DEFAULT: Closed mode");
return tempBasalRequested || bolusRequested; return tempBasalRequested || bolusRequested;
} }
// open loop mode: try to limit request // open loop mode: try to limit request
if (!tempBasalRequested && !bolusRequested) { if (!tempBasalRequested && !bolusRequested) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "FALSE: No request");
log.debug("FALSE: No request");
return false; return false;
} }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now);
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); PumpInterface pump = activePlugin.getActivePump();
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = profileFunction.getProfile();
if (profile == null) { if (profile == null) {
log.error("FALSE: No Profile"); aapsLogger.error("FALSE: No Profile");
return false; return false;
} }
if (usePercent) { if (usePercent) {
if (activeTemp == null && percent == 100) { if (activeTemp == null && percent == 100) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp");
log.debug("FALSE: No temp running, asking cancel temp");
return false; return false;
} }
if (activeTemp != null && Math.abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.getPumpDescription().basalStep) { if (activeTemp != null && Math.abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.getPumpDescription().basalStep) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "FALSE: Temp equal");
log.debug("FALSE: Temp equal");
return false; return false;
} }
// always report zerotemp // always report zerotemp
if (percent == 0) { if (percent == 0) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Zero temp");
log.debug("TRUE: Zero temp");
return true; return true;
} }
// always report hightemp // always report hightemp
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) { if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose(); double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
if (percent == pumpLimit) { if (percent == pumpLimit) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Pump limit");
log.debug("TRUE: Pump limit");
return true; return true;
} }
} }
// report change bigger than 30% // report change bigger than 30%
double percentMinChangeChange = SP.getDouble(R.string.key_loop_openmode_min_change, 30d); double percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30d);
percentMinChangeChange /= 100d; percentMinChangeChange /= 100d;
double lowThreshold = 1 - percentMinChangeChange; double lowThreshold = 1 - percentMinChangeChange;
double highThreshold = 1 + percentMinChangeChange; double highThreshold = 1 + percentMinChangeChange;
@ -348,42 +354,36 @@ public class APSResult {
change = percent / (double) activeTemp.tempBasalConvertedToPercent(now, profile); change = percent / (double) activeTemp.tempBasalConvertedToPercent(now, profile);
if (change < lowThreshold || change > highThreshold) { if (change < lowThreshold || change > highThreshold) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + (change * 100d) + "%");
log.debug("TRUE: Outside allowed range " + (change * 100d) + "%");
return true; return true;
} else { } else {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + (change * 100d) + "%");
log.debug("TRUE: Inside allowed range " + (change * 100d) + "%");
return false; return false;
} }
} else { } else {
if (activeTemp == null && rate == pump.getBaseBasalRate()) { if (activeTemp == null && rate == pump.getBaseBasalRate()) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp");
log.debug("FALSE: No temp running, asking cancel temp");
return false; return false;
} }
if (activeTemp != null && Math.abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) { if (activeTemp != null && Math.abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "FALSE: Temp equal");
log.debug("FALSE: Temp equal");
return false; return false;
} }
// always report zerotemp // always report zerotemp
if (rate == 0) { if (rate == 0) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Zero temp");
log.debug("TRUE: Zero temp");
return true; return true;
} }
// always report hightemp // always report hightemp
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose(); double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
if (rate == pumpLimit) { if (rate == pumpLimit) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Pump limit");
log.debug("TRUE: Pump limit");
return true; return true;
} }
} }
// report change bigger than 30% // report change bigger than 30%
double percentMinChangeChange = SP.getDouble(R.string.key_loop_openmode_min_change, 30d); double percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30d);
percentMinChangeChange /= 100d; percentMinChangeChange /= 100d;
double lowThreshold = 1 - percentMinChangeChange; double lowThreshold = 1 - percentMinChangeChange;
double highThreshold = 1 + percentMinChangeChange; double highThreshold = 1 + percentMinChangeChange;
@ -392,12 +392,10 @@ public class APSResult {
change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile); change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile);
if (change < lowThreshold || change > highThreshold) { if (change < lowThreshold || change > highThreshold) {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + (change * 100d) + "%");
log.debug("TRUE: Outside allowed range " + (change * 100d) + "%");
return true; return true;
} else { } else {
if (L.isEnabled(L.APS)) aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + (change * 100d) + "%");
log.debug("TRUE: Inside allowed range " + (change * 100d) + "%");
return false; return false;
} }
} }

View file

@ -6,6 +6,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
/* /*
{ {
@ -365,7 +366,7 @@ import info.nightscout.androidaps.logging.L;
*/ */
public class DeviceStatus { public class DeviceStatus {
private static Logger log = LoggerFactory.getLogger(L.APS); private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
public String device = null; public String device = null;
public JSONObject pump = null; public JSONObject pump = null;

View file

@ -4,23 +4,31 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBusWrapper
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.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SP import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.plusAssign import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.loop_fragment.* import kotlinx.android.synthetic.main.loop_fragment.*
import javax.inject.Inject
class LoopFragment : Fragment() { class LoopFragment : DaggerFragment() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var loopPlugin: LoopPlugin
private var disposable: CompositeDisposable = CompositeDisposable() private var disposable: CompositeDisposable = CompositeDisposable()
@ -33,33 +41,31 @@ class LoopFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
loop_run.setOnClickListener { loop_run.setOnClickListener {
loop_lastrun.text = MainApp.gs(R.string.executing) loop_lastrun.text = resourceHelper.gs(R.string.executing)
Thread { LoopPlugin.getPlugin().invoke("Loop button", true) }.start() Thread { loopPlugin.invoke("Loop button", true) }.start()
} }
} }
@Synchronized @Synchronized
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
disposable += RxBus disposable += rxBus
.toObservable(EventLoopUpdateGui::class.java) .toObservable(EventLoopUpdateGui::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ .subscribe({
updateGUI() updateGUI()
}, { }, { fabricPrivacy.logException(it) })
FabricPrivacy.logException(it)
})
disposable += RxBus disposable += rxBus
.toObservable(EventLoopSetLastRunGui::class.java) .toObservable(EventLoopSetLastRunGui::class.java)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ .subscribe({
clearGUI() clearGUI()
loop_lastrun?.text = it.text loop_lastrun?.text = it.text
}, { FabricPrivacy.logException(it) }) }, { fabricPrivacy.logException(it) })
updateGUI() updateGUI()
SP.putBoolean(R.string.key_objectiveuseloop, true) sp.putBoolean(R.string.key_objectiveuseloop, true)
} }
@Synchronized @Synchronized
@ -71,11 +77,11 @@ class LoopFragment : Fragment() {
@Synchronized @Synchronized
fun updateGUI() { fun updateGUI() {
if (loop_request == null) return if (loop_request == null) return
LoopPlugin.lastRun?.let { loopPlugin.lastRun?.let {
loop_request?.text = it.request?.toSpanned() ?: "" loop_request?.text = it.request?.toSpanned() ?: ""
loop_constraintsprocessed?.text = it.constraintsProcessed?.toSpanned() ?: "" loop_constraintsprocessed?.text = it.constraintsProcessed?.toSpanned() ?: ""
loop_source?.text = it.source ?: "" loop_source?.text = it.source ?: ""
loop_lastrun?.text = it.lastAPSRun?.let { lastRun -> DateUtil.dateAndTimeString(lastRun.time) } loop_lastrun?.text = DateUtil.dateAndTimeString(it.lastAPSRun)
?: "" ?: ""
loop_smbrequest_time?.text = DateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest) loop_smbrequest_time?.text = DateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest)
loop_smbexecution_time?.text = DateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact) loop_smbexecution_time?.text = DateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact)
@ -92,7 +98,7 @@ class LoopFragment : Fragment() {
val allConstraints = Constraint(0.0) val allConstraints = Constraint(0.0)
constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) } constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) }
constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) } constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) }
allConstraints.mostLimitedReasons allConstraints.getMostLimitedReasons(aapsLogger)
} ?: "" } ?: ""
loop_constraints?.text = constraints loop_constraints?.text = constraints
} }

View file

@ -11,49 +11,55 @@ import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import org.jetbrains.annotations.Nullable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Lazy;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
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.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper;
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.events.EventAcceptOpenLoopChange; import info.nightscout.androidaps.events.EventAcceptOpenLoopChange;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.Constraint;
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.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
@ -61,32 +67,34 @@ import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.androidaps.queue.commands.Command;
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.SP;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
/** @Singleton
* Created by mike on 05.08.2016.
*/
public class LoopPlugin extends PluginBase { public class LoopPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.APS); private final HasAndroidInjector injector;
private final SP sp;
private final RxBusWrapper rxBus;
private final ConstraintChecker constraintChecker;
private final ResourceHelper resourceHelper;
private final ProfileFunction profileFunction;
private final Context context;
private final CommandQueueProvider commandQueue;
private final ActivePluginProvider activePlugin;
private final TreatmentsPlugin treatmentsPlugin;
private final VirtualPumpPlugin virtualPumpPlugin;
private final Lazy<ActionStringHandler> actionStringHandler;
private final IobCobCalculatorPlugin iobCobCalculatorPlugin;
private CompositeDisposable disposable = new CompositeDisposable(); private CompositeDisposable disposable = new CompositeDisposable();
private static final String CHANNEL_ID = "AndroidAPS-Openloop"; private static final String CHANNEL_ID = "AndroidAPS-Openloop";
private long lastBgTriggeredRun = 0; private long lastBgTriggeredRun = 0;
private static LoopPlugin loopPlugin;
@NonNull
public static LoopPlugin getPlugin() {
if (loopPlugin == null) {
loopPlugin = new LoopPlugin();
}
return loopPlugin;
}
private long loopSuspendedTill; // end of manual loop suspend private long loopSuspendedTill; // end of manual loop suspend
private boolean isSuperBolus; private boolean isSuperBolus;
private boolean isDisconnected; private boolean isDisconnected;
@ -97,7 +105,7 @@ public class LoopPlugin extends PluginBase {
public PumpEnactResult tbrSetByPump = null; public PumpEnactResult tbrSetByPump = null;
public PumpEnactResult smbSetByPump = null; public PumpEnactResult smbSetByPump = null;
public String source = null; public String source = null;
public Date lastAPSRun = null; public long lastAPSRun = DateUtil.now();
public long lastTBREnact = 0; public long lastTBREnact = 0;
public long lastSMBEnact = 0; public long lastSMBEnact = 0;
public long lastTBRRequest = 0; public long lastTBRRequest = 0;
@ -105,32 +113,61 @@ public class LoopPlugin extends PluginBase {
public long lastOpenModeAccept; public long lastOpenModeAccept;
} }
static public LastRun lastRun = null; @Nullable public LastRun lastRun = null;
public LoopPlugin() { @Inject
public LoopPlugin(
HasAndroidInjector injector,
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
SP sp,
ConstraintChecker constraintChecker,
ResourceHelper resourceHelper,
ProfileFunction profileFunction,
Context context,
CommandQueueProvider commandQueue,
ActivePluginProvider activePlugin,
TreatmentsPlugin treatmentsPlugin,
VirtualPumpPlugin virtualPumpPlugin,
Lazy<ActionStringHandler> actionStringHandler, // TODO Adrian use RxBus instead of Lazy
IobCobCalculatorPlugin iobCobCalculatorPlugin
) {
super(new PluginDescription() super(new PluginDescription()
.mainType(PluginType.LOOP) .mainType(PluginType.LOOP)
.fragmentClass(LoopFragment.class.getName()) .fragmentClass(LoopFragment.class.getName())
.pluginName(R.string.loop) .pluginName(R.string.loop)
.shortName(R.string.loop_shortname) .shortName(R.string.loop_shortname)
.preferencesId(R.xml.pref_loop) .preferencesId(R.xml.pref_loop)
.description(R.string.description_loop) .description(R.string.description_loop),
aapsLogger, resourceHelper, injector
); );
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L); this.injector = injector;
isSuperBolus = SP.getBoolean("isSuperBolus", false); this.sp = sp;
isDisconnected = SP.getBoolean("isDisconnected", false); this.rxBus = rxBus;
this.constraintChecker = constraintChecker;
this.resourceHelper = resourceHelper;
this.profileFunction = profileFunction;
this.context = context;
this.activePlugin = activePlugin;
this.commandQueue = commandQueue;
this.treatmentsPlugin = treatmentsPlugin;
this.virtualPumpPlugin = virtualPumpPlugin;
this.actionStringHandler = actionStringHandler;
this.iobCobCalculatorPlugin = iobCobCalculatorPlugin;
loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L);
isSuperBolus = sp.getBoolean("isSuperBolus", false);
isDisconnected = sp.getBoolean("isDisconnected", false);
} }
@Override @Override
protected void onStart() { protected void onStart() {
createNotificationChannel(); createNotificationChannel();
super.onStart(); super.onStart();
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventTempTargetChange.class) .toObservable(EventTempTargetChange.class)
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.subscribe(event -> { .subscribe(event -> invoke("EventTempTargetChange", true), exception -> FabricPrivacy.getInstance().logException(exception))
invoke("EventTempTargetChange", true);
}, FabricPrivacy::logException)
); );
/** /**
* This method is triggered once autosens calculation has completed, so the LoopPlugin * This method is triggered once autosens calculation has completed, so the LoopPlugin
@ -139,14 +176,14 @@ public class LoopPlugin extends PluginBase {
* the event causing the calculation is not EventNewBg. * the event causing the calculation is not EventNewBg.
* <p> * <p>
*/ */
disposable.add(RxBus.INSTANCE disposable.add(rxBus
.toObservable(EventAutosensCalculationFinished.class) .toObservable(EventAutosensCalculationFinished.class)
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.subscribe(event -> { .subscribe(event -> {
// Autosens calculation not triggered by a new BG // Autosens calculation not triggered by a new BG
if (!(event.getCause() instanceof EventNewBG)) return; if (!(event.getCause() instanceof EventNewBG)) return;
BgReading bgReading = DatabaseHelper.actualBg(); BgReading bgReading = iobCobCalculatorPlugin.actualBg();
// BG outdated // BG outdated
if (bgReading == null) return; if (bgReading == null) return;
// already looped with that value // already looped with that value
@ -154,7 +191,7 @@ public class LoopPlugin extends PluginBase {
lastBgTriggeredRun = bgReading.date; lastBgTriggeredRun = bgReading.date;
invoke("AutosenseCalculation for " + bgReading, true); invoke("AutosenseCalculation for " + bgReading, true);
}, FabricPrivacy::logException) }, exception -> FabricPrivacy.getInstance().logException(exception))
); );
} }
@ -162,7 +199,7 @@ public class LoopPlugin extends PluginBase {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = NotificationManager mNotificationManager =
(NotificationManager) MainApp.instance().getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_ID, CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH); NotificationManager.IMPORTANCE_HIGH);
@ -178,8 +215,13 @@ public class LoopPlugin extends PluginBase {
@Override @Override
public boolean specialEnableCondition() { public boolean specialEnableCondition() {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); try {
return pump == null || pump.getPumpDescription().isTempBasalCapable; PumpInterface pump = activePlugin.getActivePump();
return pump.getPumpDescription().isTempBasalCapable;
} catch (Exception ignored) {
// may fail during initialization
return true;
}
} }
public long suspendedTo() { public long suspendedTo() {
@ -190,27 +232,27 @@ public class LoopPlugin extends PluginBase {
loopSuspendedTill = endTime; loopSuspendedTill = endTime;
isSuperBolus = false; isSuperBolus = false;
isDisconnected = false; isDisconnected = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill); sp.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus); sp.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected); sp.putBoolean("isDisconnected", isDisconnected);
} }
public void superBolusTo(long endTime) { public void superBolusTo(long endTime) {
loopSuspendedTill = endTime; loopSuspendedTill = endTime;
isSuperBolus = true; isSuperBolus = true;
isDisconnected = false; isDisconnected = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill); sp.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus); sp.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected); sp.putBoolean("isDisconnected", isDisconnected);
} }
public void disconnectTo(long endTime) { private void disconnectTo(long endTime) {
loopSuspendedTill = endTime; loopSuspendedTill = endTime;
isSuperBolus = false; isSuperBolus = false;
isDisconnected = true; isDisconnected = true;
SP.putLong("loopSuspendedTill", loopSuspendedTill); sp.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus); sp.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected); sp.putBoolean("isDisconnected", isDisconnected);
} }
public int minutesToEndOfSuspend() { public int minutesToEndOfSuspend() {
@ -275,44 +317,41 @@ public class LoopPlugin extends PluginBase {
public synchronized void invoke(String initiator, boolean allowNotification, boolean tempBasalFallback) { public synchronized void invoke(String initiator, boolean allowNotification, boolean tempBasalFallback) {
try { try {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "invoke from " + initiator);
log.debug("invoke from " + initiator); Constraint<Boolean> loopEnabled = constraintChecker.isLoopInvocationAllowed();
Constraint<Boolean> loopEnabled = MainApp.getConstraintChecker().isLoopInvokationAllowed();
if (!loopEnabled.value()) { if (!loopEnabled.value()) {
String message = MainApp.gs(R.string.loopdisabled) + "\n" + loopEnabled.getReasons(); String message = resourceHelper.gs(R.string.loopdisabled) + "\n" + loopEnabled.getReasons(getAapsLogger());
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, message);
log.debug(message); rxBus.send(new EventLoopSetLastRunGui(message));
RxBus.INSTANCE.send(new EventLoopSetLastRunGui(message));
return; return;
} }
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final PumpInterface pump = activePlugin.getActivePump();
APSResult result = null; APSResult result = null;
if (!isEnabled(PluginType.LOOP)) if (!isEnabled(PluginType.LOOP))
return; return;
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = profileFunction.getProfile();
if (profile == null || !ProfileFunctions.getInstance().isProfileValid("Loop")) { if (profile == null || !profileFunction.isProfileValid("Loop")) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected));
log.debug(MainApp.gs(R.string.noprofileselected)); rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.noprofileselected)));
RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected)));
return; return;
} }
// Check if pump info is loaded // Check if pump info is loaded
if (pump.getBaseBasalRate() < 0.01d) return; if (pump.getBaseBasalRate() < 0.01d) return;
APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); APSInterface usedAPS = activePlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) { if (((PluginBase) usedAPS).isEnabled(PluginType.APS)) {
usedAPS.invoke(initiator, tempBasalFallback); usedAPS.invoke(initiator, tempBasalFallback);
result = usedAPS.getLastAPSResult(); result = usedAPS.getLastAPSResult();
} }
// Check if we have any result // Check if we have any result
if (result == null) { if (result == null) {
RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noapsselected))); rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.noapsselected)));
return; return;
} }
@ -323,28 +362,27 @@ public class LoopPlugin extends PluginBase {
result.percent = (int) (result.rate / profile.getBasal() * 100); result.percent = (int) (result.rate / profile.getBasal() * 100);
// check rate for constrais // check rate for constrais
final APSResult resultAfterConstraints = result.clone(); final APSResult resultAfterConstraints = result.newAndClone(injector);
resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate); resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value(); resultAfterConstraints.rate = constraintChecker.applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value();
resultAfterConstraints.percentConstraint = new Constraint<>(resultAfterConstraints.percent); resultAfterConstraints.percentConstraint = new Constraint<>(resultAfterConstraints.percent);
resultAfterConstraints.percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(resultAfterConstraints.percentConstraint, profile).value(); resultAfterConstraints.percent = constraintChecker.applyBasalPercentConstraints(resultAfterConstraints.percentConstraint, profile).value();
resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb); resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb);
resultAfterConstraints.smb = MainApp.getConstraintChecker().applyBolusConstraints(resultAfterConstraints.smbConstraint).value(); resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint).value();
// safety check for multiple SMBs // safety check for multiple SMBs
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(); long lastBolusTime = treatmentsPlugin.getLastBolusTime();
if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) { if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "SMB requsted but still in 3 min interval");
log.debug("SMB requsted but still in 3 min interval");
resultAfterConstraints.smb = 0; resultAfterConstraints.smb = 0;
} }
if (lastRun == null) lastRun = new LastRun(); if (lastRun == null) lastRun = new LastRun();
lastRun.request = result; lastRun.request = result;
lastRun.constraintsProcessed = resultAfterConstraints; lastRun.constraintsProcessed = resultAfterConstraints;
lastRun.lastAPSRun = new Date(); lastRun.lastAPSRun = DateUtil.now();
lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.tbrSetByPump = null; lastRun.tbrSetByPump = null;
lastRun.smbSetByPump = null; lastRun.smbSetByPump = null;
@ -353,63 +391,61 @@ public class LoopPlugin extends PluginBase {
lastRun.lastSMBEnact = 0; lastRun.lastSMBEnact = 0;
lastRun.lastSMBRequest = 0; lastRun.lastSMBRequest = 0;
NSUpload.uploadDeviceStatus(); NSUpload.uploadDeviceStatus(this, iobCobCalculatorPlugin, profileFunction, activePlugin.getActivePump());
if (isSuspended()) { if (isSuspended()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended));
log.debug(MainApp.gs(R.string.loopsuspended)); rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)));
RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.loopsuspended)));
return; return;
} }
if (pump.isSuspended()) { if (pump.isSuspended()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.pumpsuspended));
log.debug(MainApp.gs(R.string.pumpsuspended)); rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.pumpsuspended)));
RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.pumpsuspended)));
return; return;
} }
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed(); Constraint<Boolean> closedLoopEnabled = constraintChecker.isClosedLoopAllowed();
if (closedLoopEnabled.value()) { if (closedLoopEnabled.value()) {
if (resultAfterConstraints.isChangeRequested() if (resultAfterConstraints.isChangeRequested()
&& !ConfigBuilderPlugin.getPlugin().getCommandQueue().bolusInQueue() && !commandQueue.bolusInQueue()
&& !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BOLUS)) { && !commandQueue.isRunning(Command.CommandType.BOLUS)) {
final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult waiting = new PumpEnactResult(getInjector());
waiting.queued = true; waiting.queued = true;
if (resultAfterConstraints.tempBasalRequested) if (resultAfterConstraints.tempBasalRequested)
lastRun.tbrSetByPump = waiting; lastRun.tbrSetByPump = waiting;
if (resultAfterConstraints.bolusRequested) if (resultAfterConstraints.bolusRequested)
lastRun.smbSetByPump = waiting; lastRun.smbSetByPump = waiting;
RxBus.INSTANCE.send(new EventLoopUpdateGui()); rxBus.send(new EventLoopUpdateGui());
FabricPrivacy.getInstance().logCustom("APSRequest"); FabricPrivacy.getInstance().logCustom("APSRequest");
applyTBRRequest(resultAfterConstraints, profile, new Callback() { applyTBRRequest(resultAfterConstraints, profile, new Callback() {
@Override @Override
public void run() { public void run() {
if (result.enacted || result.success) { if (result.enacted || result.success) {
lastRun.tbrSetByPump = result; lastRun.tbrSetByPump = result;
lastRun.lastTBRRequest = lastRun.lastAPSRun.getTime(); lastRun.lastTBRRequest = lastRun.lastAPSRun;
lastRun.lastTBREnact = DateUtil.now(); lastRun.lastTBREnact = DateUtil.now();
RxBus.INSTANCE.send(new EventLoopUpdateGui()); rxBus.send(new EventLoopUpdateGui());
applySMBRequest(resultAfterConstraints, new Callback() { applySMBRequest(resultAfterConstraints, new Callback() {
@Override @Override
public void run() { public void run() {
//Callback is only called if a bolus was acutally requested //Callback is only called if a bolus was acutally requested
if (result.enacted || result.success) { if (result.enacted || result.success) {
lastRun.smbSetByPump = result; lastRun.smbSetByPump = result;
lastRun.lastSMBRequest = lastRun.lastAPSRun.getTime(); lastRun.lastSMBRequest = lastRun.lastAPSRun;
lastRun.lastSMBEnact = DateUtil.now(); lastRun.lastSMBEnact = DateUtil.now();
} else { } else {
new Thread(() -> { new Thread(() -> {
SystemClock.sleep(1000); SystemClock.sleep(1000);
LoopPlugin.getPlugin().invoke("tempBasalFallback", allowNotification, true); invoke("tempBasalFallback", allowNotification, true);
}).start(); }).start();
} }
RxBus.INSTANCE.send(new EventLoopUpdateGui()); rxBus.send(new EventLoopUpdateGui());
} }
}); });
} }
RxBus.INSTANCE.send(new EventLoopUpdateGui()); rxBus.send(new EventLoopUpdateGui());
} }
}); });
} else { } else {
@ -419,26 +455,26 @@ public class LoopPlugin extends PluginBase {
} else { } else {
if (resultAfterConstraints.isChangeRequested() && allowNotification) { if (resultAfterConstraints.isChangeRequested() && allowNotification) {
NotificationCompat.Builder builder = NotificationCompat.Builder builder =
new NotificationCompat.Builder(MainApp.instance().getApplicationContext(), CHANNEL_ID); new NotificationCompat.Builder(context, CHANNEL_ID);
builder.setSmallIcon(R.drawable.notif_icon) builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(MainApp.gs(R.string.openloop_newsuggestion)) .setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
.setContentText(resultAfterConstraints.toString()) .setContentText(resultAfterConstraints.toString())
.setAutoCancel(true) .setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH) .setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_ALARM) .setCategory(Notification.CATEGORY_ALARM)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
if (SP.getBoolean("wearcontrol", false)) { if (sp.getBoolean("wearcontrol", false)) {
builder.setLocalOnly(true); builder.setLocalOnly(true);
} }
// Creates an explicit intent for an Activity in your app // Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(MainApp.instance().getApplicationContext(), MainActivity.class); Intent resultIntent = new Intent(context, MainActivity.class);
// The stack builder object will contain an artificial back stack for the // The stack builder object will contain an artificial back stack for the
// started Activity. // started Activity.
// This ensures that navigating backward from the Activity leads out of // This ensures that navigating backward from the Activity leads out of
// your application to the Home screen. // your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(MainApp.instance().getApplicationContext()); TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class); stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack // Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent); stackBuilder.addNextIntent(resultIntent);
@ -447,44 +483,43 @@ public class LoopPlugin extends PluginBase {
builder.setContentIntent(resultPendingIntent); builder.setContentIntent(resultPendingIntent);
builder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000}); builder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
NotificationManager mNotificationManager = NotificationManager mNotificationManager =
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on. // mId allows you to update the notification later on.
mNotificationManager.notify(Constants.notificationID, builder.build()); mNotificationManager.notify(Constants.notificationID, builder.build());
RxBus.INSTANCE.send(new EventNewOpenLoopNotification()); rxBus.send(new EventNewOpenLoopNotification());
// Send to Wear // Send to Wear
ActionStringHandler.handleInitiate("changeRequest"); actionStringHandler.get().handleInitiate("changeRequest");
} else if (allowNotification) { } else if (allowNotification) {
// dismiss notifications // dismiss notifications
NotificationManager notificationManager = NotificationManager notificationManager =
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(Constants.notificationID); notificationManager.cancel(Constants.notificationID);
ActionStringHandler.handleInitiate("cancelChangeRequest"); actionStringHandler.get().handleInitiate("cancelChangeRequest");
} }
} }
RxBus.INSTANCE.send(new EventLoopUpdateGui()); rxBus.send(new EventLoopUpdateGui());
} finally { } finally {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "invoke end");
log.debug("invoke end");
} }
} }
public void acceptChangeRequest() { public void acceptChangeRequest() {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = profileFunction.getProfile();
final LoopPlugin lp = this;
applyTBRRequest(lastRun.constraintsProcessed, profile, new Callback() { applyTBRRequest(lastRun.constraintsProcessed, profile, new Callback() {
@Override @Override
public void run() { public void run() {
if (result.enacted) { if (result.enacted) {
lastRun.tbrSetByPump = result; lastRun.tbrSetByPump = result;
lastRun.lastTBRRequest = lastRun.lastAPSRun.getTime(); lastRun.lastTBRRequest = lastRun.lastAPSRun;
lastRun.lastTBREnact = DateUtil.now(); lastRun.lastTBREnact = DateUtil.now();
lastRun.lastOpenModeAccept = DateUtil.now(); lastRun.lastOpenModeAccept = DateUtil.now();
NSUpload.uploadDeviceStatus(); NSUpload.uploadDeviceStatus(lp, iobCobCalculatorPlugin, profileFunction, activePlugin.getActivePump());
SP.incInt(R.string.key_ObjectivesmanualEnacts); sp.incInt(R.string.key_ObjectivesmanualEnacts);
} }
RxBus.INSTANCE.send(new EventAcceptOpenLoopChange()); rxBus.send(new EventAcceptOpenLoopChange());
} }
}); });
FabricPrivacy.getInstance().logCustom("AcceptTemp"); FabricPrivacy.getInstance().logCustom("AcceptTemp");
@ -495,206 +530,187 @@ public class LoopPlugin extends PluginBase {
* TODO: update pump drivers to support APS request in % * TODO: update pump drivers to support APS request in %
*/ */
public void applyTBRRequest(APSResult request, Profile profile, Callback callback) { private void applyTBRRequest(APSResult request, Profile profile, Callback callback) {
boolean allowPercentage = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); boolean allowPercentage = virtualPumpPlugin.isEnabled(PluginType.PUMP);
if (!request.tempBasalRequested) { if (!request.tempBasalRequested) {
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().enacted(false).success(true).comment(MainApp.gs(R.string.nochangerequested))).run(); callback.result(new PumpEnactResult(getInjector()).enacted(false).success(true).comment(resourceHelper.gs(R.string.nochangerequested))).run();
} }
return; return;
} }
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); PumpInterface pump = activePlugin.getActivePump();
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
if (!pump.isInitialized()) { if (!pump.isInitialized()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpNotInitialized));
log.debug("applyAPSRequest: " + MainApp.gs(R.string.pumpNotInitialized));
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run(); callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
} }
return; return;
} }
if (pump.isSuspended()) { if (pump.isSuspended()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpsuspended));
log.debug("applyAPSRequest: " + MainApp.gs(R.string.pumpsuspended));
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.gs(R.string.pumpsuspended)).enacted(false).success(false)).run(); callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false)).run();
} }
return; return;
} }
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + request.toString());
log.debug("applyAPSRequest: " + request.toString());
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
TemporaryBasal activeTemp = activeTreatments.getTempBasalFromHistory(now); TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now);
if (request.usePercent && allowPercentage) { if (request.usePercent && allowPercentage) {
if (request.percent == 100 && request.duration == 0) { if (request.percent == 100 && request.duration == 0) {
if (activeTemp != null) { if (activeTemp != null) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()");
log.debug("applyAPSRequest: cancelTempBasal()"); commandQueue.cancelTempBasal(false, callback);
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(false, callback);
} else { } else {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly");
log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().percent(request.percent).duration(0) callback.result(new PumpEnactResult(getInjector()).percent(request.percent).duration(0)
.enacted(false).success(true).comment(MainApp.gs(R.string.basal_set_correctly))).run(); .enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run();
} }
} }
} else if (activeTemp != null } else if (activeTemp != null
&& activeTemp.getPlannedRemainingMinutes() > 5 && activeTemp.getPlannedRemainingMinutes() > 5
&& request.duration - activeTemp.getPlannedRemainingMinutes() < 30 && request.duration - activeTemp.getPlannedRemainingMinutes() < 30
&& request.percent == activeTemp.percentRate) { && request.percent == activeTemp.percentRate) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly");
log.debug("applyAPSRequest: Temp basal set correctly");
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().percent(request.percent) callback.result(new PumpEnactResult(getInjector()).percent(request.percent)
.enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes()) .enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes())
.comment(MainApp.gs(R.string.let_temp_basal_run))).run(); .comment(resourceHelper.gs(R.string.let_temp_basal_run))).run();
} }
} else { } else {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: tempBasalPercent()");
log.debug("applyAPSRequest: tempBasalPercent()"); commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, callback);
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(request.percent, request.duration, false, profile, callback);
} }
} else { } else {
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) { if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
if (activeTemp != null) { if (activeTemp != null) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()");
log.debug("applyAPSRequest: cancelTempBasal()"); commandQueue.cancelTempBasal(false, callback);
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(false, callback);
} else { } else {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly");
log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().absolute(request.rate).duration(0) callback.result(new PumpEnactResult(getInjector()).absolute(request.rate).duration(0)
.enacted(false).success(true).comment(MainApp.gs(R.string.basal_set_correctly))).run(); .enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run();
} }
} }
} else if (activeTemp != null } else if (activeTemp != null
&& activeTemp.getPlannedRemainingMinutes() > 5 && activeTemp.getPlannedRemainingMinutes() > 5
&& request.duration - activeTemp.getPlannedRemainingMinutes() < 30 && request.duration - activeTemp.getPlannedRemainingMinutes() < 30
&& Math.abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) { && Math.abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly");
log.debug("applyAPSRequest: Temp basal set correctly");
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile)) callback.result(new PumpEnactResult(getInjector()).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile))
.enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes()) .enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes())
.comment(MainApp.gs(R.string.let_temp_basal_run))).run(); .comment(resourceHelper.gs(R.string.let_temp_basal_run))).run();
} }
} else { } else {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()");
log.debug("applyAPSRequest: setTempBasalAbsolute()"); commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, callback);
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, profile, callback);
} }
} }
} }
public void applySMBRequest(APSResult request, Callback callback) { private void applySMBRequest(APSResult request, Callback callback) {
if (!request.bolusRequested) { if (!request.bolusRequested) {
return; return;
} }
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); PumpInterface pump = activePlugin.getActivePump();
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
long lastBolusTime = activeTreatments.getLastBolusTime(); long lastBolusTime = treatmentsPlugin.getLastBolusTime();
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) { if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "SMB requested but still in 3 min interval");
log.debug("SMB requested but still in 3 min interval");
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult() callback.result(new PumpEnactResult(getInjector())
.comment(MainApp.gs(R.string.smb_frequency_exceeded)) .comment(resourceHelper.gs(R.string.smb_frequency_exceeded))
.enacted(false).success(false)).run(); .enacted(false).success(false)).run();
} }
return; return;
} }
if (!pump.isInitialized()) { if (!pump.isInitialized()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpNotInitialized));
log.debug("applySMBRequest: " + MainApp.gs(R.string.pumpNotInitialized));
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run(); callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
} }
return; return;
} }
if (pump.isSuspended()) { if (pump.isSuspended()) {
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpsuspended));
log.debug("applySMBRequest: " + MainApp.gs(R.string.pumpsuspended));
if (callback != null) { if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.gs(R.string.pumpsuspended)).enacted(false).success(false)).run(); callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false)).run();
} }
return; return;
} }
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applySMBRequest: " + request.toString());
log.debug("applySMBRequest: " + request.toString());
// deliver SMB // deliver SMB
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.lastKnownBolusTime = activeTreatments.getLastBolusTime(); detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.getLastBolusTime();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = request.smb; detailedBolusInfo.insulin = request.smb;
detailedBolusInfo.isSMB = true; detailedBolusInfo.isSMB = true;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
detailedBolusInfo.deliverAt = request.deliverAt; detailedBolusInfo.deliverAt = request.deliverAt;
if (L.isEnabled(L.APS)) getAapsLogger().debug(LTag.APS, "applyAPSRequest: bolus()");
log.debug("applyAPSRequest: bolus()"); commandQueue.bolus(detailedBolusInfo, callback);
ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, callback);
} }
public void disconnectPump(int durationInMinutes, Profile profile) { public void disconnectPump(int durationInMinutes, Profile profile) {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); PumpInterface pump = activePlugin.getActivePump();
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() { commandQueue.tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); Intent i = new Intent(context, ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment); i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i); context.startActivity(i);
} }
} }
}); });
} else { } else {
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { commandQueue.tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); Intent i = new Intent(context, ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment); i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i); context.startActivity(i);
} }
} }
}); });
} }
if (pump.getPumpDescription().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) { if (pump.getPumpDescription().isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() { commandQueue.cancelExtended(new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); Intent i = new Intent(context, ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment); i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.extendedbolusdeliveryerror)); i.putExtra("title", resourceHelper.gs(R.string.extendedbolusdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i); context.startActivity(i);
} }
} }
}); });
@ -703,17 +719,17 @@ public class LoopPlugin extends PluginBase {
} }
public void suspendLoop(int durationInMinutes) { public void suspendLoop(int durationInMinutes) {
LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000); suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000);
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { commandQueue.cancelTempBasal(true, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); Intent i = new Intent(context, ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment); i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i); context.startActivity(i);
} }
} }
}); });
@ -726,7 +742,7 @@ public class LoopPlugin extends PluginBase {
data.put("eventType", CareportalEvent.OPENAPSOFFLINE); data.put("eventType", CareportalEvent.OPENAPSOFFLINE);
data.put("duration", durationInMinutes); data.put("duration", durationInMinutes);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); getAapsLogger().error("Unhandled exception", e);
} }
CareportalEvent event = new CareportalEvent(); CareportalEvent event = new CareportalEvent();
event.date = DateUtil.now(); event.date = DateUtil.now();

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