Merge Upstream
This commit is contained in:
commit
0ea13b5671
334 changed files with 13264 additions and 9371 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -6,10 +6,17 @@
|
|||
/captures
|
||||
*.apk
|
||||
build/
|
||||
.idea/
|
||||
.idea/*
|
||||
!.idea/codeStyles/
|
||||
app/src/main/jniLibs
|
||||
full/
|
||||
debug/
|
||||
release/
|
||||
app/com.crashlytics.settings.json
|
||||
app/session_analytics.tap
|
||||
.project
|
||||
.settings/org.eclipse.buildship.core.prefs
|
||||
app/.classpath
|
||||
app/.settings/org.eclipse.buildship.core.prefs
|
||||
wear/.classpath
|
||||
wear/.settings/org.eclipse.buildship.core.prefs
|
||||
|
|
137
.idea/codeStyles/Project.xml
Normal file
137
.idea/codeStyles/Project.xml
Normal file
|
@ -0,0 +1,137 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="AUTODETECT_INDENTS" value="false" />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />
|
||||
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="LINE_COMMENT_ADD_SPACE" value="true" />
|
||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
|
@ -226,6 +226,8 @@ dependencies {
|
|||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
||||
implementation 'com.google.firebase:firebase-core:17.2.1'
|
||||
implementation 'com.google.firebase:firebase-auth:19.2.0'
|
||||
implementation 'com.google.firebase:firebase-database:19.2.0'
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
|
||||
transitive = true;
|
||||
}
|
||||
|
@ -264,7 +266,10 @@ dependencies {
|
|||
exclude group: "org.json", module: "json"
|
||||
}
|
||||
implementation "com.google.code.gson:gson:2.8.6"
|
||||
implementation "com.google.guava:guava:24.1-jre"
|
||||
implementation ("com.google.guava:guava:24.1-jre") {
|
||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||
}
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
implementation "net.danlew:android.joda:2.10.3"
|
||||
|
||||
|
@ -282,6 +287,7 @@ dependencies {
|
|||
testImplementation "joda-time:joda-time:2.10.5"
|
||||
testImplementation("com.google.truth:truth:0.39") {
|
||||
exclude group: "com.google.guava", module: "guava"
|
||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||
}
|
||||
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
||||
testImplementation "org.hamcrest:hamcrest-all:1.3"
|
||||
|
@ -291,9 +297,6 @@ dependencies {
|
|||
}
|
||||
*/
|
||||
|
||||
androidTestImplementation "org.mockito:mockito-core:2.8.47"
|
||||
androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
|
||||
|
@ -305,6 +308,13 @@ dependencies {
|
|||
implementation "com.squareup.retrofit2:adapter-rxjava2:2.6.2"
|
||||
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
|
||||
|
||||
// Phone checker
|
||||
implementation 'com.scottyab:rootbeer-lib:0.0.7'
|
||||
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0-alpha03'
|
||||
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,12 @@
|
|||
"package_name": "info.nightscout.aapspumpcontrol"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM"
|
||||
|
@ -37,7 +42,12 @@
|
|||
"package_name": "info.nightscout.androidaps"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM"
|
||||
|
@ -61,7 +71,12 @@
|
|||
"package_name": "info.nightscout.nsclient"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM"
|
||||
|
@ -85,7 +100,12 @@
|
|||
"package_name": "info.nightscout.nsclient2"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM"
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package info.nightscout.androidaps
|
||||
|
||||
import androidx.test.espresso.ViewAction
|
||||
import androidx.test.espresso.ViewInteraction
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
|
||||
fun ViewInteraction.isDisplayed(): Boolean {
|
||||
try {
|
||||
check(matches(ViewMatchers.isDisplayed()))
|
||||
return true
|
||||
} catch (e: Throwable) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun ViewInteraction.waitAndPerform(viewActions: ViewAction): ViewInteraction? {
|
||||
val startTime = System.currentTimeMillis()
|
||||
while (!isDisplayed()) {
|
||||
Thread.sleep(100)
|
||||
if (System.currentTimeMillis() - startTime >= 5000) {
|
||||
throw AssertionError("View not visible after 5000 milliseconds")
|
||||
}
|
||||
}
|
||||
return perform(viewActions)
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
package info.nightscout.androidaps
|
||||
|
||||
|
||||
import android.os.SystemClock
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.test.espresso.Espresso.onData
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.scrollTo
|
||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.source.RandomBgPlugin
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.isRunningTest
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
import org.hamcrest.TypeSafeMatcher
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SetupWizardActivityTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var mActivityTestRule = ActivityTestRule(SetupWizardActivity::class.java)
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var mGrantPermissionRule =
|
||||
GrantPermissionRule.grant(
|
||||
android.Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
android.Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
|
||||
@Before
|
||||
fun clear() {
|
||||
SP.clear()
|
||||
}
|
||||
/*
|
||||
|
||||
To run from command line
|
||||
gradlew connectedFullDebugAndroidTest
|
||||
|
||||
do not run when your production phone is connected !!!
|
||||
|
||||
do this before for running in emulator
|
||||
adb shell settings put global window_animation_scale 0 &
|
||||
adb shell settings put global transition_animation_scale 0 &
|
||||
adb shell settings put global animator_duration_scale 0 &
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
fun setupWizardActivityTest() {
|
||||
Assert.assertTrue(isRunningTest())
|
||||
// Welcome page
|
||||
onView(withId(R.id.next_button)).perform(click())
|
||||
// Language selection
|
||||
onView(withText("English")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Agreement page
|
||||
onView(withText("I UNDERSTAND AND AGREE")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Loction permission
|
||||
var askButton = onView(withText("Ask for permission"))
|
||||
if (askButton.isDisplayed()) {
|
||||
askButton.perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
}
|
||||
// Store permission
|
||||
askButton = onView(withText("Ask for permission"))
|
||||
if (askButton.isDisplayed()) {
|
||||
askButton.perform(scrollTo(), click())
|
||||
onView(withText("OK")).perform(click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
}
|
||||
// Units selection
|
||||
onView(withText("mmol/L")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).perform(click())
|
||||
// Display target selection
|
||||
onView(withText("4.2")).perform(scrollTo(), ViewActions.replaceText("5"))
|
||||
onView(withText("10.0")).perform(scrollTo(), ViewActions.replaceText("11"))
|
||||
onView(withId(R.id.next_button)).perform(click())
|
||||
// NSClient
|
||||
onView(withId(R.id.next_button)).perform(click())
|
||||
// Age selection
|
||||
onView(withText("Adult")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Insulin selection
|
||||
onView(withText("Ultra-Rapid Oref")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// BG source selection
|
||||
onView(withText("Random BG")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Profile selection
|
||||
onView(withText("Local Profile")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Local profile - DIA
|
||||
onView(withTagValue(Matchers.`is`("LP_DIA"))).perform(scrollTo(), ViewActions.replaceText("6.0"))
|
||||
// Local profile - IC
|
||||
onView(withId(R.id.ic_tab)).perform(scrollTo(), click())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("IC-1-0")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("2"), ViewActions.closeSoftKeyboard())
|
||||
// Local profile - ISF
|
||||
onView(withId(R.id.isf_tab)).perform(scrollTo(), click())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("ISF-1-0")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("3"), ViewActions.closeSoftKeyboard())
|
||||
// Local profile - BAS
|
||||
onView(withId(R.id.basal_tab)).perform(scrollTo(), click())
|
||||
onView(childAtPosition(Matchers.allOf(withId(R.id.localprofile_basal), childAtPosition(withClassName(Matchers.`is`("android.widget.LinearLayout")), 6)), 2))
|
||||
.perform(scrollTo(), click())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("BASAL-1-0")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("1.1"), ViewActions.closeSoftKeyboard())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("BASAL-1-1")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("1.2"), ViewActions.closeSoftKeyboard())
|
||||
onView(Matchers.allOf(withId(R.id.timelistedit_time), childAtPosition(childAtPosition(withId(R.id.localprofile_basal), 2), 0)))
|
||||
.perform(scrollTo(), click())
|
||||
onData(Matchers.anything()).inAdapterView(childAtPosition(withClassName(Matchers.`is`("android.widget.PopupWindow\$PopupBackgroundView")), 0)).atPosition(13)
|
||||
.perform(click())
|
||||
// Local profile - TARGET
|
||||
onView(withId(R.id.target_tab)).perform(scrollTo(), click())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("TARGET-1-0")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("6"), ViewActions.closeSoftKeyboard())
|
||||
onView(Matchers.allOf(withTagValue(Matchers.`is`("TARGET-2-0")), isDisplayed()))
|
||||
.perform(ViewActions.replaceText("6.5"), ViewActions.closeSoftKeyboard())
|
||||
onView(withText("Save")).perform(scrollTo(), click())
|
||||
onView(Matchers.allOf(withId(R.id.localprofile_profileswitch), isDisplayed()))
|
||||
.perform(scrollTo(), click())
|
||||
onView(allOf(withId(R.id.ok), isDisplayed())).perform(click())
|
||||
onView(Matchers.allOf(withText("OK"), isDisplayed())).perform(click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Profile switch
|
||||
askButton = onView(withText("Do Profile Switch"))
|
||||
if (askButton.isDisplayed()) {
|
||||
askButton.perform(scrollTo(), click())
|
||||
onView(allOf(withId(R.id.ok), isDisplayed())).perform(click())
|
||||
onView(Matchers.allOf(withText("OK"), isDisplayed())).perform(click())
|
||||
while (ProfileFunctions.getInstance().profile == null) SystemClock.sleep(100)
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
}
|
||||
// Pump
|
||||
onView(withText("Virtual Pump")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// APS
|
||||
onView(withText("OpenAPS SMB")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Open Closed Loop
|
||||
onView(withText("Closed Loop")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Loop
|
||||
askButton = onView(withText("Enable loop"))
|
||||
if (askButton.isDisplayed()) {
|
||||
askButton.perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
}
|
||||
// Sensitivity
|
||||
onView(withText("Sensitivity Oref1")).perform(scrollTo(), click())
|
||||
onView(withId(R.id.next_button)).waitAndPerform(click())
|
||||
// Objectives
|
||||
onView(allOf(withText("Start"), isDisplayed())).perform(scrollTo(), click())
|
||||
onView(withId(R.id.finish_button)).waitAndPerform(click())
|
||||
|
||||
// Verify settings
|
||||
Assert.assertEquals(Constants.MMOL, ProfileFunctions.getSystemUnits())
|
||||
Assert.assertEquals(17.0, HardLimits.maxBolus(), 0.0001) // Adult
|
||||
Assert.assertTrue(RandomBgPlugin.isEnabled(PluginType.BGSOURCE))
|
||||
Assert.assertTrue(LocalProfilePlugin.isEnabled(PluginType.PROFILE))
|
||||
val p = ProfileFunctions.getInstance().profile
|
||||
Assert.assertNotNull(p)
|
||||
Assert.assertEquals(2.0, p!!.ic, 0.0001)
|
||||
Assert.assertEquals(3.0 * Constants.MMOLL_TO_MGDL, p.isfMgdl, 0.0001)
|
||||
Assert.assertEquals(1.1, p.getBasalTimeFromMidnight(0), 0.0001)
|
||||
Assert.assertEquals(6.0 * Constants.MMOLL_TO_MGDL, p.targetLowMgdl, 0.0001)
|
||||
Assert.assertTrue(VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP))
|
||||
Assert.assertTrue(OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS))
|
||||
Assert.assertTrue(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
|
||||
Assert.assertTrue(SensitivityOref1Plugin.getPlugin().isEnabled(PluginType.SENSITIVITY))
|
||||
Assert.assertTrue(ObjectivesPlugin.objectives[0].isStarted)
|
||||
}
|
||||
|
||||
private fun childAtPosition(
|
||||
parentMatcher: Matcher<View>, position: Int): Matcher<View> {
|
||||
|
||||
return object : TypeSafeMatcher<View>() {
|
||||
override fun describeTo(description: Description) {
|
||||
description.appendText("Child at position $position in parent ")
|
||||
parentMatcher.describeTo(description)
|
||||
}
|
||||
|
||||
public override fun matchesSafely(view: View): Boolean {
|
||||
val parent = view.parent
|
||||
return parent is ViewGroup && parentMatcher.matches(parent)
|
||||
&& view == parent.getChildAt(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,12 +51,11 @@
|
|||
</activity>
|
||||
<activity android:name=".activities.PreferencesActivity" />
|
||||
<activity
|
||||
android:name=".plugins.general.overview.dialogs.BolusProgressHelperActivity"
|
||||
android:name=".activities.BolusProgressHelperActivity"
|
||||
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity
|
||||
android:name=".plugins.general.overview.dialogs.ErrorHelperActivity"
|
||||
android:name=".activities.ErrorHelperActivity"
|
||||
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity android:name=".activities.AgreementActivity" />
|
||||
<activity android:name=".plugins.pump.danaR.activities.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.pump.danaR.activities.DanaRUserOptionsActivity" />
|
||||
<activity android:name=".activities.TDDStatsActivity" />
|
||||
|
@ -76,6 +75,8 @@
|
|||
</activity>
|
||||
<activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" />
|
||||
<activity android:name=".activities.HistoryBrowseActivity" />
|
||||
<activity android:name=".activities.SurveyActivity" />
|
||||
<activity android:name=".activities.StatsActivity" />
|
||||
|
||||
<!-- Receive new BG readings from other local apps -->
|
||||
<receiver
|
||||
|
@ -114,7 +115,7 @@
|
|||
|
||||
<!-- Auto start -->
|
||||
<receiver
|
||||
android:name=".plugins.general.nsclient.receivers.AutoStartReceiver"
|
||||
android:name=".receivers.AutoStartReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
|
@ -122,16 +123,6 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- NSClient -->
|
||||
<receiver
|
||||
android:name=".plugins.general.nsclient.receivers.DBAccessReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.client.DBACCESS" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Network change local receiver -->
|
||||
<receiver android:name=".receivers.NetworkChangeReceiver">
|
||||
<intent-filter>
|
||||
|
|
|
@ -25,8 +25,6 @@ public class Constants {
|
|||
public static final int hoursToKeepInDatabase = 72;
|
||||
public static final int daysToKeepHistoryInDatabase = 30;
|
||||
|
||||
public static final long keepAliveMsecs = 5 * 60 * 1000L;
|
||||
|
||||
// SMS COMMUNICATOR
|
||||
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||
|
||||
|
@ -78,4 +76,15 @@ public class Constants {
|
|||
//Storage [MB]
|
||||
public static final long MINIMUM_FREE_SPACE = 200;
|
||||
|
||||
// Overview
|
||||
public static final double LOWMARK = 76.0;
|
||||
public static final double HIGHMARK = 180.0;
|
||||
|
||||
// STATISTICS
|
||||
public static final double STATS_TARGET_LOW_MMOL = 3.9;
|
||||
public static final double STATS_TARGET_HIGH_MMOL = 7.8;
|
||||
public static final double STATS_RANGE_LOW_MMOL = 3.9;
|
||||
public static final double STATS_RANGE_HIGH_MMOL = 10.0;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ 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;
|
||||
|
@ -56,6 +57,7 @@ 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;
|
||||
|
@ -90,8 +92,6 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
// initialize screen wake lock
|
||||
processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
|
||||
|
||||
doMigrations();
|
||||
|
||||
final ViewPager viewPager = findViewById(R.id.pager);
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
|
@ -137,7 +137,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
.subscribe(this::processPreferenceChange, FabricPrivacy::logException)
|
||||
);
|
||||
|
||||
if (!SP.getBoolean(R.string.key_setupwizard_processed, false) || !SP.contains(R.string.key_units)) {
|
||||
if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
|
||||
Intent intent = new Intent(this, SetupWizardActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
@ -231,17 +231,6 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private void doMigrations() {
|
||||
|
||||
// guarantee that the unreachable threshold is at least 30 and of type String
|
||||
// Added in 1.57 at 21.01.2018
|
||||
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||
if (unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
@ -250,10 +239,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
switch (requestCode) {
|
||||
case AndroidPermission.CASE_STORAGE:
|
||||
//show dialog after permission is granted
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setMessage(R.string.alert_dialog_storage_permission_text);
|
||||
alert.setPositiveButton(R.string.ok, null);
|
||||
alert.show();
|
||||
OKDialog.show(this, "", MainApp.gs(R.string.alert_dialog_storage_permission_text));
|
||||
break;
|
||||
case AndroidPermission.CASE_LOCATION:
|
||||
case AndroidPermission.CASE_SMS:
|
||||
|
@ -327,9 +313,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
return true;
|
||||
case R.id.nav_exit:
|
||||
log.debug("Exiting");
|
||||
MainApp.instance().stopKeepAliveService();
|
||||
RxBus.INSTANCE.send(new EventAppExit());
|
||||
MainApp.closeDbHelper();
|
||||
finish();
|
||||
System.runFinalization();
|
||||
System.exit(0);
|
||||
|
@ -343,6 +327,14 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.PluralsRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
@ -15,6 +17,7 @@ import com.j256.ormlite.android.apptools.OpenHelperManager;
|
|||
|
||||
import net.danlew.android.joda.JodaTimeAndroid;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -22,6 +25,7 @@ import java.io.File;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
|
@ -32,6 +36,7 @@ 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.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
|
@ -46,8 +51,6 @@ 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.receivers.AckAlarmReceiver;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.receivers.DBAccessReceiver;
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||
|
@ -72,6 +75,7 @@ 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;
|
||||
|
@ -86,8 +90,10 @@ import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
|||
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
|
||||
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
|
||||
import info.nightscout.androidaps.services.Intents;
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion;
|
||||
|
@ -95,7 +101,6 @@ import static info.nightscout.androidaps.plugins.constraints.versionChecker.Vers
|
|||
|
||||
public class MainApp extends Application {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
private static KeepAliveReceiver keepAliveReceiver;
|
||||
|
||||
private static MainApp sInstance;
|
||||
public static Resources sResources;
|
||||
|
@ -108,11 +113,7 @@ public class MainApp extends Application {
|
|||
private static ArrayList<PluginBase> pluginsList = null;
|
||||
|
||||
private static DataReceiver dataReceiver = new DataReceiver();
|
||||
private static NSAlarmReceiver alarmReciever = new NSAlarmReceiver();
|
||||
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
|
||||
private static DBAccessReceiver dbAccessReciever = new DBAccessReceiver();
|
||||
private LocalBroadcastManager lbm;
|
||||
BroadcastReceiver btReceiver;
|
||||
private static NSAlarmReceiver alarmReceiver = new NSAlarmReceiver();
|
||||
TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
|
||||
|
||||
public static boolean devBranch;
|
||||
|
@ -145,6 +146,8 @@ public class MainApp extends Application {
|
|||
log.error("Error with Fabric init! " + e);
|
||||
}
|
||||
|
||||
registerActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
|
||||
|
||||
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
|
||||
mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase"));
|
||||
|
||||
|
@ -164,7 +167,6 @@ public class MainApp extends Application {
|
|||
|
||||
//trigger here to see the new version on app start after an update
|
||||
triggerCheckVersion();
|
||||
//setBTReceiver();
|
||||
|
||||
if (pluginsList == null) {
|
||||
pluginsList = new ArrayList<>();
|
||||
|
@ -188,7 +190,7 @@ public class MainApp extends Application {
|
|||
if (Config.PUMPDRIVERS) pluginsList.add(MedtronicPumpPlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(MDIPlugin.getPlugin());
|
||||
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||
pluginsList.add(CareportalPlugin.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());
|
||||
|
@ -209,6 +211,7 @@ public class MainApp extends Application {
|
|||
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());
|
||||
|
||||
|
@ -235,13 +238,40 @@ public class MainApp extends Application {
|
|||
new Thread(() -> {
|
||||
SystemClock.sleep(5000);
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Initialization", null);
|
||||
startKeepAliveService();
|
||||
}).start();
|
||||
}
|
||||
|
||||
new Thread(() -> KeepAliveReceiver.setAlarm(this)).start();
|
||||
doMigrations();
|
||||
}
|
||||
|
||||
private void doMigrations() {
|
||||
|
||||
// guarantee that the unreachable threshold is at least 30 and of type String
|
||||
// Added in 1.57 at 21.01.2018
|
||||
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||
if (unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
|
||||
|
||||
// 2.5 -> 2.6
|
||||
if (!SP.contains(R.string.key_units)) {
|
||||
String newUnits = Constants.MGDL;
|
||||
Profile p = ProfileFunctions.getInstance().getProfile();
|
||||
if (p != null && p.getData() != null && p.getData().has("units")) {
|
||||
try {
|
||||
newUnits = p.getData().getString("units");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
SP.putString(R.string.key_units, newUnits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerLocalBroadcastReceiver() {
|
||||
lbm = LocalBroadcastManager.getInstance(this);
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT));
|
||||
|
@ -256,39 +286,21 @@ public class MainApp extends Application {
|
|||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_CAL));
|
||||
|
||||
//register alarms
|
||||
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ALARM));
|
||||
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ANNOUNCEMENT));
|
||||
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_CLEAR_ALARM));
|
||||
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_URGENT_ALARM));
|
||||
|
||||
//register ack alarm
|
||||
lbm.registerReceiver(ackAlarmReciever, new IntentFilter(Intents.ACTION_ACK_ALARM));
|
||||
|
||||
//register dbaccess
|
||||
lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ALARM));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ANNOUNCEMENT));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_CLEAR_ALARM));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_URGENT_ALARM));
|
||||
|
||||
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
|
||||
this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
|
||||
|
||||
}
|
||||
|
||||
private void startKeepAliveService() {
|
||||
if (keepAliveReceiver == null) {
|
||||
keepAliveReceiver = new KeepAliveReceiver();
|
||||
keepAliveReceiver.setAlarm(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopKeepAliveService() {
|
||||
if (keepAliveReceiver != null)
|
||||
KeepAliveReceiver.cancelAlarm(this);
|
||||
}
|
||||
|
||||
public static String gs(int id) {
|
||||
public static String gs(@StringRes int id) {
|
||||
return sResources.getString(id);
|
||||
}
|
||||
|
||||
public static String gs(int id, Object... args) {
|
||||
public static String gs(@StringRes int id, Object... args) {
|
||||
return sResources.getString(id, args);
|
||||
}
|
||||
|
||||
|
@ -296,8 +308,8 @@ public class MainApp extends Application {
|
|||
return sResources.getQuantityString(id, quantity, args);
|
||||
}
|
||||
|
||||
public static int gc(int id) {
|
||||
return sResources.getColor(id);
|
||||
public static int gc(@ColorRes int id) {
|
||||
return ContextCompat.getColor(instance(), id);
|
||||
}
|
||||
|
||||
public static MainApp instance() {
|
||||
|
@ -308,13 +320,6 @@ public class MainApp extends Application {
|
|||
return sDatabaseHelper;
|
||||
}
|
||||
|
||||
public static void closeDbHelper() {
|
||||
if (sDatabaseHelper != null) {
|
||||
sDatabaseHelper.close();
|
||||
sDatabaseHelper = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static FirebaseAnalytics getFirebaseAnalytics() {
|
||||
return mFirebaseAnalytics;
|
||||
}
|
||||
|
@ -417,20 +422,12 @@ public class MainApp extends Application {
|
|||
public void onTerminate() {
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("onTerminate");
|
||||
super.onTerminate();
|
||||
if (sDatabaseHelper != null) {
|
||||
sDatabaseHelper.close();
|
||||
sDatabaseHelper = null;
|
||||
}
|
||||
|
||||
if (btReceiver != null) {
|
||||
unregisterReceiver(btReceiver);
|
||||
}
|
||||
|
||||
if (timeDateOrTZChangeReceiver != null) {
|
||||
if (timeDateOrTZChangeReceiver != null)
|
||||
unregisterReceiver(timeDateOrTZChangeReceiver);
|
||||
}
|
||||
|
||||
unregisterActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
|
||||
KeepAliveReceiver.cancelAlarm(this);
|
||||
super.onTerminate();
|
||||
}
|
||||
|
||||
public static int dpToPx(int dp) {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.dialogs.BolusProgressDialog
|
||||
|
||||
class BolusProgressHelperActivity : DialogAppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
BolusProgressDialog()
|
||||
.setHelperActivity(this)
|
||||
.setInsulin(intent.getDoubleExtra("insulin", 0.0))
|
||||
.show(supportFragmentManager, "BolusProgress")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import info.nightscout.androidaps.utils.LocaleHelper
|
||||
|
||||
open class DialogAppCompatActivity : AppCompatActivity() {
|
||||
public override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.dialogs
|
||||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||
import info.nightscout.androidaps.dialogs.ErrorDialog
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
|
||||
class ErrorHelperActivity : NoSplashAppCompatActivity() {
|
||||
class ErrorHelperActivity : DialogAppCompatActivity() {
|
||||
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
@ -89,7 +89,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
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), null);
|
||||
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning));
|
||||
}
|
||||
updatePrefSummary(myPreferenceFragment.findPreference(key));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package info.nightscout.androidaps.activities
|
|||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin
|
||||
|
||||
class RequestDexcomPermissionActivity : NoSplashAppCompatActivity() {
|
||||
class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
|
||||
|
||||
private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
package info.nightscout.androidaps.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
||||
|
||||
public class SingleFragmentActivity extends AppCompatActivity {
|
||||
|
||||
private PluginBase plugin;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_single_fragment);
|
||||
|
||||
this.plugin = MainApp.getPluginsList().get(getIntent().getIntExtra("plugin", -1));
|
||||
setTitle(plugin.getName());
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout,
|
||||
Fragment.instantiate(this, plugin.pluginDescription.getFragmentClass())).commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
else if (item.getItemId() == R.id.nav_plugin_preferences) {
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (plugin.getPreferencesId() != -1)
|
||||
getMenuInflater().inflate(R.menu.menu_single_fragment, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.utils.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.PasswordProtection
|
||||
|
||||
class SingleFragmentActivity : AppCompatActivity() {
|
||||
private var plugin: PluginBase? = null
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_single_fragment)
|
||||
plugin = MainApp.getPluginsList()[intent.getIntExtra("plugin", -1)]
|
||||
title = plugin?.name
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager.beginTransaction().replace(R.id.frame_layout,
|
||||
supportFragmentManager.fragmentFactory.instantiate(ClassLoader.getSystemClassLoader(), plugin?.pluginDescription?.fragmentClass!!)).commit()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
return true
|
||||
} else if (item.itemId == R.id.nav_plugin_preferences) {
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", Runnable {
|
||||
val i = Intent(this, PreferencesActivity::class.java)
|
||||
i.putExtra("id", plugin?.preferencesId)
|
||||
startActivity(i)
|
||||
}, null)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (plugin?.preferencesId != -1) menuInflater.inflate(R.menu.menu_single_fragment, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
public override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.TddCalculator
|
||||
import info.nightscout.androidaps.utils.TirCalculator
|
||||
import kotlinx.android.synthetic.main.stats_activity.*
|
||||
|
||||
class StatsActivity : NoSplashAppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.stats_activity)
|
||||
|
||||
stats_tdds.text = TddCalculator.stats()
|
||||
stats_tir.text = TirCalculator.stats()
|
||||
stats_activity.text = ActivityMonitor.stats()
|
||||
|
||||
ok.setOnClickListener { finish() }
|
||||
stats_reset.setOnClickListener {
|
||||
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats), Runnable {
|
||||
ActivityMonitor.reset()
|
||||
recreate()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.ArrayAdapter
|
||||
import com.google.firebase.auth.FirebaseAuth
|
||||
import com.google.firebase.database.FirebaseDatabase
|
||||
import info.nightscout.androidaps.R
|
||||
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.utils.*
|
||||
import kotlinx.android.synthetic.main.survey_activity.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class SurveyActivity : NoSplashAppCompatActivity() {
|
||||
private val log = LoggerFactory.getLogger(SurveyActivity::class.java)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.survey_activity)
|
||||
|
||||
survey_id.text = InstanceId.instanceId()
|
||||
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
val profileList = profileStore?.getProfileList() ?: return
|
||||
survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||
|
||||
survey_tdds.text = TddCalculator.stats()
|
||||
survey_tir.text = TirCalculator.stats()
|
||||
survey_activity.text = ActivityMonitor.stats()
|
||||
|
||||
survey_profile.setOnClickListener {
|
||||
val age = SafeParse.stringToDouble(survey_age.text.toString())
|
||||
val weight = SafeParse.stringToDouble(survey_weight.text.toString())
|
||||
val tdd = SafeParse.stringToDouble(survey_tdd.text.toString())
|
||||
if (age < 1 || age > 120) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if ((weight < 5 || weight > 150) && tdd == 0.0) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if ((tdd < 5 || tdd > 150) && weight == 0.0) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
val profile = DefaultProfile().profile(age, tdd, weight, ProfileFunctions.getSystemUnits())
|
||||
val args = Bundle()
|
||||
args.putLong("time", DateUtil.now())
|
||||
args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal)
|
||||
args.putString("customProfile", profile.data.toString())
|
||||
args.putString("customProfileUnits", profile.units)
|
||||
args.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
|
||||
val pvd = ProfileViewerDialog()
|
||||
pvd.arguments = args
|
||||
pvd.show(supportFragmentManager, "ProfileViewDialog")
|
||||
}
|
||||
|
||||
survey_submit.setOnClickListener {
|
||||
val r = FirebaseRecord()
|
||||
r.id = InstanceId.instanceId()
|
||||
r.age = SafeParse.stringToInt(survey_age.text.toString())
|
||||
r.weight = SafeParse.stringToInt(survey_weight.text.toString())
|
||||
if (r.age < 1 || r.age > 120) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (r.weight < 5 || r.weight > 150) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (survey_spinner.selectedItem == null)
|
||||
return@setOnClickListener
|
||||
val profileName = survey_spinner.selectedItem.toString()
|
||||
val specificProfile = profileStore.getSpecificProfile(profileName)
|
||||
|
||||
r.profileJson = specificProfile.toString()
|
||||
|
||||
val auth = FirebaseAuth.getInstance()
|
||||
auth.signInAnonymously()
|
||||
.addOnCompleteListener(this) { task ->
|
||||
if (task.isSuccessful) {
|
||||
log.debug("signInAnonymously:success")
|
||||
val user = auth.currentUser // TODO: do we need this, seems unused?
|
||||
|
||||
val database = FirebaseDatabase.getInstance().reference
|
||||
database.child("survey").child(r.id).setValue(r)
|
||||
} else {
|
||||
log.error("signInAnonymously:failure", task.exception)
|
||||
ToastUtils.showToastInUiThread(this, "Authentication failed.")
|
||||
//updateUI(null)
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
inner class FirebaseRecord {
|
||||
var id = ""
|
||||
var age: Int = 0
|
||||
var weight: Int = 0
|
||||
var profileJson = "ghfg"
|
||||
}
|
||||
|
||||
}
|
|
@ -397,7 +397,7 @@ public class Profile {
|
|||
return toMgdl(getIsfTimeFromMidnight(secondsFromMidnight(time)), units);
|
||||
}
|
||||
|
||||
double getIsfTimeFromMidnight(int timeAsSeconds) {
|
||||
public double getIsfTimeFromMidnight(int timeAsSeconds) {
|
||||
if (isf_v == null)
|
||||
isf_v = convertToSparseArray(isf);
|
||||
return getValueToTime(isf_v, timeAsSeconds);
|
||||
|
@ -589,7 +589,7 @@ public class Profile {
|
|||
public double getMaxDailyBasal() {
|
||||
double max = 0d;
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
|
||||
double value = getBasalTimeFromMidnight(hour * 60 * 60);
|
||||
if (value > max) max = value;
|
||||
}
|
||||
return max;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.data
|
||||
|
||||
import androidx.collection.ArrayMap
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
|
@ -40,21 +41,19 @@ class ProfileStore(val data: JSONObject) {
|
|||
|
||||
fun getSpecificProfile(profileName: String): Profile? {
|
||||
var profile: Profile? = null
|
||||
try {
|
||||
getStore()?.let { store ->
|
||||
if (store.has(profileName)) {
|
||||
profile = cachedObjects[profileName]
|
||||
if (profile == null) {
|
||||
val profileObject = store.getJSONObject(profileName)
|
||||
if (profileObject != null && profileObject.has("units")) {
|
||||
profile = Profile(profileObject, profileObject.getString("units"))
|
||||
getStore()?.let { store ->
|
||||
if (store.has(profileName)) {
|
||||
profile = cachedObjects[profileName]
|
||||
if (profile == null) {
|
||||
JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject ->
|
||||
// take units from profile and if N/A from store
|
||||
JsonHelper.safeGetStringAllowNull(profileObject, "units", JsonHelper.safeGetString(data, "units"))?.let { units ->
|
||||
profile = Profile(profileObject, units)
|
||||
cachedObjects[profileName] = profile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
return profile
|
||||
}
|
||||
|
|
|
@ -125,7 +125,8 @@ public class QuickWizardEntry {
|
|||
trend = true;
|
||||
}
|
||||
|
||||
return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard");
|
||||
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() {
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package info.nightscout.androidaps.data.defaultProfile
|
||||
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
|
||||
class DefaultProfile {
|
||||
var oneToFive: TreeMap<Double, Array<Double>> = TreeMap()
|
||||
var sixToEleven: TreeMap<Double, Array<Double>> = TreeMap()
|
||||
var twelveToSeventeen: TreeMap<Double, Array<Double>> = TreeMap()
|
||||
var eighteenToTwentyfor: TreeMap<Double, Array<Double>> = TreeMap()
|
||||
|
||||
fun profile(age: Double, tdd: Double, weight: Double, units: String): Profile {
|
||||
val profile = JSONObject()
|
||||
if (age >= 1 && age < 6) {
|
||||
val _tdd = if (tdd == 0.0) 0.6 * weight else tdd
|
||||
closest(oneToFive, _tdd * 0.3)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||
val ic = Round.roundTo(250.0 / _tdd, 1.0)
|
||||
profile.put("carbratio", singleValueArray(ic, arrayOf( 0.0, -4.0, -1.0, -2.0, -4.0, 0.0, -4.0)))
|
||||
val isf = Round.roundTo(200.0 / _tdd, 0.1)
|
||||
profile.put("sens", singleValueArray(isf, arrayOf( 0.0, -2.0, -0.0, -0.0, -2.0, 0.0, -2.0)))
|
||||
} else if (age >= 6 && age < 12) {
|
||||
val _tdd = if (tdd == 0.0) 0.8 * weight else tdd
|
||||
closest(sixToEleven, _tdd * 0.4)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||
val ic = Round.roundTo(375.0 / _tdd, 1.0)
|
||||
profile.put("carbratio", singleValueArray(ic, arrayOf( 0.0, -3.0, 0.0, -1.0, -3.0, 0.0, -2.0)))
|
||||
val isf = Round.roundTo(170.0 / _tdd, 0.1)
|
||||
profile.put("sens", singleValueArray(isf, arrayOf( 0.0, -1.0, -0.0, -0.0, -1.0, 0.0, -1.0)))
|
||||
} else if (age >= 12 && age < 17) {
|
||||
val _tdd = if (tdd == 0.0) 1.0 * weight else tdd
|
||||
closest(twelveToSeventeen, _tdd * 0.5)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||
val ic = Round.roundTo(500.0 / _tdd, 1.0)
|
||||
profile.put("carbratio", singleValueArray(ic, arrayOf( 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0)))
|
||||
val isf = Round.roundTo(100.0 / _tdd, 0.1)
|
||||
profile.put("sens", singleValueArray(isf, arrayOf( 0.2, 0.0, 0.2, 0.2, 0.0, 0.2, 0.2)))
|
||||
} else if (age >= 18) {
|
||||
|
||||
}
|
||||
profile.put("dia", 5.0)
|
||||
profile.put("carbs_hr", 20) // not used
|
||||
profile.put("delay", 5.0) // not used
|
||||
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_low", JSONArray().put(JSONObject().put("time", "00:00").put("value", Profile.fromMgdlToUnits(108.0, units))))
|
||||
return Profile(profile, units)
|
||||
}
|
||||
|
||||
init {
|
||||
oneToFive[1.00] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050)
|
||||
oneToFive[1.13] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050)
|
||||
oneToFive[1.25] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.050, 0.050)
|
||||
oneToFive[1.38] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.050, 0.050)
|
||||
oneToFive[1.50] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.075, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.050, 0.050, 0.050, 0.075, 0.100, 0.100, 0.050, 0.050)
|
||||
oneToFive[1.75] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.050, 0.050, 0.050, 0.060, 0.060, 0.075, 0.075, 0.050, 0.050, 0.050, 0.100, 0.125, 0.100, 0.050, 0.050)
|
||||
oneToFive[2.00] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.075, 0.050, 0.050, 0.065, 0.065, 0.075, 0.075, 0.050, 0.050, 0.050, 0.100, 0.125, 0.100, 0.050, 0.050)
|
||||
oneToFive[2.25] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.100, 0.100, 0.075, 0.060, 0.060, 0.070, 0.070, 0.100, 0.100, 0.050, 0.050, 0.050, 0.125, 0.150, 0.125, 0.065, 0.050)
|
||||
oneToFive[2.50] = arrayOf(0.050, 0.050, 0.050, 0.050, 0.075, 0.075, 0.100, 0.125, 0.125, 0.100, 0.065, 0.065, 0.075, 0.075, 0.125, 0.125, 0.060, 0.060, 0.060, 0.150, 0.150, 0.150, 0.070, 0.060)
|
||||
oneToFive[2.75] = arrayOf(0.075, 0.075, 0.075, 0.100, 0.100, 0.100, 0.125, 0.150, 0.125, 0.100, 0.070, 0.070, 0.080, 0.080, 0.150, 0.150, 0.070, 0.070, 0.070, 0.175, 0.175, 0.175, 0.080, 0.070)
|
||||
oneToFive[3.25] = arrayOf(0.100, 0.100, 0.100, 0.125, 0.125, 0.125, 0.150, 0.150, 0.150, 0.100, 0.080, 0.080, 0.100, 0.100, 0.175, 0.175, 0.075, 0.075, 0.075, 0.200, 0.200, 0.200, 0.090, 0.080)
|
||||
oneToFive[3.75] = arrayOf(0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.175, 0.175, 0.175, 0.100, 0.085, 0.085, 0.110, 0.110, 0.185, 0.185, 0.080, 0.080, 0.080, 0.225, 0.225, 0.225, 0.100, 0.090)
|
||||
oneToFive[4.25] = arrayOf(0.125, 0.125, 0.130, 0.140, 0.140, 0.140, 0.200, 0.200, 0.200, 0.125, 0.090, 0.090, 0.120, 0.120, 0.200, 0.200, 0.100, 0.100, 0.100, 0.250, 0.250, 0.250, 0.125, 0.100)
|
||||
oneToFive[4.75] = arrayOf(0.125, 0.130, 0.135, 0.150, 0.150, 0.150, 0.200, 0.225, 0.200, 0.125, 0.100, 0.100, 0.125, 0.125, 0.250, 0.200, 0.110, 0.125, 0.125, 0.275, 0.275, 0.275, 0.130, 0.125)
|
||||
oneToFive[5.25] = arrayOf(0.150, 0.150, 0.150, 0.170, 0.170, 0.170, 0.225, 0.225, 0.225, 0.130, 0.125, 0.125, 0.140, 0.140, 0.250, 0.250, 0.150, 0.150, 0.150, 0.300, 0.300, 0.300, 0.150, 0.150)
|
||||
oneToFive[6.00] = arrayOf(0.170, 0.170, 0.175, 0.200, 0.200, 0.200, 0.250, 0.250, 0.250, 0.150, 0.125, 0.125, 0.150, 0.150, 0.275, 0.275, 0.170, 0.150, 0.150, 0.350, 0.350, 0.350, 0.175, 0.150)
|
||||
oneToFive[6.75] = arrayOf(0.200, 0.200, 0.200, 0.225, 0.225, 0.225, 0.275, 0.275, 0.275, 0.200, 0.130, 0.130, 0.175, 0.175, 0.300, 0.300, 0.170, 0.175, 0.175, 0.375, 0.375, 0.375, 0.200, 0.175)
|
||||
oneToFive[7.50] = arrayOf(0.225, 0.230, 0.235, 0.250, 0.250, 0.250, 0.300, 0.300, 0.300, 0.250, 0.150, 0.150, 0.200, 0.200, 0.325, 0.325, 0.200, 0.200, 0.200, 0.400, 0.450, 0.400, 0.350, 0.200)
|
||||
|
||||
sixToEleven[5.26] = arrayOf(0.18, 0.18, 0.18, 0.20, 0.20, 0.23, 0.25, 0.25, 0.25, 0.18, 0.15, 0.13, 0.15, 0.15, 0.25, 0.25, 0.20, 0.15, 0.18, 0.25, 0.25, 0.25, 0.23, 0.20)
|
||||
sixToEleven[5.61] = arrayOf(0.18, 0.20, 0.20, 0.23, 0.23, 0.25, 0.28, 0.28, 0.25, 0.20, 0.15, 0.13, 0.15, 0.18, 0.25, 0.25, 0.20, 0.15, 0.18, 0.28, 0.25, 0.25, 0.23, 0.20)
|
||||
sixToEleven[5.93] = arrayOf(0.20, 0.20, 0.23, 0.25, 0.25, 0.25, 0.30, 0.30, 0.30, 0.25, 0.15, 0.15, 0.18, 0.18, 0.28, 0.28, 0.20, 0.20, 0.20, 0.28, 0.28, 0.28, 0.25, 0.23)
|
||||
sixToEleven[6.26] = arrayOf(0.20, 0.23, 0.23, 0.25, 0.25, 0.28, 0.33, 0.30, 0.30, 0.25, 0.18, 0.15, 0.18, 0.18, 0.28, 0.28, 0.23, 0.20, 0.20, 0.28, 0.30, 0.28, 0.25, 0.23)
|
||||
sixToEleven[6.60] = arrayOf(0.23, 0.23, 0.25, 0.25, 0.25, 0.28, 0.33, 0.33, 0.33, 0.28, 0.18, 0.15, 0.18, 0.18, 0.30, 0.28, 0.23, 0.23, 0.20, 0.30, 0.30, 0.30, 0.25, 0.25)
|
||||
sixToEleven[7.26] = arrayOf(0.23, 0.25, 0.28, 0.28, 0.30, 0.33, 0.38, 0.35, 0.35, 0.30, 0.18, 0.18, 0.18, 0.19, 0.33, 0.30, 0.25, 0.23, 0.23, 0.33, 0.33, 0.33, 0.30, 0.25)
|
||||
sixToEleven[7.92] = arrayOf(0.25, 0.25, 0.28, 0.30, 0.33, 0.35, 0.38, 0.38, 0.38, 0.35, 0.20, 0.20, 0.23, 0.25, 0.35, 0.33, 0.30, 0.25, 0.25, 0.35, 0.35, 0.35, 0.33, 0.28)
|
||||
sixToEleven[8.57] = arrayOf(0.28, 0.28, 0.30, 0.30, 0.33, 0.38, 0.40, 0.43, 0.40, 0.38, 0.25, 0.25, 0.25, 0.28, 0.38, 0.38, 0.33, 0.28, 0.28, 0.38, 0.40, 0.38, 0.35, 0.30)
|
||||
sixToEleven[9.24] = arrayOf(0.30, 0.33, 0.35, 0.38, 0.40, 0.40, 0.43, 0.45, 0.43, 0.40, 0.30, 0.25, 0.28, 0.28, 0.38, 0.40, 0.33, 0.30, 0.30, 0.40, 0.43, 0.40, 0.38, 0.35)
|
||||
sixToEleven[9.89] = arrayOf(0.35, 0.35, 0.38, 0.40, 0.40, 0.43, 0.45, 0.48, 0.45, 0.40, 0.30, 0.25, 0.28, 0.30, 0.40, 0.43, 0.35, 0.33, 0.33, 0.43, 0.45, 0.43, 0.40, 0.38)
|
||||
sixToEleven[10.56] = arrayOf(0.38, 0.38, 0.40, 0.43, 0.45, 0.45, 0.48, 0.50, 0.48, 0.40, 0.35, 0.25, 0.30, 0.33, 0.43, 0.45, 0.35, 0.35, 0.35, 0.45, 0.48, 0.45, 0.43, 0.40)
|
||||
sixToEleven[11.21] = arrayOf(0.40, 0.43, 0.43, 0.45, 0.48, 0.50, 0.53, 0.55, 0.50, 0.40, 0.35, 0.30, 0.33, 0.33, 0.45, 0.48, 0.38, 0.35, 0.37, 0.50, 0.50, 0.48, 0.45, 0.43)
|
||||
sixToEleven[11.88] = arrayOf(0.43, 0.43, 0.45, 0.45, 0.48, 0.50, 0.55, 0.58, 0.50, 0.40, 0.35, 0.33, 0.33, 0.33, 0.48, 0.50, 0.40, 0.38, 0.38, 0.53, 0.53, 0.50, 0.48, 0.45)
|
||||
sixToEleven[12.53] = arrayOf(0.45, 0.45, 0.48, 0.50, 0.53, 0.55, 0.60, 0.60, 0.60, 0.45, 0.40, 0.35, 0.35, 0.38, 0.50, 0.53, 0.40, 0.38, 0.38, 0.55, 0.58, 0.55, 0.50, 0.48)
|
||||
sixToEleven[13.19] = arrayOf(0.48, 0.48, 0.50, 0.55, 0.58, 0.60, 0.65, 0.65, 0.65, 0.50, 0.45, 0.36, 0.38, 0.40, 0.55, 0.55, 0.45, 0.40, 0.40, 0.60, 0.60, 0.58, 0.55, 0.50)
|
||||
sixToEleven[14.18] = arrayOf(0.53, 0.53, 0.55, 0.60, 0.65, 0.68, 0.70, 0.70, 0.68, 0.60, 0.55, 0.40, 0.40, 0.45, 0.60, 0.60, 0.50, 0.45, 0.45, 0.63, 0.65, 0.63, 0.60, 0.60)
|
||||
sixToEleven[15.17] = arrayOf(0.55, 0.58, 0.60, 0.65, 0.70, 0.70, 0.75, 0.75, 0.70, 0.65, 0.60, 0.42, 0.42, 0.45, 0.65, 0.65, 0.60, 0.50, 0.50, 0.68, 0.68, 0.65, 0.63, 0.63)
|
||||
sixToEleven[16.50] = arrayOf(0.60, 0.63, 0.65, 0.70, 0.70, 0.70, 0.80, 0.80, 0.80, 0.70, 0.60, 0.45, 0.45, 0.50, 0.65, 0.70, 0.60, 0.55, 0.55, 0.75, 0.75, 0.70, 0.65, 0.65)
|
||||
|
||||
twelveToSeventeen[10.70] = arrayOf(0.30, 0.30, 0.30, 0.30, 0.40, 0.40, 0.60, 0.60, 0.60, 0.40, 0.35, 0.30, 0.30, 0.35, 0.45, 0.50, 0.40, 0.30, 0.30, 0.40, 0.50, 0.40, 0.40, 0.30)
|
||||
twelveToSeventeen[11.10] = arrayOf(0.30, 0.30, 0.30, 0.35, 0.40, 0.45, 0.60, 0.60, 0.60, 0.40, 0.40, 0.30, 0.35, 0.40, 0.50, 0.50, 0.30, 0.30, 0.30, 0.50, 0.50, 0.50, 0.30, 0.30)
|
||||
twelveToSeventeen[11.60] = arrayOf(0.30, 0.30, 0.35, 0.45, 0.45, 0.50, 0.65, 0.65, 0.65, 0.45, 0.40, 0.40, 0.40, 0.40, 0.50, 0.55, 0.55, 0.45, 0.45, 0.50, 0.50, 0.50, 0.40, 0.40)
|
||||
twelveToSeventeen[13.00] = arrayOf(0.40, 0.40, 0.40, 0.50, 0.55, 0.60, 0.70, 0.70, 0.70, 0.60, 0.50, 0.40, 0.40, 0.40, 0.50, 0.60, 0.60, 0.50, 0.50, 0.60, 0.60, 0.60, 0.40, 0.30)
|
||||
twelveToSeventeen[15.60] = arrayOf(0.45, 0.50, 0.50, 0.60, 0.65, 0.70, 0.80, 0.80, 0.80, 0.70, 0.60, 0.60, 0.50, 0.50, 0.60, 0.70, 0.70, 0.60, 0.60, 0.60, 0.70, 0.70, 0.50, 0.50)
|
||||
twelveToSeventeen[17.00] = arrayOf(0.50, 0.55, 0.60, 0.70, 0.75, 0.80, 1.00, 1.00, 1.00, 0.80, 0.70, 0.60, 0.60, 0.60, 0.70, 0.80, 0.80, 0.65, 0.65, 0.65, 0.70, 0.70, 0.60, 0.60)
|
||||
twelveToSeventeen[18.00] = arrayOf(0.60, 0.65, 0.70, 0.80, 0.85, 0.90, 1.10, 1.10, 1.10, 0.90, 0.80, 0.60, 0.60, 0.60, 0.70, 0.80, 0.80, 0.70, 0.65, 0.70, 0.75, 0.70, 0.60, 0.60)
|
||||
twelveToSeventeen[20.20] = arrayOf(0.70, 0.75, 0.80, 0.90, 0.95, 1.00, 1.10, 1.10, 1.10, 0.90, 0.80, 0.70, 0.70, 0.70, 0.80, 0.90, 0.90, 0.75, 0.75, 0.75, 0.80, 0.80, 0.70, 0.70)
|
||||
twelveToSeventeen[21.60] = arrayOf(0.75, 0.80, 0.90, 0.90, 1.00, 1.00, 1.20, 1.20, 1.20, 0.90, 0.80, 0.70, 0.70, 0.70, 0.90, 1.00, 1.00, 0.80, 0.80, 0.80, 0.80, 0.80, 0.70, 0.70)
|
||||
twelveToSeventeen[23.80] = arrayOf(0.75, 0.80, 0.90, 1.00, 1.10, 1.10, 1.20, 1.20, 1.20, 1.00, 0.90, 0.80, 0.80, 0.80, 0.90, 1.10, 1.10, 0.90, 0.90, 0.90, 1.00, 1.00, 0.80, 0.80)
|
||||
twelveToSeventeen[26.10] = arrayOf(0.80, 0.80, 0.90, 1.00, 1.20, 1.20, 1.30, 1.30, 1.30, 1.10, 1.00, 0.90, 0.90, 0.90, 1.00, 1.20, 1.10, 0.90, 0.90, 1.00, 1.00, 1.00, 0.90, 0.90)
|
||||
twelveToSeventeen[28.00] = arrayOf(0.90, 0.90, 1.00, 1.10, 1.10, 1.20, 1.30, 1.30, 1.30, 1.20, 1.00, 1.00, 1.00, 1.00, 1.20, 1.20, 1.20, 1.00, 1.00, 1.10, 1.10, 1.10, 0.90, 0.90)
|
||||
twelveToSeventeen[30.10] = arrayOf(1.00, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.50, 1.50, 1.30, 1.20, 1.00, 1.00, 1.00, 1.30, 1.40, 1.40, 1.00, 1.00, 1.15, 1.15, 1.10, 1.00, 1.00)
|
||||
twelveToSeventeen[32.60] = arrayOf(1.10, 1.10, 1.20, 1.20, 1.40, 1.50, 1.50, 1.50, 1.50, 1.30, 1.20, 1.10, 1.10, 1.10, 1.40, 1.50, 1.40, 1.10, 1.10, 1.20, 1.20, 1.20, 1.10, 1.10)
|
||||
twelveToSeventeen[35.20] = arrayOf(1.20, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.70, 1.50, 1.40, 1.20, 1.10, 1.10, 1.10, 1.40, 1.50, 1.60, 1.40, 1.20, 1.20, 1.30, 1.30, 1.20, 1.20)
|
||||
twelveToSeventeen[39.00] = arrayOf(1.30, 1.30, 1.40, 1.60, 1.60, 1.60, 1.90, 1.90, 1.90, 1.50, 1.30, 1.20, 1.20, 1.30, 1.50, 1.60, 1.70, 1.80, 1.50, 1.50, 1.60, 1.60, 1.30, 1.30)
|
||||
twelveToSeventeen[42.80] = arrayOf(1.40, 1.40, 1.50, 1.70, 1.80, 1.80, 2.00, 2.00, 2.00, 1.80, 1.80, 1.50, 1.50, 1.50, 1.60, 1.70, 1.80, 1.90, 1.60, 1.60, 1.70, 1.70, 1.50, 1.50)
|
||||
twelveToSeventeen[47.30] = arrayOf(1.50, 1.50, 1.70, 1.70, 2.00, 2.00, 2.20, 2.30, 2.20, 2.00, 1.80, 1.60, 1.60, 1.60, 1.80, 2.00, 2.10, 1.90, 1.80, 1.80, 2.00, 2.00, 1.60, 1.60)
|
||||
}
|
||||
|
||||
private fun closest(map: TreeMap<Double, Array<Double>>, key: Double): Array<Double>? {
|
||||
val low = map.floorEntry(key)
|
||||
val high = map.ceilingEntry(key)
|
||||
var res: Array<Double>? = null
|
||||
if (low != null && high != null) {
|
||||
res = if (Math.abs(key - low.key) < Math.abs(key - high.key))
|
||||
low.value
|
||||
else
|
||||
high.value
|
||||
} else if (low != null || high != null) {
|
||||
res = if (low != null) low.value else high.value
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun arrayToJson(b: Array<Double>): JSONArray {
|
||||
val basals = JSONArray()
|
||||
for (i in 0..23) {
|
||||
val time = String.format(Locale.ENGLISH, "%02d:00", i)
|
||||
basals.put(JSONObject().put("time", time).put("value", b[i].toString()))
|
||||
}
|
||||
return basals
|
||||
}
|
||||
|
||||
fun singleValueArray(value: Double, sample: Array<Double>): JSONArray {
|
||||
val array = JSONArray()
|
||||
array.put(JSONObject().put("time", "00:00").put("value", value + sample[0]))
|
||||
array.put(JSONObject().put("time", "06:00").put("value", value + sample[1]))
|
||||
array.put(JSONObject().put("time", "09:00").put("value", value + sample[2]))
|
||||
array.put(JSONObject().put("time", "11:00").put("value", value + sample[3]))
|
||||
array.put(JSONObject().put("time", "14:00").put("value", value + sample[4]))
|
||||
array.put(JSONObject().put("time", "16:00").put("value", value + sample[5]))
|
||||
array.put(JSONObject().put("time", "19:00").put("value", value + sample[6]))
|
||||
return array
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.db;
|
|||
import android.content.Context;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||
|
@ -32,7 +33,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||
import info.nightscout.androidaps.data.NonOverlappingIntervals;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||
|
@ -193,15 +194,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return newVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the database connections and clear any cached DAOs.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
}
|
||||
|
||||
|
||||
public long size(String database) {
|
||||
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
|
||||
}
|
||||
|
@ -558,12 +550,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
// ------------- DbRequests handling -------------------
|
||||
|
||||
public void create(DbRequest dbr) {
|
||||
try {
|
||||
public void create(DbRequest dbr) throws SQLException {
|
||||
getDaoDbRequest().create(dbr);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public int delete(DbRequest dbr) {
|
||||
|
@ -772,8 +760,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TempTarget tempTarget = new TempTarget()
|
||||
.date(trJson.getLong("mills"))
|
||||
.duration(JsonHelper.safeGetInt(trJson, "duration"))
|
||||
.low(Profile.toMgdl(trJson.getDouble("targetBottom"), units))
|
||||
.high(Profile.toMgdl(trJson.getDouble("targetTop"), units))
|
||||
.low(Profile.toMgdl(JsonHelper.safeGetDouble(trJson, "targetBottom"), units))
|
||||
.high(Profile.toMgdl(JsonHelper.safeGetDouble(trJson, "targetTop"), units))
|
||||
.reason(JsonHelper.safeGetString(trJson, "reason", ""))
|
||||
._id(trJson.getString("_id"))
|
||||
.source(Source.NIGHTSCOUT);
|
||||
|
@ -1425,7 +1413,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", false);
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("eventType", event);
|
||||
where.eq("eventType", event).and().isNotNull("json");
|
||||
queryBuilder.limit(1L);
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
|
@ -1445,10 +1433,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", mills);
|
||||
where.ge("date", mills).and().isNotNull("json").and().isNotNull("eventType");
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
careportalEvents = preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
return careportalEvents;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -1462,10 +1450,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.between("date", start, end);
|
||||
where.between("date", start, end).and().isNotNull("json").and().isNotNull("eventType");
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
careportalEvents = preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
return careportalEvents;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -1473,14 +1461,16 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void preprocessOpenAPSOfflineEvents(List<CareportalEvent> list) {
|
||||
OverlappingIntervals offlineEvents = new OverlappingIntervals();
|
||||
public List<CareportalEvent> preprocessOpenAPSOfflineEvents(List<CareportalEvent> list) {
|
||||
NonOverlappingIntervals offlineEvents = new NonOverlappingIntervals();
|
||||
List<CareportalEvent> other = new ArrayList<>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CareportalEvent event = list.get(i);
|
||||
if (!event.eventType.equals(CareportalEvent.OPENAPSOFFLINE)) continue;
|
||||
offlineEvents.add(event);
|
||||
if (event.eventType.equals(CareportalEvent.OPENAPSOFFLINE)) offlineEvents.add(event);
|
||||
else other.add(event);
|
||||
}
|
||||
|
||||
other.addAll(offlineEvents.getList());
|
||||
return other;
|
||||
}
|
||||
|
||||
public List<CareportalEvent> getCareportalEventsFromTime(long mills, String type, boolean ascending) {
|
||||
|
@ -1489,10 +1479,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", mills).and().eq("eventType", type);
|
||||
where.ge("date", mills).and().eq("eventType", type).and().isNotNull("json");
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
careportalEvents = preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
return careportalEvents;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -1505,9 +1495,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
List<CareportalEvent> careportalEvents;
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.isNotNull("json").and().isNotNull("eventType");
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
careportalEvents = preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||
return careportalEvents;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -1592,15 +1584,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
// ---------------- ProfileSwitch handling ---------------
|
||||
|
||||
public List<ProfileSwitch> getProfileSwitchData(boolean ascending) {
|
||||
public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) {
|
||||
try {
|
||||
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
||||
List<ProfileSwitch> profileSwitches;
|
||||
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
queryBuilder.limit(100L);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", from);
|
||||
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
||||
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
||||
//add last one without duration
|
||||
ProfileSwitch last = getLastProfileSwitchWithoutDuration();
|
||||
if (last != null) {
|
||||
if (!profileSwitches.contains(last))
|
||||
profileSwitches.add(last);
|
||||
}
|
||||
return profileSwitches;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -1608,6 +1608,28 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProfileSwitch getLastProfileSwitchWithoutDuration() {
|
||||
try {
|
||||
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
||||
List<ProfileSwitch> profileSwitches;
|
||||
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
||||
queryBuilder.orderBy("date", false);
|
||||
queryBuilder.limit(1L);
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("durationInMinutes", 0);
|
||||
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
||||
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
||||
if (profileSwitches.size() > 0)
|
||||
return profileSwitches.get(0);
|
||||
else
|
||||
return null;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 27.02.2016.
|
||||
|
@ -40,36 +41,49 @@ public class DbRequest {
|
|||
}
|
||||
|
||||
// dbAdd
|
||||
public DbRequest(String action, String collection, String nsClientID, JSONObject data) {
|
||||
public DbRequest(String action, String collection, JSONObject data) {
|
||||
this.action = action;
|
||||
this.collection = collection;
|
||||
this.nsClientID = "" + DateUtil.now();
|
||||
try {
|
||||
data.put("NSCLIENT_ID", nsClientID);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.data = data.toString();
|
||||
this.nsClientID = nsClientID;
|
||||
this._id = "";
|
||||
}
|
||||
|
||||
// dbUpdate, dbUpdateUnset
|
||||
public DbRequest(String action, String collection, String nsClientID, String _id, JSONObject data) {
|
||||
public DbRequest(String action, String collection, String _id, JSONObject data) {
|
||||
this.action = action;
|
||||
this.collection = collection;
|
||||
this.nsClientID = "" + DateUtil.now();
|
||||
try {
|
||||
data.put("NSCLIENT_ID", nsClientID);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.data = data.toString();
|
||||
this.nsClientID = nsClientID;
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
// dbRemove
|
||||
public DbRequest(String action, String collection, String nsClientID, String _id) {
|
||||
public DbRequest(String action, String collection,
|
||||
String _id) {
|
||||
JSONObject data = new JSONObject();
|
||||
this.action = action;
|
||||
this.collection = collection;
|
||||
this.data = new JSONObject().toString();
|
||||
this.nsClientID = nsClientID;
|
||||
this.nsClientID = "" + DateUtil.now();
|
||||
try {
|
||||
data.put("NSCLIENT_ID", nsClientID);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.data = data.toString();
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
public String hash() {
|
||||
return Hashing.sha1().hashString(action + collection + _id + data.toString(), Charsets.UTF_8).toString();
|
||||
}
|
||||
|
||||
public JSONObject toJSON() {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
|
|
|
@ -325,8 +325,8 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
|||
}
|
||||
|
||||
public String toStringMedium() {
|
||||
return "E " + DecimalFormatter.to2Decimal(absoluteRate()) + "U/h ("
|
||||
+ getRealDuration() + "/" + durationInMinutes + ") ";
|
||||
return DecimalFormatter.to2Decimal(absoluteRate()) + "U/h "
|
||||
+ getRealDuration() + "/" + durationInMinutes + "'";
|
||||
}
|
||||
|
||||
public String toStringTotal() {
|
||||
|
|
|
@ -6,8 +6,11 @@ import com.j256.ormlite.table.DatabaseTable;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 20.09.2017.
|
||||
|
@ -56,4 +59,12 @@ public class TDD {
|
|||
", total=" + total +
|
||||
']';
|
||||
}
|
||||
|
||||
public String toText() {
|
||||
return MainApp.gs(R.string.tddformat, DateUtil.dateStringShort(date), total, bolus, basal);
|
||||
}
|
||||
|
||||
public String toText(int days) {
|
||||
return MainApp.gs(R.string.tddformat, String.format("%d ", days) + MainApp.gs(R.string.days), total, bolus, basal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.BolusProgressHelperActivity
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.dialog_bolusprogress.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class BolusProgressDialog : DialogFragment() {
|
||||
private val log = LoggerFactory.getLogger(L.UI)
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_STATE = MainApp.gs(R.string.waitingforpump)
|
||||
@JvmField
|
||||
var bolusEnded = false
|
||||
@JvmField
|
||||
var stopPressed = false
|
||||
}
|
||||
|
||||
private var running = true
|
||||
private var amount = 0.0
|
||||
private var state: String? = null
|
||||
private var helpActivity: BolusProgressHelperActivity? = null
|
||||
|
||||
fun setInsulin(amount: Double): BolusProgressDialog {
|
||||
this.amount = amount
|
||||
bolusEnded = false
|
||||
return this
|
||||
}
|
||||
|
||||
fun setHelperActivity(activity: BolusProgressHelperActivity): BolusProgressDialog {
|
||||
helpActivity = activity
|
||||
return this
|
||||
}
|
||||
|
||||
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 = false
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
return inflater.inflate(R.layout.dialog_bolusprogress, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
overview_bolusprogress_title.text = String.format(MainApp.gs(R.string.overview_bolusprogress_goingtodeliver), amount)
|
||||
overview_bolusprogress_stop.setOnClickListener {
|
||||
if (L.isEnabled(L.UI)) log.debug("Stop bolus delivery button pressed")
|
||||
stopPressed = true
|
||||
overview_bolusprogress_stoppressed.visibility = View.VISIBLE
|
||||
overview_bolusprogress_stop.visibility = View.INVISIBLE
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.cancelAllBoluses()
|
||||
}
|
||||
overview_bolusprogress_progressbar.max = 100
|
||||
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
|
||||
overview_bolusprogress_status.text = state
|
||||
stopPressed = false
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (L.isEnabled(L.UI)) log.debug("onResume")
|
||||
if (!ConfigBuilderPlugin.getPlugin().commandQueue.bolusInQueue())
|
||||
bolusEnded = true
|
||||
|
||||
if (bolusEnded) dismiss()
|
||||
else running = true
|
||||
|
||||
disposable.add(toObservable(EventPumpStatusChanged::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ overview_bolusprogress_status.text = it.getStatus() }) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
disposable.add(toObservable(EventDismissBolusProgressIfRunning::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ if (running) dismiss() }) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
disposable.add(toObservable(EventOverviewBolusProgress::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
if (L.isEnabled(L.UI)) log.debug("Status: " + it.status + " Percent: " + it.percent)
|
||||
overview_bolusprogress_status.text = it.status
|
||||
overview_bolusprogress_progressbar.progress = it.percent
|
||||
if (it.percent == 100) {
|
||||
overview_bolusprogress_stop.visibility = View.INVISIBLE
|
||||
scheduleDismiss()
|
||||
}
|
||||
state = it.status
|
||||
}) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
if (L.isEnabled(L.UI)) log.debug("dismiss")
|
||||
try {
|
||||
super.dismiss()
|
||||
} catch (e: IllegalStateException) {
|
||||
// dialog not running yet. onResume will try again. Set bolusEnded to make extra
|
||||
// sure onResume will catch this
|
||||
bolusEnded = true
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
helpActivity?.finish()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (L.isEnabled(L.UI)) log.debug("onPause")
|
||||
running = false
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString("state", state)
|
||||
}
|
||||
|
||||
private fun scheduleDismiss() {
|
||||
if (L.isEnabled(L.UI)) log.debug("scheduleDismiss")
|
||||
Thread(Runnable {
|
||||
SystemClock.sleep(5000)
|
||||
bolusEnded = true
|
||||
val activity: Activity? = activity
|
||||
activity?.runOnUiThread {
|
||||
if (running) {
|
||||
if (L.isEnabled(L.UI)) log.debug("executing")
|
||||
try {
|
||||
dismiss()
|
||||
} catch (e: Exception) {
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.XdripCalibrations
|
||||
import kotlinx.android.synthetic.main.dialog_calibration.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
||||
class CalibrationDialog : DialogFragmentWithDate() {
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_calibration, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
|
||||
?: 0.0, units)
|
||||
if (units == Constants.MMOL)
|
||||
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
|
||||
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok)
|
||||
else
|
||||
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
|
||||
?: 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)
|
||||
}
|
||||
|
||||
override fun submit() :Boolean {
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val bg = overview_calibration_bg.value
|
||||
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(bg) + " " + unitLabel)
|
||||
if (bg > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
XdripCalibrations.confirmAndSendCalibration(bg, context)
|
||||
})
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.overview_calibration), MainApp.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.DatabaseHelper
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import kotlinx.android.synthetic.main.dialog_carbs.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
||||
class CarbsDialog : DialogFragmentWithDate() {
|
||||
|
||||
companion object {
|
||||
private const val FAV1_DEFAULT = 5
|
||||
private const val FAV2_DEFAULT = 10
|
||||
private const val FAV3_DEFAULT = 20
|
||||
}
|
||||
|
||||
private val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
val time = overview_carbs_time.value.toInt()
|
||||
if (time > 12 * 60 || time < -12 * 60) {
|
||||
overview_carbs_time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_duration.value > 10) {
|
||||
overview_carbs_duration.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_carbs.value.toInt() > maxCarbs) {
|
||||
overview_carbs_carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_carbs_time", overview_carbs_time.value)
|
||||
savedInstanceState.putDouble("overview_carbs_duration", overview_carbs_duration.value)
|
||||
savedInstanceState.putDouble("overview_carbs_carbs", overview_carbs_carbs.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_carbs, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
|
||||
overview_carbs_duration.setParams(savedInstanceState?.getDouble("overview_carbs_duration")
|
||||
?: 0.0, 0.0, 10.0, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
|
||||
overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs")
|
||||
?: 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.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
overview_carbs_plus2.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
overview_carbs_plus2.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
overview_carbs_plus3.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
overview_carbs_plus3.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
DatabaseHelper.actualBg()?.let { bgReading ->
|
||||
if (bgReading.value < 72)
|
||||
overview_carbs_hypo_tt.setChecked(true)
|
||||
}
|
||||
overview_carbs_hypo_tt.setOnClickListener {
|
||||
overview_carbs_activity_tt.isChecked = false
|
||||
overview_carbs_eating_soon_tt.isChecked = false
|
||||
}
|
||||
overview_carbs_activity_tt.setOnClickListener {
|
||||
overview_carbs_hypo_tt.isChecked = false
|
||||
overview_carbs_eating_soon_tt.isChecked = false
|
||||
}
|
||||
overview_carbs_eating_soon_tt.setOnClickListener {
|
||||
overview_carbs_hypo_tt.isChecked = false
|
||||
overview_carbs_activity_tt.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun toSignedString(value: Int): String {
|
||||
return if (value > 0) "+$value" else value.toString()
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val carbs = overview_carbs_carbs.value.toInt()
|
||||
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val activityTTDuration = DefaultValueHelper.determineActivityTTDuration()
|
||||
val activityTT = DefaultValueHelper.determineActivityTT()
|
||||
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
|
||||
val hypoTTDuration = DefaultValueHelper.determineHypoTTDuration()
|
||||
val hypoTT = DefaultValueHelper.determineHypoTT()
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
|
||||
val activitySelected = overview_carbs_activity_tt.isChecked
|
||||
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>")
|
||||
val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked
|
||||
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>")
|
||||
val hypoSelected = overview_carbs_hypo_tt.isChecked
|
||||
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>")
|
||||
|
||||
val timeOffset = overview_carbs_time.value.toInt()
|
||||
val time = eventTime + timeOffset * 1000 * 60
|
||||
if (timeOffset != 0)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
|
||||
val duration = overview_carbs_duration.value.toInt()
|
||||
if (duration > 0)
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour))
|
||||
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>")
|
||||
if (carbsAfterConstraints != carbs)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (activitySelected) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(activityTTDuration)
|
||||
.reason(MainApp.gs(R.string.activity))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
} else if (eatingSoonSelected) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(eatingSoonTTDuration)
|
||||
.reason(MainApp.gs(R.string.eatingsoon))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
} else if (hypoSelected) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(hypoTTDuration)
|
||||
.reason(MainApp.gs(R.string.hypo))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
if (carbsAfterConstraints > 0) {
|
||||
if (duration == 0) {
|
||||
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
|
||||
} else {
|
||||
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
|
||||
NSUpload.uploadEvent(CareportalEvent.NOTE, time - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
|
||||
}
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.carbs), MainApp.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.Translator
|
||||
import kotlinx.android.synthetic.main.dialog_care.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.json.JSONObject
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
||||
class CareDialog : DialogFragmentWithDate() {
|
||||
|
||||
enum class EventType {
|
||||
BGCHECK,
|
||||
SENSOR_INSERT,
|
||||
BATTERY_CHANGE,
|
||||
NOTE,
|
||||
EXERCISE
|
||||
}
|
||||
|
||||
private var options: EventType = EventType.BGCHECK
|
||||
@StringRes
|
||||
private var event: Int = R.string.none
|
||||
|
||||
fun setOptions(options: EventType, @StringRes event: Int): CareDialog {
|
||||
this.options = options
|
||||
this.event = event
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("actions_care_bg", actions_care_bg.value)
|
||||
savedInstanceState.putDouble("actions_care_duration", actions_care_duration.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_care, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
actions_care_icon.setImageResource(when (options) {
|
||||
EventType.BGCHECK -> R.drawable.icon_cp_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.drawable.icon_cp_cgm_insert
|
||||
EventType.BATTERY_CHANGE -> R.drawable.icon_cp_pump_battery
|
||||
EventType.NOTE -> R.drawable.icon_cp_note
|
||||
EventType.EXERCISE -> R.drawable.icon_cp_exercise
|
||||
})
|
||||
actions_care_title.text = MainApp.gs(when (options) {
|
||||
EventType.BGCHECK -> R.string.careportal_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert
|
||||
EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange
|
||||
EventType.NOTE -> R.string.careportal_note
|
||||
EventType.EXERCISE -> R.string.careportal_exercise
|
||||
})
|
||||
|
||||
when (options) {
|
||||
EventType.BGCHECK -> {
|
||||
action_care_duration_layout.visibility = View.GONE
|
||||
}
|
||||
EventType.SENSOR_INSERT,
|
||||
EventType.BATTERY_CHANGE -> {
|
||||
action_care_bg_layout.visibility = View.GONE
|
||||
actions_care_bgsource.visibility = View.GONE
|
||||
action_care_duration_layout.visibility = View.GONE
|
||||
}
|
||||
EventType.NOTE,
|
||||
EventType.EXERCISE -> {
|
||||
action_care_bg_layout.visibility = View.GONE
|
||||
actions_care_bgsource.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
|
||||
?: 0.0, ProfileFunctions.getSystemUnits())
|
||||
val bgTextWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
if (actions_care_sensor.isChecked) actions_care_meter.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
if (ProfileFunctions.getSystemUnits() == Constants.MMOL) {
|
||||
actions_care_bgunits.text = MainApp.gs(R.string.mmol)
|
||||
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
|
||||
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, bgTextWatcher)
|
||||
} else {
|
||||
actions_care_bgunits.text = MainApp.gs(R.string.mgdl)
|
||||
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
|
||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok, bgTextWatcher)
|
||||
}
|
||||
actions_care_duration.setParams(savedInstanceState?.getDouble("actions_care_duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
|
||||
if (options == EventType.NOTE)
|
||||
notes_layout?.visibility = View.VISIBLE // independent to preferences
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val enteredBy = SP.getString("careportal_enteredby", "")
|
||||
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
|
||||
val json = JSONObject()
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
if (options == EventType.BGCHECK) {
|
||||
val type =
|
||||
when {
|
||||
actions_care_meter.isChecked -> "Finger"
|
||||
actions_care_sensor.isChecked -> "Sensor"
|
||||
else -> "Manual"
|
||||
}
|
||||
actions.add(MainApp.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))
|
||||
json.put("glucose", actions_care_bg.value)
|
||||
json.put("glucoseType", type)
|
||||
}
|
||||
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()))
|
||||
json.put("duration", actions_care_duration.value.toInt())
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty()) {
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
json.put("notes", notes)
|
||||
}
|
||||
eventTime -= eventTime % 1000
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
json.put("created_at", DateUtil.toISOString(eventTime))
|
||||
json.put("mills", eventTime)
|
||||
json.put("eventType", when (options) {
|
||||
EventType.BGCHECK -> CareportalEvent.BGCHECK
|
||||
EventType.SENSOR_INSERT -> CareportalEvent.SENSORCHANGE
|
||||
EventType.BATTERY_CHANGE -> CareportalEvent.PUMPBATTERYCHANGE
|
||||
EventType.NOTE -> CareportalEvent.NOTE
|
||||
EventType.EXERCISE -> CareportalEvent.EXERCISE
|
||||
})
|
||||
json.put("units", ProfileFunctions.getSystemUnits())
|
||||
if (enteredBy.isNotEmpty())
|
||||
json.put("enteredBy", enteredBy)
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val careportalEvent = CareportalEvent()
|
||||
careportalEvent.date = eventTime
|
||||
careportalEvent.source = Source.USER
|
||||
careportalEvent.eventType = when (options) {
|
||||
EventType.BGCHECK -> CareportalEvent.BGCHECK
|
||||
EventType.SENSOR_INSERT -> CareportalEvent.SENSORCHANGE
|
||||
EventType.BATTERY_CHANGE -> CareportalEvent.PUMPBATTERYCHANGE
|
||||
EventType.NOTE -> CareportalEvent.NOTE
|
||||
EventType.EXERCISE -> CareportalEvent.EXERCISE
|
||||
}
|
||||
careportalEvent.json = json.toString()
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent)
|
||||
NSUpload.uploadCareportalEntryToNS(json)
|
||||
}, null)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.toVisibility
|
||||
import kotlinx.android.synthetic.main.datetime.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
|
||||
abstract class DialogFragmentWithDate : DialogFragment() {
|
||||
private val log = LoggerFactory.getLogger(DialogFragmentWithDate::class.java)
|
||||
|
||||
var eventTime = DateUtil.now()
|
||||
var eventTimeChanged = false
|
||||
|
||||
//one shot guards
|
||||
private var okClicked: Boolean = false
|
||||
|
||||
companion object {
|
||||
private var seconds: Int = (Math.random() * 59.0).toInt()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putLong("eventTime", eventTime)
|
||||
savedInstanceState.putBoolean("eventTimeChanged", eventTimeChanged)
|
||||
}
|
||||
|
||||
fun onCreateViewGeneral() {
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
eventTime = savedInstanceState?.getLong("eventTime") ?: DateUtil.now()
|
||||
eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false
|
||||
overview_eventdate?.text = DateUtil.dateString(eventTime)
|
||||
overview_eventtime?.text = DateUtil.timeString(eventTime)
|
||||
|
||||
// create an OnDateSetListener
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
cal.set(Calendar.YEAR, year)
|
||||
cal.set(Calendar.MONTH, monthOfYear)
|
||||
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
eventTime = cal.timeInMillis
|
||||
eventTimeChanged = true
|
||||
overview_eventdate?.text = DateUtil.dateString(eventTime)
|
||||
}
|
||||
|
||||
overview_eventdate?.setOnClickListener {
|
||||
context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
DatePickerDialog(it, dateSetListener,
|
||||
cal.get(Calendar.YEAR),
|
||||
cal.get(Calendar.MONTH),
|
||||
cal.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
// create an OnTimeSetListener
|
||||
val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour)
|
||||
cal.set(Calendar.MINUTE, minute)
|
||||
cal.set(Calendar.SECOND, seconds++) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||
eventTime = cal.timeInMillis
|
||||
eventTimeChanged = true
|
||||
overview_eventtime?.text = DateUtil.timeString(eventTime)
|
||||
}
|
||||
|
||||
overview_eventtime?.setOnClickListener {
|
||||
context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
TimePickerDialog(it, timeSetListener,
|
||||
cal.get(Calendar.HOUR_OF_DAY),
|
||||
cal.get(Calendar.MINUTE),
|
||||
DateFormat.is24HourFormat(context)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
notes_layout?.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
|
||||
ok.setOnClickListener {
|
||||
synchronized(okClicked) {
|
||||
if (okClicked) {
|
||||
log.debug("guarding: ok already clicked")
|
||||
} else {
|
||||
okClicked = true
|
||||
if (submit()) dismiss()
|
||||
else okClicked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
abstract fun submit(): Boolean
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.dialogs
|
||||
|
||||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
|
@ -7,11 +6,14 @@ 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 androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.services.AlarmSoundService
|
||||
import kotlinx.android.synthetic.main.overview_error_dialog.*
|
||||
import kotlinx.android.synthetic.main.dialog_error.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class ErrorDialog : DialogFragment() {
|
||||
|
@ -24,20 +26,23 @@ class ErrorDialog : DialogFragment() {
|
|||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
dialog?.setTitle(title)
|
||||
isCancelable = false
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
|
||||
savedInstanceState?.let { bundle ->
|
||||
bundle.getString("status")?.let { status = it }
|
||||
bundle.getString("title")?.let { title = it }
|
||||
sound = bundle.getInt("sound", R.raw.error)
|
||||
}
|
||||
return inflater.inflate(R.layout.overview_error_dialog, container, false)
|
||||
return inflater.inflate(R.layout.dialog_error, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
error_title.text = title
|
||||
overview_error_ok.setOnClickListener {
|
||||
log.debug("Error dialog ok button pressed")
|
||||
dismiss()
|
||||
|
@ -56,9 +61,13 @@ class ErrorDialog : DialogFragment() {
|
|||
bundle.putInt("sound", sound)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
overview_error_status.text = status
|
||||
}
|
||||
|
||||
|
@ -81,5 +90,5 @@ class ErrorDialog : DialogFragment() {
|
|||
}
|
||||
|
||||
private fun stopAlarm() =
|
||||
MainApp.instance().stopService(Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java))
|
||||
MainApp.instance().stopService(Intent(MainApp.instance().applicationContext, AlarmSoundService::class.java))
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import kotlinx.android.synthetic.main.dialog_extendedbolus.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("actions_extendedbolus_insulin", actions_extendedbolus_insulin.value)
|
||||
savedInstanceState.putDouble("actions_extendedbolus_duration", actions_extendedbolus_duration.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_extendedbolus, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
|
||||
val maxInsulin = MainApp.getConstraintChecker().maxExtendedBolusAllowed.value()
|
||||
val extendedStep = pumpDescription.extendedBolusStep
|
||||
actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin")
|
||||
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok)
|
||||
|
||||
val extendedDurationStep = pumpDescription.extendedBolusDurationStep
|
||||
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
|
||||
actions_extendedbolus_duration.setParams(savedInstanceState?.getDouble("actions_extendedbolus_duration")
|
||||
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, ok)
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text)
|
||||
val durationInMinutes = SafeParse.stringToInt(actions_extendedbolus_duration.text)
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(insulin)).value()
|
||||
actions.add(MainApp.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
if (abs(insulinAfterConstraint - insulin) > 0.01)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, null)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import kotlinx.android.synthetic.main.dialog_fill.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class FillDialog : DialogFragmentWithDate() {
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("fill_insulinamount", fill_insulinamount.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_fill, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep
|
||||
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulinamount")
|
||||
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), true, ok)
|
||||
val amount1 = SP.getDouble("fill_button1", 0.3)
|
||||
if (amount1 > 0) {
|
||||
fill_preset_button1.visibility = View.VISIBLE
|
||||
fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1) // + "U");
|
||||
fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 }
|
||||
} else {
|
||||
fill_preset_button1.visibility = View.GONE
|
||||
}
|
||||
val amount2 = SP.getDouble("fill_button2", 0.0)
|
||||
if (amount2 > 0) {
|
||||
fill_preset_button2.visibility = View.VISIBLE
|
||||
fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2) // + "U");
|
||||
fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 }
|
||||
} else {
|
||||
fill_preset_button2.visibility = View.GONE
|
||||
}
|
||||
val amount3 = SP.getDouble("fill_button3", 0.0)
|
||||
if (amount3 > 0) {
|
||||
fill_preset_button3.visibility = View.VISIBLE
|
||||
fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3) // + "U");
|
||||
fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 }
|
||||
} else {
|
||||
fill_preset_button3.visibility = View.GONE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val insulin = SafeParse.stringToDouble(fill_insulinamount.text)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
if (insulinAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.fillwarning))
|
||||
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>")
|
||||
if (abs(insulinAfterConstraints - insulin) > 0.01)
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
}
|
||||
val siteChange = fill_catheter_change.isChecked
|
||||
if (siteChange)
|
||||
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>")
|
||||
val insulinChange = fill_cartridge_change.isChecked
|
||||
if (insulinChange)
|
||||
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>")
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
eventTime -= eventTime % 1000
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (insulinAfterConstraints > 0) {
|
||||
requestPrimeBolus(insulinAfterConstraints, notes)
|
||||
}
|
||||
if (siteChange) {
|
||||
generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes)
|
||||
}
|
||||
if (insulinChange) {
|
||||
// add a second for case of both checked
|
||||
generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
} else {
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.primefill), MainApp.gs(R.string.no_action_selected))
|
||||
}
|
||||
}
|
||||
dismiss()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun requestPrimeBolus(insulin: Double, notes: String) {
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
detailedBolusInfo.insulin = insulin
|
||||
detailedBolusInfo.context = context
|
||||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
|
||||
detailedBolusInfo.notes = notes
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun generateCareportalEvent(eventType: String, time: Long, notes: String) {
|
||||
val careportalEvent = CareportalEvent()
|
||||
careportalEvent.source = Source.USER
|
||||
careportalEvent.date = time
|
||||
careportalEvent.json = generateJson(eventType, time, notes).toString()
|
||||
careportalEvent.eventType = eventType
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent)
|
||||
NSUpload.uploadEvent(eventType, time, notes)
|
||||
}
|
||||
|
||||
private fun generateJson(careportalEvent: String, time: Long, notes: String): JSONObject {
|
||||
val data = JSONObject()
|
||||
try {
|
||||
data.put("eventType", careportalEvent)
|
||||
data.put("created_at", DateUtil.toISOString(time))
|
||||
data.put("mills", time)
|
||||
data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name)))
|
||||
if (notes.isNotEmpty()) data.put("notes", notes)
|
||||
} catch (ignored: JSONException) {
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import kotlinx.android.synthetic.main.dialog_insulin.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
|
||||
class InsulinDialog : DialogFragmentWithDate() {
|
||||
|
||||
companion object {
|
||||
private const val PLUS1_DEFAULT = 0.5
|
||||
private const val PLUS2_DEFAULT = 1.0
|
||||
private const val PLUS3_DEFAULT = 2.0
|
||||
}
|
||||
|
||||
private val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
|
||||
overview_insulin_time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_insulin_amount.value > maxInsulin) {
|
||||
overview_insulin_amount.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_insulin_time", overview_insulin_time.value)
|
||||
savedInstanceState.putDouble("overview_insulin_amount", overview_insulin_amount.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_insulin, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount")
|
||||
?: 0.0, 0.0, maxInsulin, ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
|
||||
|
||||
overview_insulin_plus05.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
overview_insulin_plus05.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus10.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
overview_insulin_plus10.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus20.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||
overview_insulin_plus20.setOnClickListener {
|
||||
overview_insulin_amount.value = Math.max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
overview_insulin_time_layout.visibility = View.GONE
|
||||
overview_insulin_record_only.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
||||
overview_insulin_time_layout.visibility = isChecked.toVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toSignedString(value: Double): String {
|
||||
val formatted = DecimalFormatter.toPumpSupportedBolus(value)
|
||||
return if (value > 0) "+$formatted" else formatted
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
|
||||
?: return false
|
||||
val insulin = SafeParse.stringToDouble(overview_insulin_amount.text)
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
val recordOnlyChecked = overview_insulin_record_only.isChecked
|
||||
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
|
||||
|
||||
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>")
|
||||
if (recordOnlyChecked)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
|
||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
}
|
||||
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
|
||||
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>")
|
||||
|
||||
val timeOffset = overview_insulin_time.value.toInt()
|
||||
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
|
||||
if (timeOffset != 0)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
|
||||
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
if (insulinAfterConstraints > 0 || eatingSoonChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (eatingSoonChecked) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(eatingSoonTTDuration)
|
||||
.reason(MainApp.gs(R.string.eatingsoon))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
if (insulinAfterConstraints > 0) {
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
|
||||
detailedBolusInfo.insulin = insulinAfterConstraints
|
||||
detailedBolusInfo.context = context
|
||||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.notes = notes
|
||||
if (recordOnlyChecked) {
|
||||
detailedBolusInfo.date = time
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
|
||||
} else {
|
||||
detailedBolusInfo.date = DateUtil.now()
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.bolus), MainApp.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import kotlinx.android.synthetic.main.dialog_profileswitch.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
||||
class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_profileswitch_duration", overview_profileswitch_duration.value)
|
||||
savedInstanceState.putDouble("overview_profileswitch_percentage", overview_profileswitch_percentage.value)
|
||||
savedInstanceState.putDouble("overview_profileswitch_timeshift", overview_profileswitch_timeshift.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_profileswitch, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
overview_profileswitch_duration.setParams(savedInstanceState?.getDouble("overview_profileswitch_duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
|
||||
overview_profileswitch_percentage.setParams(savedInstanceState?.getDouble("overview_profileswitch_percentage")
|
||||
?: 100.0, Constants.CPP_MIN_PERCENTAGE.toDouble(), Constants.CPP_MAX_PERCENTAGE.toDouble(), 1.0, DecimalFormat("0"), false, ok)
|
||||
overview_profileswitch_timeshift.setParams(savedInstanceState?.getDouble("overview_profileswitch_timeshift")
|
||||
?: 0.0, Constants.CPP_MIN_TIMESHIFT.toDouble(), Constants.CPP_MAX_TIMESHIFT.toDouble(), 1.0, DecimalFormat("0"), false, ok)
|
||||
|
||||
// profile
|
||||
context?.let { context ->
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
?: return
|
||||
val profileList = profileStore.getProfileList()
|
||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
||||
overview_profileswitch_profile.adapter = adapter
|
||||
// set selected to actual profile
|
||||
for (p in profileList.indices)
|
||||
if (profileList[p] == ProfileFunctions.getInstance().getProfileName(false))
|
||||
overview_profileswitch_profile.setSelection(p)
|
||||
} ?: return
|
||||
|
||||
TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
|
||||
if (ps.isCPP) {
|
||||
overview_profileswitch_reuselayout.visibility = View.VISIBLE
|
||||
overview_profileswitch_reusebutton.text = MainApp.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h"
|
||||
overview_profileswitch_reusebutton.setOnClickListener {
|
||||
overview_profileswitch_percentage.value = ps.percentage.toDouble()
|
||||
overview_profileswitch_timeshift.value = ps.timeshift.toDouble()
|
||||
}
|
||||
} else {
|
||||
overview_profileswitch_reuselayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
?: return false
|
||||
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val duration = overview_profileswitch_duration.value
|
||||
if (duration > 0)
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_hours, duration))
|
||||
val profile = overview_profileswitch_profile.selectedItem.toString()
|
||||
actions.add(MainApp.gs(R.string.profile) + ": " + profile)
|
||||
val percent = overview_profileswitch_percentage.value.toInt()
|
||||
if (percent != 100)
|
||||
actions.add(MainApp.gs(R.string.percent) + ": " + percent + "%")
|
||||
val timeShift = overview_profileswitch_timeshift.value.toInt()
|
||||
if (timeShift != 0)
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + MainApp.gs(R.string.format_hours, timeShift.toDouble()))
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
ProfileFunctions.doProfileSwitch(profileStore, profile, duration.toInt(), percent, timeShift, eventTime)
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,29 +1,34 @@
|
|||
package info.nightscout.androidaps.plugins.treatments.fragments
|
||||
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 androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import kotlinx.android.synthetic.main.close.*
|
||||
import kotlinx.android.synthetic.main.profileviewer_fragment.*
|
||||
import kotlinx.android.synthetic.main.dialog_profileviewer.*
|
||||
import org.json.JSONObject
|
||||
|
||||
class ProfileViewerDialog : DialogFragment() {
|
||||
private var time: Long = 0
|
||||
|
||||
enum class Mode(val i: Int) {
|
||||
RUNNING_PROFILE(1),
|
||||
PUMP_PROFILE(2)
|
||||
CUSTOM_PROFILE(2)
|
||||
}
|
||||
|
||||
private var mode: Mode = Mode.RUNNING_PROFILE;
|
||||
private var mode: Mode = Mode.RUNNING_PROFILE
|
||||
private var customProfileJson: String = ""
|
||||
private var customProfileName: String = ""
|
||||
private var customProfileUnits: String = Constants.MGDL
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
@ -31,19 +36,23 @@ class ProfileViewerDialog : DialogFragment() {
|
|||
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||
time = bundle.getLong("time", 0)
|
||||
mode = Mode.values()[bundle.getInt("mode", Mode.RUNNING_PROFILE.ordinal)]
|
||||
customProfileJson = bundle.getString("customProfile", "")
|
||||
customProfileUnits = bundle.getString("customProfileUnits", Constants.MGDL)
|
||||
customProfileName = bundle.getString("customProfileName", "")
|
||||
}
|
||||
|
||||
return inflater.inflate(R.layout.profileviewer_fragment, container, false)
|
||||
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_profileviewer, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
close.setOnClickListener { dismiss() }
|
||||
profileview_reload.setOnClickListener {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("ProfileViewDialog", null)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
val profile: Profile?
|
||||
val profileName: String?
|
||||
|
@ -53,15 +62,14 @@ class ProfileViewerDialog : DialogFragment() {
|
|||
profile = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.profileObject
|
||||
profileName = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.customizedName
|
||||
date = DateUtil.dateAndTimeString(TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.date
|
||||
?: 0)
|
||||
profileview_reload.visibility = View.GONE
|
||||
?: 0)
|
||||
profileview_datelayout.visibility = View.VISIBLE
|
||||
}
|
||||
Mode.PUMP_PROFILE -> {
|
||||
profile = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profile?.getDefaultProfile()
|
||||
profileName = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profileName
|
||||
|
||||
Mode.CUSTOM_PROFILE -> {
|
||||
profile = Profile(JSONObject(customProfileJson), customProfileUnits)
|
||||
profileName = customProfileName
|
||||
date = ""
|
||||
profileview_reload.visibility = View.VISIBLE
|
||||
profileview_datelayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
@ -83,15 +91,18 @@ class ProfileViewerDialog : DialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
super.onSaveInstanceState(bundle)
|
||||
bundle.putLong("time", time)
|
||||
bundle.putInt("mode", mode.ordinal)
|
||||
bundle.putString("customProfile", customProfileJson)
|
||||
bundle.putString("customProfileName", customProfileName)
|
||||
bundle.putString("customProfileUnits", customProfileUnits)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import kotlinx.android.synthetic.main.dialog_tempbasal.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class TempBasalDialog : DialogFragmentWithDate() {
|
||||
private var isPercentPump = true
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("actions_tempbasal_duration", actions_tempbasal_duration.value)
|
||||
savedInstanceState.putDouble("actions_tempbasal_basalpercentinput", actions_tempbasal_basalpercentinput.value)
|
||||
savedInstanceState.putDouble("actions_tempbasal_basalabsoluteinput", actions_tempbasal_basalabsoluteinput.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_tempbasal, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
val profile = ProfileFunctions.getInstance().profile ?: return
|
||||
|
||||
val maxTempPercent = pumpDescription.maxTempPercent.toDouble()
|
||||
val tempPercentStep = pumpDescription.tempPercentStep.toDouble()
|
||||
|
||||
actions_tempbasal_basalpercentinput.setParams(savedInstanceState?.getDouble("actions_tempbasal_basalpercentinput")
|
||||
?: 100.0, 0.0, maxTempPercent, tempPercentStep, DecimalFormat("0"), true, ok)
|
||||
|
||||
actions_tempbasal_basalabsoluteinput.setParams(savedInstanceState?.getDouble("actions_tempbasal_basalabsoluteinput")
|
||||
?: profile.basal, 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, ok)
|
||||
|
||||
val tempDurationStep = pumpDescription.tempDurationStep.toDouble()
|
||||
val tempMaxDuration = pumpDescription.tempMaxDuration.toDouble()
|
||||
actions_tempbasal_duration.setParams(savedInstanceState?.getDouble("actions_tempbasal_duration")
|
||||
?: tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, DecimalFormat("0"), false, ok)
|
||||
|
||||
isPercentPump = pumpDescription.tempBasalStyle and PumpDescription.PERCENT == PumpDescription.PERCENT
|
||||
if (isPercentPump) {
|
||||
actions_tempbasal_percent_layout.visibility = View.VISIBLE
|
||||
actions_tempbasal_absolute_layout.visibility = View.GONE
|
||||
} else {
|
||||
actions_tempbasal_percent_layout.visibility = View.GONE
|
||||
actions_tempbasal_absolute_layout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
var percent = 0
|
||||
var absolute = 0.0
|
||||
val durationInMinutes = SafeParse.stringToInt(actions_tempbasal_duration.text)
|
||||
val profile = ProfileFunctions.getInstance().profile ?: return false
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
if (isPercentPump) {
|
||||
val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text)
|
||||
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
|
||||
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": $percent%")
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
if (percent != basalPercentInput) actions.add(MainApp.gs(R.string.constraintapllied))
|
||||
} else {
|
||||
val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text)
|
||||
absolute = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
|
||||
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": " + MainApp.gs(R.string.pump_basebasalrate, absolute))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
if (abs(absolute - basalAbsoluteInput) > 0.01)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
|
||||
}
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.pump_tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val callback: Callback = object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPercentPump) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
|
||||
} else {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import com.google.common.base.Joiner
|
||||
import com.google.common.collect.Lists
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import kotlinx.android.synthetic.main.dialog_temptarget.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
||||
class TempTargetDialog : DialogFragmentWithDate() {
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_temptarget_duration", overview_temptarget_duration.value)
|
||||
savedInstanceState.putDouble("overview_temptarget_temptarget", overview_temptarget_temptarget.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_temptarget, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
overview_temptarget_duration.setParams(savedInstanceState?.getDouble("overview_temptarget_duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
|
||||
|
||||
if (ProfileFunctions.getSystemUnits() == Constants.MMOL)
|
||||
overview_temptarget_temptarget.setParams(
|
||||
savedInstanceState?.getDouble("overview_temptarget_temptarget")
|
||||
?: Constants.MIN_TT_MMOL,
|
||||
Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1, DecimalFormat("0.0"), false, ok)
|
||||
else
|
||||
overview_temptarget_temptarget.setParams(
|
||||
savedInstanceState?.getDouble("overview_temptarget_temptarget")
|
||||
?: Constants.MIN_TT_MGDL,
|
||||
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, ok)
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
overview_temptarget_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
// temp target
|
||||
context?.let { context ->
|
||||
val reasonList: List<String> = Lists.newArrayList(
|
||||
MainApp.gs(R.string.manual),
|
||||
MainApp.gs(R.string.cancel),
|
||||
MainApp.gs(R.string.eatingsoon),
|
||||
MainApp.gs(R.string.activity),
|
||||
MainApp.gs(R.string.hypo)
|
||||
)
|
||||
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
|
||||
overview_temptarget_reason.adapter = adapterReason
|
||||
overview_temptarget_reason.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||
val defaultDuration: Double
|
||||
val defaultTarget: Double
|
||||
when (reasonList[position]) {
|
||||
MainApp.gs(R.string.eatingsoon) -> {
|
||||
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineEatingSoonTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.activity) -> {
|
||||
defaultDuration = DefaultValueHelper.determineActivityTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineActivityTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.hypo) -> {
|
||||
defaultDuration = DefaultValueHelper.determineHypoTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineHypoTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.cancel) -> {
|
||||
defaultDuration = 0.0
|
||||
defaultTarget = 0.0
|
||||
}
|
||||
|
||||
else -> {
|
||||
defaultDuration = overview_temptarget_duration.value
|
||||
defaultTarget = overview_temptarget_temptarget.value
|
||||
}
|
||||
}
|
||||
overview_temptarget_temptarget.value = defaultTarget
|
||||
overview_temptarget_duration.value = defaultDuration
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val reason = overview_temptarget_reason.selectedItem.toString()
|
||||
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
val target = overview_temptarget_temptarget.value
|
||||
val duration = overview_temptarget_duration.value
|
||||
if (target != 0.0 && duration != 0.0) {
|
||||
actions.add(MainApp.gs(R.string.reason) + ": " + reason)
|
||||
actions.add(MainApp.gs(R.string.nsprofileview_target_label) + ": " + Profile.toCurrentUnitsString(target) + " " + MainApp.gs(unitResId))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_hours, duration))
|
||||
} else {
|
||||
actions.add(MainApp.gs(R.string.stoptemptarget))
|
||||
}
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (target == 0.0 || duration == 0.0) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(0)
|
||||
.low(0.0).high(0.0)
|
||||
.source(Source.USER)
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
} else {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(duration.toInt())
|
||||
.reason(reason)
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
if (duration == 10.0) SP.putBoolean(R.string.key_objectiveusetemptarget, true)
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import kotlinx.android.synthetic.main.dialog_treatment.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class TreatmentDialog : DialogFragmentWithDate() {
|
||||
private var maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
|
||||
private var maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
validateInputs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) {
|
||||
overview_treatment_carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) {
|
||||
overview_treatment_insulin.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_treatment_carbs", overview_treatment_carbs.value)
|
||||
savedInstanceState.putDouble("overview_treatment_insulin", overview_treatment_insulin.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_treatment, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
overview_treatment_insulin.setParams(savedInstanceState?.getDouble("overview_treatment_insulin")
|
||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
|
||||
?: return false
|
||||
val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text)
|
||||
val carbs = SafeParse.stringToInt(overview_treatment_carbs.text)
|
||||
val recordOnlyChecked = overview_treatment_record_only.isChecked
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
|
||||
|
||||
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>")
|
||||
if (recordOnlyChecked)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
|
||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
}
|
||||
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>")
|
||||
if (carbsAfterConstraints != carbs)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
}
|
||||
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION
|
||||
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
|
||||
detailedBolusInfo.insulin = insulinAfterConstraints
|
||||
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
|
||||
detailedBolusInfo.context = context
|
||||
detailedBolusInfo.source = Source.USER
|
||||
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
|
||||
})
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.overview_treatment_label), MainApp.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.general.overview.dialogs
|
||||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AdapterView.OnItemSelectedListener
|
||||
import android.widget.ArrayAdapter
|
||||
|
@ -26,7 +29,7 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
|||
import info.nightscout.androidaps.utils.*
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.overview_wizard_dialog.*
|
||||
import kotlinx.android.synthetic.main.dialog_wizard.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
@ -36,16 +39,13 @@ class WizardDialog : DialogFragment() {
|
|||
private val log = LoggerFactory.getLogger(WizardDialog::class.java)
|
||||
|
||||
private var wizard: BolusWizard? = null
|
||||
private var parentContext: Context? = null
|
||||
|
||||
//one shot guards
|
||||
private var okClicked: Boolean = false
|
||||
|
||||
private val textWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
calculateInsulin()
|
||||
}
|
||||
|
@ -53,21 +53,11 @@ class WizardDialog : DialogFragment() {
|
|||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
this.parentContext = context
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
super.onDetach()
|
||||
this.parentContext = null
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("treatments_wizard_bg_input", treatments_wizard_bg_input.value)
|
||||
|
@ -83,28 +73,28 @@ class WizardDialog : DialogFragment() {
|
|||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
|
||||
return inflater.inflate(R.layout.overview_wizard_dialog, container, false)
|
||||
return inflater.inflate(R.layout.dialog_wizard, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
loadCheckedStates()
|
||||
processCobCheckBox()
|
||||
treatments_wizard_sbcheckbox.visibility = if (SP.getBoolean(R.string.key_usesuperbolus, false)) View.VISIBLE else View.GONE
|
||||
treatments_wizard_notes_layout.visibility = if (SP.getBoolean(R.string.key_show_notes_entry_dialogs, false)) View.VISIBLE else View.GONE
|
||||
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()
|
||||
|
||||
val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value()
|
||||
val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
|
||||
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")
|
||||
?: 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
|
||||
?: 0.1
|
||||
?: 0.1
|
||||
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(), false, ok, textWatcher)
|
||||
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()
|
||||
|
||||
treatments_wizard_percent_used.text = MainApp.gs(R.string.format_percent, SP.getInt(R.string.key_boluswizard_percentage, 100))
|
||||
|
@ -115,7 +105,7 @@ class WizardDialog : DialogFragment() {
|
|||
} else {
|
||||
okClicked = true
|
||||
calculateInsulin()
|
||||
parentContext?.let { context ->
|
||||
context?.let { context ->
|
||||
wizard?.confirmAndExecute(context)
|
||||
}
|
||||
}
|
||||
|
@ -124,23 +114,23 @@ class WizardDialog : DialogFragment() {
|
|||
// cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
// checkboxes
|
||||
treatments_wizard_bgcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_ttcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_cobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_sbcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
|
||||
treatments_wizard_bgcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_ttcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_cobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
|
||||
val showCalc = SP.getBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), false)
|
||||
treatments_wizard_delimiter.visibility = if (showCalc) View.VISIBLE else View.GONE
|
||||
treatments_wizard_resulttable.visibility = if (showCalc) View.VISIBLE else View.GONE
|
||||
treatments_wizard_delimiter.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_calculationcheckbox.isChecked = showCalc
|
||||
treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
run {
|
||||
SP.putBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), isChecked)
|
||||
treatments_wizard_delimiter.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||
treatments_wizard_resulttable.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||
treatments_wizard_delimiter.visibility = isChecked.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = isChecked.toVisibility()
|
||||
}
|
||||
}
|
||||
// profile spinner
|
||||
|
@ -157,13 +147,13 @@ class WizardDialog : DialogFragment() {
|
|||
}
|
||||
// bus
|
||||
disposable.add(RxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
activity?.runOnUiThread { calculateInsulin() }
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
activity?.runOnUiThread { calculateInsulin() }
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -173,7 +163,7 @@ class WizardDialog : DialogFragment() {
|
|||
disposable.clear()
|
||||
}
|
||||
|
||||
private fun onCheckedChanged(buttonView: CompoundButton) {
|
||||
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
|
||||
saveCheckedStates()
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
|
||||
if (buttonView.id == treatments_wizard_cobcheckbox.id)
|
||||
|
@ -221,7 +211,6 @@ class WizardDialog : DialogFragment() {
|
|||
treatments_wizard_profile.adapter = adapter
|
||||
} ?: return
|
||||
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
treatments_wizard_bgunits.text = units
|
||||
if (units == Constants.MGDL)
|
||||
|
@ -250,7 +239,7 @@ class WizardDialog : DialogFragment() {
|
|||
|
||||
calculateInsulin()
|
||||
|
||||
treatments_wizard_percent_used.visibility = if (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100) View.VISIBLE else View.GONE
|
||||
treatments_wizard_percent_used.visibility = (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
|
||||
}
|
||||
|
||||
private fun calculateInsulin() {
|
||||
|
@ -291,15 +280,15 @@ class WizardDialog : DialogFragment() {
|
|||
val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text)
|
||||
|
||||
wizard = BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
|
||||
SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
|
||||
treatments_wizard_bgcheckbox.isChecked,
|
||||
treatments_wizard_cobcheckbox.isChecked,
|
||||
treatments_wizard_bolusiobcheckbox.isChecked,
|
||||
treatments_wizard_basaliobcheckbox.isChecked,
|
||||
treatments_wizard_sbcheckbox.isChecked,
|
||||
treatments_wizard_ttcheckbox.isChecked,
|
||||
treatments_wizard_bgtrendcheckbox.isChecked,
|
||||
treatment_wizard_notes.text.toString(), carbTime)
|
||||
SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
|
||||
treatments_wizard_bgcheckbox.isChecked,
|
||||
treatments_wizard_cobcheckbox.isChecked,
|
||||
treatments_wizard_bolusiobcheckbox.isChecked,
|
||||
treatments_wizard_basaliobcheckbox.isChecked,
|
||||
treatments_wizard_sbcheckbox.isChecked,
|
||||
treatments_wizard_ttcheckbox.isChecked,
|
||||
treatments_wizard_bgtrendcheckbox.isChecked,
|
||||
treatment_wizard_notes.text.toString(), carbTime)
|
||||
|
||||
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)
|
||||
|
@ -320,8 +309,8 @@ class WizardDialog : DialogFragment() {
|
|||
// Trend
|
||||
if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
|
||||
treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "")
|
||||
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, ProfileFunctions.getSystemUnits())
|
||||
+ " " + ProfileFunctions.getSystemUnits())
|
||||
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, ProfileFunctions.getSystemUnits())
|
||||
+ " " + ProfileFunctions.getSystemUnits())
|
||||
} else {
|
||||
treatments_wizard_bgtrend.text = ""
|
||||
}
|
|
@ -4,7 +4,6 @@ import android.os.SystemClock;
|
|||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -20,6 +19,7 @@ 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;
|
||||
|
||||
/**
|
||||
|
@ -58,20 +58,16 @@ public abstract class PluginBase {
|
|||
if (allowHardwarePump || activity == null) {
|
||||
performPluginSwitch(newState, type);
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.allow_hardware_pump_text)
|
||||
.setPositiveButton(R.string.yes, (dialog, id) -> {
|
||||
performPluginSwitch(newState, type);
|
||||
SP.putBoolean("allow_hardware_pump", true);
|
||||
if (L.isEnabled(L.PUMP))
|
||||
log.debug("First time HW pump allowed!");
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, (dialog, id) -> {
|
||||
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
|
||||
if (L.isEnabled(L.PUMP))
|
||||
log.debug("User does not allow switching to HW pump!");
|
||||
});
|
||||
builder.create().show();
|
||||
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);
|
||||
|
|
|
@ -29,8 +29,8 @@ public class PluginDescription {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription alwaysVisible(boolean alwayVisible) {
|
||||
this.alwaysVisible = alwayVisible;
|
||||
public PluginDescription alwaysVisible(boolean alwaysVisible) {
|
||||
this.alwaysVisible = alwaysVisible;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public interface TreatmentsInterface {
|
|||
MealData getMealData();
|
||||
|
||||
List<Treatment> getTreatmentsFromHistory();
|
||||
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
||||
List<Treatment> getCarbTreatments5MinBackFromHistory(long time);
|
||||
List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp);
|
||||
long getLastBolusTime();
|
||||
|
||||
|
|
|
@ -381,13 +381,11 @@ public class DeviceStatus {
|
|||
try {
|
||||
if (device != null) record.put("device", device);
|
||||
if (pump != null) record.put("pump", pump);
|
||||
if (suggested != null) {
|
||||
JSONObject openaps = new JSONObject();
|
||||
if (enacted != null) openaps.put("enacted", enacted);
|
||||
if (suggested != null) openaps.put("suggested", suggested);
|
||||
if (iob != null) openaps.put("iob", iob);
|
||||
record.put("openaps", openaps);
|
||||
}
|
||||
JSONObject openaps = new JSONObject();
|
||||
if (enacted != null) openaps.put("enacted", enacted);
|
||||
if (suggested != null) openaps.put("suggested", suggested);
|
||||
if (iob != null) openaps.put("iob", iob);
|
||||
record.put("openaps", openaps);
|
||||
if (uploaderBattery != 0) record.put("uploaderBattery", uploaderBattery);
|
||||
if (created_at != null) record.put("created_at", created_at);
|
||||
} catch (JSONException e) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop
|
||||
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -12,7 +11,11 @@ import info.nightscout.androidaps.interfaces.Constraint
|
|||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.plusAssign
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.loop_fragment.*
|
||||
|
@ -39,23 +42,21 @@ class LoopFragment : Fragment() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
disposable += RxBus
|
||||
.toObservable(EventLoopUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGUI()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.toObservable(EventLoopUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGUI()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
|
||||
disposable += RxBus
|
||||
.toObservable(EventLoopSetLastRunGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
clearGUI()
|
||||
loop_lastrun.text = it.text
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.toObservable(EventLoopSetLastRunGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
clearGUI()
|
||||
loop_lastrun?.text = it.text
|
||||
}, { FabricPrivacy.logException(it) })
|
||||
|
||||
updateGUI()
|
||||
SP.putBoolean(R.string.key_objectiveuseloop, true)
|
||||
|
@ -71,39 +72,38 @@ class LoopFragment : Fragment() {
|
|||
fun updateGUI() {
|
||||
if (loop_request == null) return
|
||||
LoopPlugin.lastRun?.let {
|
||||
loop_request.text = it.request?.toSpanned() ?: ""
|
||||
loop_constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: ""
|
||||
loop_source.text = it.source ?: ""
|
||||
loop_lastrun.text = it.lastAPSRun?.let { lastRun -> DateUtil.dateAndTimeString(lastRun.time) }
|
||||
?: ""
|
||||
loop_lastenact.text = it.lastAPSRun?.let { lastEnact -> DateUtil.dateAndTimeString(lastEnact.time) }
|
||||
?: ""
|
||||
loop_tbrsetbypump.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) }
|
||||
?: ""
|
||||
loop_smbsetbypump.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) }
|
||||
?: ""
|
||||
loop_request?.text = it.request?.toSpanned() ?: ""
|
||||
loop_constraintsprocessed?.text = it.constraintsProcessed?.toSpanned() ?: ""
|
||||
loop_source?.text = it.source ?: ""
|
||||
loop_lastrun?.text = it.lastAPSRun?.let { lastRun -> DateUtil.dateAndTimeString(lastRun.time) }
|
||||
?: ""
|
||||
loop_lastenact?.text = it.lastAPSRun?.let { lastEnact -> DateUtil.dateAndTimeString(lastEnact.time) }
|
||||
?: ""
|
||||
loop_tbrsetbypump?.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) }
|
||||
?: ""
|
||||
loop_smbsetbypump?.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) }
|
||||
?: ""
|
||||
|
||||
val constraints =
|
||||
it.constraintsProcessed?.let { constraintsProcessed ->
|
||||
val allConstraints = Constraint(0.0)
|
||||
constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) }
|
||||
constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) }
|
||||
allConstraints.mostLimitedReasons
|
||||
} ?: ""
|
||||
loop_constraints.text = constraints
|
||||
it.constraintsProcessed?.let { constraintsProcessed ->
|
||||
val allConstraints = Constraint(0.0)
|
||||
constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) }
|
||||
constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) }
|
||||
allConstraints.mostLimitedReasons
|
||||
} ?: ""
|
||||
loop_constraints?.text = constraints
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun clearGUI() {
|
||||
if (loop_request == null) return
|
||||
loop_request.text = ""
|
||||
loop_constraints.text = ""
|
||||
loop_constraintsprocessed.text = ""
|
||||
loop_source.text = ""
|
||||
loop_lastrun.text = ""
|
||||
loop_lastenact.text = ""
|
||||
loop_tbrsetbypump.text = ""
|
||||
loop_smbsetbypump.text = ""
|
||||
loop_request?.text = ""
|
||||
loop_constraints?.text = ""
|
||||
loop_constraintsprocessed?.text = ""
|
||||
loop_source?.text = ""
|
||||
loop_lastrun?.text = ""
|
||||
loop_lastenact?.text = ""
|
||||
loop_tbrsetbypump?.text = ""
|
||||
loop_smbsetbypump?.text = ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus;
|
|||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
|
@ -60,7 +60,6 @@ import info.nightscout.androidaps.queue.commands.Command;
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import info.nightscout.androidaps.utils.ToastUtils;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@ package info.nightscout.androidaps.plugins.configBuilder
|
|||
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import android.widget.CheckBox
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||
|
@ -10,6 +14,7 @@ import info.nightscout.androidaps.interfaces.PluginBase
|
|||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.utils.PasswordProtection
|
||||
import info.nightscout.androidaps.utils.toVisibility
|
||||
|
||||
class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment,
|
||||
private val pluginType: PluginType,
|
||||
|
@ -56,8 +61,8 @@ class PluginViewHolder internal constructor(private val fragment: ConfigBuilderF
|
|||
}
|
||||
|
||||
fun update() {
|
||||
enabledExclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.GONE else View.VISIBLE
|
||||
enabledInclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.VISIBLE else View.GONE
|
||||
enabledExclusive.visibility = areMultipleSelectionsAllowed(pluginType).not().toVisibility()
|
||||
enabledInclusive.visibility = areMultipleSelectionsAllowed(pluginType).toVisibility()
|
||||
enabledExclusive.isChecked = plugin.isEnabled(pluginType)
|
||||
enabledInclusive.isChecked = plugin.isEnabled(pluginType)
|
||||
enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
|
||||
|
@ -70,7 +75,7 @@ class PluginViewHolder internal constructor(private val fragment: ConfigBuilderF
|
|||
pluginDescription.text = plugin.description
|
||||
}
|
||||
pluginPreferences.visibility = if (plugin.preferencesId == -1 || !plugin.isEnabled(pluginType)) View.INVISIBLE else View.VISIBLE
|
||||
pluginVisibility.visibility = if (plugin.hasFragment()) View.VISIBLE else View.INVISIBLE
|
||||
pluginVisibility.visibility = plugin.hasFragment().toVisibility()
|
||||
pluginVisibility.isEnabled = !(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwaysVisible) && plugin.isEnabled(pluginType)
|
||||
pluginVisibility.isChecked = plugin.isFragmentVisible
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
|
@ -170,8 +170,8 @@ public class ProfileFunctions {
|
|||
return profileSwitch;
|
||||
}
|
||||
|
||||
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
|
||||
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis());
|
||||
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift, final long date) {
|
||||
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, date);
|
||||
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
|
||||
if (percentage == 90 && duration == 10)
|
||||
SP.putBoolean(R.string.key_objectiveuseprofileswitch, true);
|
||||
|
|
|
@ -28,6 +28,7 @@ import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtp
|
|||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask
|
||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
||||
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
@ -71,13 +72,13 @@ class ObjectivesFragment : Fragment() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
disposable.add(RxBus
|
||||
.toObservable(EventObjectivesUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
objectives_recyclerview.adapter?.notifyDataSetChanged()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.toObservable(EventObjectivesUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
objectives_recyclerview.adapter?.notifyDataSetChanged()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -217,6 +218,7 @@ class ObjectivesFragment : Fragment() {
|
|||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
} else {
|
||||
// move out of UI thread
|
||||
Thread {
|
||||
|
@ -234,6 +236,7 @@ class ObjectivesFragment : Fragment() {
|
|||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100))
|
||||
SystemClock.sleep(1000)
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
SystemClock.sleep(100)
|
||||
scrollToCurrentObjective()
|
||||
} else {
|
||||
|
@ -254,6 +257,7 @@ class ObjectivesFragment : Fragment() {
|
|||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
} else
|
||||
// move out of UI thread
|
||||
Thread {
|
||||
|
@ -270,6 +274,7 @@ class ObjectivesFragment : Fragment() {
|
|||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100))
|
||||
SystemClock.sleep(1000)
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
SystemClock.sleep(100)
|
||||
scrollToCurrentObjective()
|
||||
} else {
|
||||
|
@ -280,16 +285,20 @@ class ObjectivesFragment : Fragment() {
|
|||
}.start()
|
||||
}
|
||||
holder.unStart.setOnClickListener {
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.doyouwantresetstart)) {
|
||||
objective.startedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.doyouwantresetstart), Runnable {
|
||||
objective.startedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
})
|
||||
}
|
||||
}
|
||||
holder.unFinish.setOnClickListener {
|
||||
objective.accomplishedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
RxBus.send(EventSWUpdate(false))
|
||||
}
|
||||
if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted && objective.specialActionEnabled()) {
|
||||
// generate random request code if none exists
|
||||
|
@ -313,7 +322,6 @@ class ObjectivesFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return ObjectivesPlugin.objectives.size
|
||||
}
|
||||
|
|
|
@ -122,9 +122,9 @@ object ObjectivesPlugin : PluginBase(PluginDescription()
|
|||
SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now())
|
||||
SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now())
|
||||
setupObjectives()
|
||||
OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null)
|
||||
OKDialog.show(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.codeaccepted))
|
||||
} else {
|
||||
OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null)
|
||||
OKDialog.show(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.codeinvalid))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtp
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.overview_bolusprogress_dialog.*
|
||||
import kotlinx.android.synthetic.main.dialog_bolusprogress.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class NtpProgressDialog : DialogFragment() {
|
||||
|
@ -33,16 +33,17 @@ class NtpProgressDialog : DialogFragment() {
|
|||
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
|
||||
percent = savedInstanceState?.getInt("percent", 0) ?: 0
|
||||
|
||||
return inflater.inflate(R.layout.overview_bolusprogress_dialog, container, false)
|
||||
return inflater.inflate(R.layout.dialog_bolusprogress, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
overview_bolusprogress_stop.setOnClickListener { dismiss() }
|
||||
overview_bolusprogress_status.setText(state)
|
||||
overview_bolusprogress_progressbar.setMax(100)
|
||||
overview_bolusprogress_progressbar.setProgress(percent)
|
||||
overview_bolusprogress_status.text = state
|
||||
overview_bolusprogress_progressbar.max = 100
|
||||
overview_bolusprogress_progressbar.progress = percent
|
||||
overview_bolusprogress_stop.text = MainApp.gs(R.string.close)
|
||||
overview_bolusprogress_title.text = MainApp.gs(R.string.please_wait)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.phoneChecker
|
||||
|
||||
import android.os.Build
|
||||
import com.scottyab.rootbeer.RootBeer
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
|
||||
object PhoneCheckerPlugin : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.pluginName(R.string.phonechecker)
|
||||
), ConstraintsInterface {
|
||||
|
||||
var phoneRooted: Boolean = false
|
||||
var devMode: Boolean = false
|
||||
val phoneModel: String = Build.MODEL
|
||||
val manufacturer: String = Build.MANUFACTURER
|
||||
|
||||
private fun isDevModeEnabled(): Boolean {
|
||||
return android.provider.Settings.Secure.getInt(MainApp.instance().contentResolver,
|
||||
android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
phoneRooted = RootBeer(MainApp.instance()).isRootedWithoutBusyBoxCheck()
|
||||
devMode = isDevModeEnabled()
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
|||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.HardLimits;
|
||||
import info.nightscout.androidaps.utils.Round;
|
||||
|
@ -73,7 +74,10 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
|||
}
|
||||
value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this);
|
||||
}
|
||||
|
||||
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
if (pump != null && !pump.isFakingTempsByExtendedBoluses() && TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
|
||||
value.set(false, MainApp.gs(R.string.closed_loop_disabled_with_eb), this);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.versionChecker
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Usually we would have a class here.
|
||||
|
@ -16,16 +22,23 @@ import java.util.concurrent.TimeUnit
|
|||
* */
|
||||
|
||||
object VersionCheckerPlugin : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.pluginName(R.string.versionChecker)), ConstraintsInterface {
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.pluginName(R.string.versionChecker)), ConstraintsInterface {
|
||||
|
||||
private val gracePeriod: GracePeriod
|
||||
get() = if ((BuildConfig.VERSION_NAME.contains("RC", ignoreCase = true))) {
|
||||
GracePeriod.RC
|
||||
} else {
|
||||
GracePeriod.RELEASE
|
||||
}
|
||||
|
||||
override fun isClosedLoopAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||
checkWarning()
|
||||
triggerCheckVersion()
|
||||
return if (isOldVersion(GRACE_PERIOD_VERY_OLD))
|
||||
return if (isOldVersion(gracePeriod.veryOld.daysToMillis()))
|
||||
value.set(false, MainApp.gs(R.string.very_old_version), this)
|
||||
else
|
||||
value
|
||||
|
@ -40,34 +53,42 @@ object VersionCheckerPlugin : PluginBase(PluginDescription()
|
|||
}
|
||||
|
||||
|
||||
if (isOldVersion(GRACE_PERIOD_WARNING) && shouldWarnAgain(now)) {
|
||||
if (isOldVersion(gracePeriod.warning.daysToMillis()) && shouldWarnAgain(now)) {
|
||||
// store last notification time
|
||||
SP.putLong(R.string.key_last_versionchecker_plugin_warning, now)
|
||||
|
||||
//notify
|
||||
val message = MainApp.gs(R.string.new_version_warning, Math.round((now - SP.getLong(R.string.key_last_time_this_version_detected, now)) / TimeUnit.DAYS.toMillis(1).toDouble()))
|
||||
val message = MainApp.gs(R.string.new_version_warning,
|
||||
((now - SP.getLong(R.string.key_last_time_this_version_detected, now)) / 1L.daysToMillis().toDouble()).roundToInt(),
|
||||
gracePeriod.old,
|
||||
gracePeriod.veryOld
|
||||
)
|
||||
val notification = Notification(Notification.OLDVERSION, message, Notification.NORMAL)
|
||||
RxBus.send(EventNewNotification(notification))
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldWarnAgain(now: Long) =
|
||||
now > SP.getLong(R.string.key_last_versionchecker_plugin_warning, 0) + WARN_EVERY
|
||||
now > SP.getLong(R.string.key_last_versionchecker_plugin_warning, 0) + WARN_EVERY
|
||||
|
||||
override fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> =
|
||||
if (isOldVersion(GRACE_PERIOD_OLD))
|
||||
maxIob.set(0.toDouble(), MainApp.gs(R.string.old_version), this)
|
||||
else
|
||||
maxIob
|
||||
if (isOldVersion(gracePeriod.old.daysToMillis()))
|
||||
maxIob.set(0.toDouble(), MainApp.gs(R.string.old_version), this)
|
||||
else
|
||||
maxIob
|
||||
|
||||
private fun isOldVersion(gracePeriod: Long): Boolean {
|
||||
val now = System.currentTimeMillis()
|
||||
return now > SP.getLong(R.string.key_last_time_this_version_detected, 0) + gracePeriod
|
||||
return now > SP.getLong(R.string.key_last_time_this_version_detected, 0) + gracePeriod
|
||||
}
|
||||
|
||||
val WARN_EVERY = TimeUnit.DAYS.toMillis(1)
|
||||
val GRACE_PERIOD_WARNING = TimeUnit.DAYS.toMillis(30)
|
||||
val GRACE_PERIOD_OLD = TimeUnit.DAYS.toMillis(60)
|
||||
val GRACE_PERIOD_VERY_OLD = TimeUnit.DAYS.toMillis(90)
|
||||
private val WARN_EVERY = TimeUnit.DAYS.toMillis(1)
|
||||
|
||||
}
|
||||
|
||||
enum class GracePeriod(val warning: Long, val old: Long, val veryOld: Long) {
|
||||
RELEASE(30, 60, 90),
|
||||
RC(1, 7, 14)
|
||||
}
|
||||
|
||||
private fun Long.daysToMillis() = TimeUnit.DAYS.toMillis(this)
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.MainApp
|
||||
|
@ -18,17 +19,21 @@ import info.nightscout.androidaps.plugins.bus.RxBus
|
|||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
|
||||
import info.nightscout.androidaps.plugins.general.actions.dialogs.FillDialog
|
||||
import info.nightscout.androidaps.plugins.general.actions.dialogs.NewExtendedBolusDialog
|
||||
import info.nightscout.androidaps.plugins.general.actions.dialogs.NewTempBasalDialog
|
||||
import info.nightscout.androidaps.dialogs.CareDialog
|
||||
import info.nightscout.androidaps.dialogs.ExtendedBolusDialog
|
||||
import info.nightscout.androidaps.dialogs.FillDialog
|
||||
import info.nightscout.androidaps.dialogs.TempBasalDialog
|
||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment
|
||||
import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
|
||||
import info.nightscout.androidaps.dialogs.TempTargetDialog
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.actions_fragment.*
|
||||
import kotlinx.android.synthetic.main.careportal_stats_fragment.*
|
||||
import java.util.*
|
||||
|
||||
class ActionsFragment : Fragment() {
|
||||
|
@ -47,39 +52,50 @@ class ActionsFragment : Fragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
actions_profileswitch.setOnClickListener {
|
||||
val newDialog = NewNSTreatmentDialog()
|
||||
val profileSwitch = CareportalFragment.PROFILESWITCH
|
||||
profileSwitch.executeProfileSwitch = true
|
||||
newDialog.setOptions(profileSwitch, R.string.careportal_profileswitch)
|
||||
fragmentManager?.let { newDialog.show(it, "NewNSTreatmentDialog") }
|
||||
fragmentManager?.let { ProfileSwitchDialog().show(it, "Actions") }
|
||||
}
|
||||
actions_temptarget.setOnClickListener {
|
||||
val newTTDialog = NewNSTreatmentDialog()
|
||||
val temptarget = CareportalFragment.TEMPTARGET
|
||||
temptarget.executeTempTarget = true
|
||||
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget)
|
||||
fragmentManager?.let { newTTDialog.show(it, "NewNSTreatmentDialog") }
|
||||
fragmentManager?.let { TempTargetDialog().show(it, "Actions") }
|
||||
}
|
||||
actions_extendedbolus.setOnClickListener {
|
||||
fragmentManager?.let { NewExtendedBolusDialog().show(it, "NewExtendedDialog") }
|
||||
context?.let { context ->
|
||||
OKDialog.showConfirmation(context, MainApp.gs(R.string.extended_bolus), MainApp.gs(R.string.ebstopsloop),
|
||||
Runnable {
|
||||
fragmentManager?.let { ExtendedBolusDialog().show(it, "Actions") }
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
actions_extendedbolus_cancel.setOnClickListener {
|
||||
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.cancelExtended(object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success)
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.extendedbolusdeliveryerror))
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.extendedbolusdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
actions_settempbasal.setOnClickListener { fragmentManager?.let { NewTempBasalDialog().show(it, "NewTempDialog") } }
|
||||
actions_settempbasal.setOnClickListener {
|
||||
fragmentManager?.let { TempBasalDialog().show(it, "Actions") }
|
||||
}
|
||||
actions_canceltempbasal.setOnClickListener {
|
||||
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success)
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.tempbasaldeliveryerror))
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -87,6 +103,21 @@ class ActionsFragment : Fragment() {
|
|||
actions_fill.setOnClickListener { fragmentManager?.let { FillDialog().show(it, "FillDialog") } }
|
||||
actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
|
||||
actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
|
||||
actions_bgcheck.setOnClickListener {
|
||||
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(it, "Actions") }
|
||||
}
|
||||
actions_cgmsensorinsert.setOnClickListener {
|
||||
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(it, "Actions") }
|
||||
}
|
||||
actions_pumpbatterychange.setOnClickListener {
|
||||
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(it, "Actions") }
|
||||
}
|
||||
actions_note.setOnClickListener {
|
||||
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.NOTE, R.string.careportal_note).show(it, "Actions") }
|
||||
}
|
||||
actions_exercise.setOnClickListener {
|
||||
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.EXERCISE, R.string.careportal_exercise).show(it, "Actions") }
|
||||
}
|
||||
|
||||
SP.putBoolean(R.string.key_objectiveuseactions, true)
|
||||
}
|
||||
|
@ -97,43 +128,27 @@ class ActionsFragment : Fragment() {
|
|||
disposable += RxBus
|
||||
.toObservable(EventInitializationChanged::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGui()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
disposable += RxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGui()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
disposable += RxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGui()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
disposable += RxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGui()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
disposable += RxBus
|
||||
.toObservable(EventCustomActionsChanged::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
updateGui()
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
disposable += RxBus
|
||||
.toObservable(EventCareportalEventChange::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
|
||||
updateGui()
|
||||
}
|
||||
|
||||
|
@ -164,7 +179,7 @@ class ActionsFragment : Fragment() {
|
|||
|
||||
actions_profileswitch?.visibility = if (!basalProfileEnabled || !pump.isInitialized || pump.isSuspended) View.GONE else View.VISIBLE
|
||||
|
||||
if (!pump.pumpDescription.isExtendedBolusCapable || !pump.isInitialized || pump.isSuspended || pump.isFakingTempsByExtendedBoluses || Config.APS) {
|
||||
if (!pump.pumpDescription.isExtendedBolusCapable || !pump.isInitialized || pump.isSuspended || pump.isFakingTempsByExtendedBoluses) {
|
||||
actions_extendedbolus?.visibility = View.GONE
|
||||
actions_extendedbolus_cancel?.visibility = View.GONE
|
||||
} else {
|
||||
|
@ -172,7 +187,7 @@ class ActionsFragment : Fragment() {
|
|||
if (activeExtendedBolus != null) {
|
||||
actions_extendedbolus?.visibility = View.GONE
|
||||
actions_extendedbolus_cancel?.visibility = View.VISIBLE
|
||||
actions_extendedbolus_cancel?.text = MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString()
|
||||
actions_extendedbolus_cancel?.text = MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toStringMedium()
|
||||
} else {
|
||||
actions_extendedbolus?.visibility = View.VISIBLE
|
||||
actions_extendedbolus_cancel?.visibility = View.GONE
|
||||
|
@ -198,8 +213,11 @@ class ActionsFragment : Fragment() {
|
|||
if (!pump.pumpDescription.isRefillingCapable || !pump.isInitialized || pump.isSuspended) View.GONE
|
||||
else View.VISIBLE
|
||||
|
||||
actions_temptarget?.visibility = if (!Config.APS) View.GONE else View.VISIBLE
|
||||
actions_tddstats?.visibility = if (!pump.pumpDescription.supportsTDDs) View.GONE else View.VISIBLE
|
||||
actions_temptarget?.visibility = Config.APS.toVisibility()
|
||||
actions_tddstats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
|
||||
activity?.let { activity ->
|
||||
CareportalFragment.updateAge(activity, careportal_sensorage, careportal_insulinage, careportal_canulaage, careportal_pbage)
|
||||
}
|
||||
checkPumpCustomActions()
|
||||
}
|
||||
|
||||
|
@ -224,8 +242,7 @@ class ActionsFragment : Fragment() {
|
|||
val action = this.pumpCustomActions[b.text.toString()]
|
||||
ConfigBuilderPlugin.getPlugin().activePump!!.executeCustomAction(action!!.customActionType)
|
||||
}
|
||||
|
||||
val top = resources.getDrawable(customAction.iconResourceId)
|
||||
val top = activity?.let { ContextCompat.getDrawable(it, customAction.iconResourceId) }
|
||||
btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null)
|
||||
|
||||
action_buttons_layout?.addView(btn)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions
|
||||
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
|
@ -8,6 +9,8 @@ import info.nightscout.androidaps.interfaces.PluginType
|
|||
object ActionsPlugin : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(ActionsFragment::class.qualifiedName)
|
||||
.enableByDefault(Config.APS || Config.PUMPCONTROL)
|
||||
.visibleByDefault(Config.APS || Config.PUMPCONTROL)
|
||||
.pluginName(R.string.actions)
|
||||
.shortName(R.string.actions_shortname)
|
||||
.description(R.string.description_actions))
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.defs;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
/**
|
||||
* Created by andy on 9/20/18.
|
||||
*/
|
||||
|
||||
public class CustomAction {
|
||||
|
||||
private int name;
|
||||
private String iconName;
|
||||
private CustomActionType customActionType;
|
||||
private int iconResourceId;
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
public CustomAction(int nameResourceId, CustomActionType actionType) {
|
||||
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, true);
|
||||
}
|
||||
|
||||
|
||||
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId) {
|
||||
this(nameResourceId, actionType, iconResourceId, true);
|
||||
}
|
||||
|
||||
public CustomAction(int nameResourceId, CustomActionType actionType, boolean enabled) {
|
||||
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled);
|
||||
}
|
||||
|
||||
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId, boolean enabled) {
|
||||
this.name = nameResourceId;
|
||||
this.customActionType = actionType;
|
||||
this.iconResourceId = iconResourceId;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
public int getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public CustomActionType getCustomActionType() {
|
||||
return customActionType;
|
||||
}
|
||||
|
||||
|
||||
public int getIconResourceId() {
|
||||
return iconResourceId;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.defs
|
||||
|
||||
import info.nightscout.androidaps.R
|
||||
|
||||
class CustomAction @JvmOverloads constructor(val name: Int, val customActionType: CustomActionType?, val iconResourceId: Int = R.drawable.icon_actions_profileswitch, var isEnabled: Boolean = true) {
|
||||
|
||||
constructor(nameResourceId: Int, actionType: CustomActionType?, enabled: Boolean) :
|
||||
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled)
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.defs;
|
||||
|
||||
/**
|
||||
* Created by andy on 9/20/18.
|
||||
*/
|
||||
|
||||
public interface CustomActionType {
|
||||
|
||||
String getKey();
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.defs
|
||||
|
||||
interface CustomActionType {
|
||||
val key: String?
|
||||
}
|
|
@ -1,255 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.dialogs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.NumberPicker;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
import info.nightscout.androidaps.utils.ToastUtils;
|
||||
|
||||
import static info.nightscout.androidaps.utils.DateUtil.now;
|
||||
|
||||
public class FillDialog extends DialogFragment implements OnClickListener {
|
||||
private static Logger log = LoggerFactory.getLogger(FillDialog.class);
|
||||
|
||||
private CheckBox pumpSiteChangeCheckbox;
|
||||
private CheckBox insulinCartridgeChangeCheckbox;
|
||||
|
||||
private NumberPicker editInsulin;
|
||||
|
||||
double amount1 = 0d;
|
||||
double amount2 = 0d;
|
||||
double amount3 = 0d;
|
||||
|
||||
private EditText notesEdit;
|
||||
|
||||
//one shot guards
|
||||
private boolean accepted;
|
||||
private boolean okClicked;
|
||||
|
||||
final private TextWatcher textWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
validateInputs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
};
|
||||
|
||||
private void validateInputs() {
|
||||
int time = editInsulin.getValue().intValue();
|
||||
if (Math.abs(time) > 12 * 60) {
|
||||
editInsulin.setValue(0d);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.actions_fill_dialog, container, false);
|
||||
|
||||
view.findViewById(R.id.ok).setOnClickListener(this);
|
||||
view.findViewById(R.id.cancel).setOnClickListener(this);
|
||||
|
||||
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
|
||||
pumpSiteChangeCheckbox = view.findViewById(R.id.fill_catheter_change);
|
||||
insulinCartridgeChangeCheckbox = view.findViewById(R.id.fill_cartridge_change);
|
||||
|
||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
||||
double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
|
||||
editInsulin = view.findViewById(R.id.fill_insulinamount);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
|
||||
|
||||
|
||||
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
|
||||
amount1 = SP.getDouble("fill_button1", 0.3);
|
||||
if (amount1 > 0) {
|
||||
preset1Button.setVisibility(View.VISIBLE);
|
||||
preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U");
|
||||
preset1Button.setOnClickListener(this);
|
||||
} else {
|
||||
preset1Button.setVisibility(View.GONE);
|
||||
}
|
||||
Button preset2Button = view.findViewById(R.id.fill_preset_button2);
|
||||
amount2 = SP.getDouble("fill_button2", 0d);
|
||||
if (amount2 > 0) {
|
||||
preset2Button.setVisibility(View.VISIBLE);
|
||||
preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U");
|
||||
preset2Button.setOnClickListener(this);
|
||||
} else {
|
||||
preset2Button.setVisibility(View.GONE);
|
||||
}
|
||||
Button preset3Button = view.findViewById(R.id.fill_preset_button3);
|
||||
amount3 = SP.getDouble("fill_button3", 0d);
|
||||
if (amount3 > 0) {
|
||||
preset3Button.setVisibility(View.VISIBLE);
|
||||
preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U");
|
||||
preset3Button.setOnClickListener(this);
|
||||
} else {
|
||||
preset3Button.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
LinearLayout notesLayout = view.findViewById(R.id.fill_notes_layout);
|
||||
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
|
||||
notesEdit = view.findViewById(R.id.fill_notes);
|
||||
|
||||
setCancelable(true);
|
||||
getDialog().setCanceledOnTouchOutside(false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.ok:
|
||||
confirmAndDeliver();
|
||||
break;
|
||||
case R.id.cancel:
|
||||
dismiss();
|
||||
break;
|
||||
case R.id.fill_preset_button1:
|
||||
editInsulin.setValue(amount1);
|
||||
break;
|
||||
case R.id.fill_preset_button2:
|
||||
editInsulin.setValue(amount2);
|
||||
break;
|
||||
case R.id.fill_preset_button3:
|
||||
editInsulin.setValue(amount3);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private synchronized void confirmAndDeliver() {
|
||||
if (okClicked) {
|
||||
log.debug("guarding: ok already clicked");
|
||||
dismiss();
|
||||
return;
|
||||
}
|
||||
okClicked = true;
|
||||
|
||||
try {
|
||||
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
|
||||
|
||||
List<String> confirmMessage = new LinkedList<>();
|
||||
|
||||
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
|
||||
if (insulinAfterConstraints > 0) {
|
||||
confirmMessage.add(MainApp.gs(R.string.fillwarning));
|
||||
confirmMessage.add("");
|
||||
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>");
|
||||
if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
|
||||
confirmMessage.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
|
||||
}
|
||||
|
||||
if (pumpSiteChangeCheckbox.isChecked())
|
||||
confirmMessage.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>");
|
||||
|
||||
if (insulinCartridgeChangeCheckbox.isChecked())
|
||||
confirmMessage.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>");
|
||||
|
||||
final String notes = notesEdit.getText().toString();
|
||||
if (!notes.isEmpty()) {
|
||||
confirmMessage.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
|
||||
}
|
||||
|
||||
final Double finalInsulinAfterConstraints = insulinAfterConstraints;
|
||||
|
||||
final Context context = getContext();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
|
||||
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage)));
|
||||
builder.setPositiveButton(MainApp.gs(R.string.primefill), (dialog, id) -> {
|
||||
synchronized (builder) {
|
||||
if (accepted) {
|
||||
log.debug("guarding: already accepted");
|
||||
return;
|
||||
}
|
||||
accepted = true;
|
||||
|
||||
if (finalInsulinAfterConstraints > 0) {
|
||||
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
|
||||
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
|
||||
detailedBolusInfo.context = context;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
|
||||
detailedBolusInfo.notes = notes;
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (pumpSiteChangeCheckbox.isChecked())
|
||||
NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
|
||||
if (insulinCartridgeChangeCheckbox.isChecked())
|
||||
NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
builder.setMessage(MainApp.gs(R.string.no_action_selected));
|
||||
}
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.dialogs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.NumberPicker;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
|
||||
public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener {
|
||||
private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class);
|
||||
|
||||
NumberPicker editInsulin;
|
||||
NumberPicker editDuration;
|
||||
|
||||
public NewExtendedBolusDialog() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getDialog().setTitle(MainApp.gs(R.string.overview_extendedbolus_button));
|
||||
|
||||
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
|
||||
|
||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxExtendedBolusAllowed().value();
|
||||
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false, view.findViewById(R.id.ok));
|
||||
|
||||
double extendedDurationStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusDurationStep;
|
||||
double extendedMaxDuration = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusMaxDuration;
|
||||
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
|
||||
editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
|
||||
|
||||
view.findViewById(R.id.ok).setOnClickListener(this);
|
||||
view.findViewById(R.id.cancel).setOnClickListener(this);
|
||||
|
||||
setCancelable(true);
|
||||
getDialog().setCanceledOnTouchOutside(false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.ok:
|
||||
try {
|
||||
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
|
||||
int durationInMinutes = SafeParse.stringToInt(editDuration.getText());
|
||||
|
||||
String confirmMessage = MainApp.gs(R.string.setextendedbolusquestion);
|
||||
|
||||
Double insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(new Constraint<>(insulin)).value();
|
||||
confirmMessage += " " + insulinAfterConstraint + " U ";
|
||||
confirmMessage += MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (Math.abs(insulinAfterConstraint - insulin) > 0.01d)
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
insulin = insulinAfterConstraint;
|
||||
|
||||
final Double finalInsulin = insulin;
|
||||
final int finalDurationInMinutes = durationInMinutes;
|
||||
|
||||
final Context context = getContext();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmMessage);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
break;
|
||||
case R.id.cancel:
|
||||
dismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.actions.dialogs;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.NumberPicker;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
|
||||
public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener {
|
||||
private static Logger log = LoggerFactory.getLogger(NewTempBasalDialog.class);
|
||||
|
||||
RadioButton percentRadio;
|
||||
RadioButton absoluteRadio;
|
||||
RadioGroup basalTypeRadioGroup;
|
||||
LinearLayout typeSelectorLayout;
|
||||
|
||||
LinearLayout percentLayout;
|
||||
LinearLayout absoluteLayout;
|
||||
|
||||
NumberPicker basalPercent;
|
||||
NumberPicker basalAbsolute;
|
||||
NumberPicker duration;
|
||||
|
||||
public NewTempBasalDialog() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getDialog().setTitle(MainApp.gs(R.string.overview_tempbasal_button));
|
||||
|
||||
View view = inflater.inflate(R.layout.overview_newtempbasal_dialog, container, false);
|
||||
|
||||
percentLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_percent_layout);
|
||||
absoluteLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_absolute_layout);
|
||||
percentRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_percent_radio);
|
||||
basalTypeRadioGroup = (RadioGroup) view.findViewById(R.id.overview_newtempbasal_radiogroup);
|
||||
absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio);
|
||||
typeSelectorLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout);
|
||||
|
||||
PumpDescription pumpDescription = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription();
|
||||
|
||||
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
|
||||
double maxTempPercent = pumpDescription.maxTempPercent;
|
||||
double tempPercentStep = pumpDescription.tempPercentStep;
|
||||
basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true, view.findViewById(R.id.ok));
|
||||
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
Double currentBasal = profile != null ? profile.getBasal() : 0d;
|
||||
basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput);
|
||||
basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true, view.findViewById(R.id.ok));
|
||||
|
||||
double tempDurationStep = pumpDescription.tempDurationStep;
|
||||
double tempMaxDuration = pumpDescription.tempMaxDuration;
|
||||
duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration);
|
||||
duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
|
||||
|
||||
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
|
||||
// Both allowed
|
||||
typeSelectorLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
typeSelectorLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT) {
|
||||
percentRadio.setChecked(true);
|
||||
absoluteRadio.setChecked(false);
|
||||
percentLayout.setVisibility(View.VISIBLE);
|
||||
absoluteLayout.setVisibility(View.GONE);
|
||||
} else if ((pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
|
||||
percentRadio.setChecked(false);
|
||||
absoluteRadio.setChecked(true);
|
||||
percentLayout.setVisibility(View.GONE);
|
||||
absoluteLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
view.findViewById(R.id.ok).setOnClickListener(this);
|
||||
view.findViewById(R.id.cancel).setOnClickListener(this);
|
||||
basalTypeRadioGroup.setOnCheckedChangeListener(this);
|
||||
|
||||
setCancelable(true);
|
||||
getDialog().setCanceledOnTouchOutside(false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.ok:
|
||||
try {
|
||||
int percent = 0;
|
||||
Double absolute = 0d;
|
||||
final boolean setAsPercent = percentRadio.isChecked();
|
||||
int durationInMinutes = SafeParse.stringToInt(duration.getText());
|
||||
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
if (profile == null)
|
||||
return;
|
||||
|
||||
String confirmMessage = MainApp.gs(R.string.setbasalquestion);
|
||||
if (setAsPercent) {
|
||||
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText());
|
||||
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(basalPercentInput), profile).value();
|
||||
confirmMessage += "\n" + percent + "% ";
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (percent != basalPercentInput)
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
} else {
|
||||
Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText());
|
||||
absolute = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(basalAbsoluteInput), profile).value();
|
||||
confirmMessage += "\n" + absolute + " U/h ";
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (Math.abs(absolute - basalAbsoluteInput) > 0.01d)
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
}
|
||||
|
||||
final int finalBasalPercent = percent;
|
||||
final Double finalBasal = absolute;
|
||||
final int finalDurationInMinutes = durationInMinutes;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmMessage);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Callback callback = new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (setAsPercent) {
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback);
|
||||
} else {
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
break;
|
||||
case R.id.cancel:
|
||||
dismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||
switch (checkedId) {
|
||||
case R.id.overview_newtempbasal_percent_radio:
|
||||
percentLayout.setVisibility(View.VISIBLE);
|
||||
absoluteLayout.setVisibility(View.GONE);
|
||||
break;
|
||||
case R.id.overview_newtempbasal_absolute_radio:
|
||||
percentLayout.setVisibility(View.GONE);
|
||||
absoluteLayout.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -16,12 +17,12 @@ import info.nightscout.androidaps.plugins.general.automation.dragHelpers.SimpleI
|
|||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
|
||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.plusAssign
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.automation_fragment.*
|
||||
|
||||
|
||||
class AutomationFragment : Fragment(), OnStartDragListener {
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
@ -40,6 +41,8 @@ class AutomationFragment : Fragment(), OnStartDragListener {
|
|||
automation_eventListView.layoutManager = LinearLayoutManager(context)
|
||||
automation_eventListView.adapter = eventListAdapter
|
||||
|
||||
automation_logView.setMovementMethod(ScrollingMovementMethod())
|
||||
|
||||
automation_fabAddEvent.setOnClickListener {
|
||||
val dialog = EditEventDialog()
|
||||
val args = Bundle()
|
||||
|
@ -88,8 +91,8 @@ class AutomationFragment : Fragment(), OnStartDragListener {
|
|||
eventListAdapter?.notifyDataSetChanged()
|
||||
val sb = StringBuilder()
|
||||
for (l in AutomationPlugin.executionLog.reversed())
|
||||
sb.append(l).append("\n")
|
||||
automation_logView?.text = sb.toString()
|
||||
sb.append(l).append("<br>")
|
||||
automation_logView?.text = HtmlHelper.fromHtml(sb.toString())
|
||||
}
|
||||
|
||||
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
|
||||
|
|
|
@ -178,10 +178,10 @@ object AutomationPlugin : PluginBase(PluginDescription()
|
|||
val sb = StringBuilder()
|
||||
sb.append(DateUtil.timeString(DateUtil.now()))
|
||||
sb.append(" ")
|
||||
sb.append(if (result.success) "☺" else "X")
|
||||
sb.append(" ")
|
||||
sb.append(if (result.success) "☺" else "▼")
|
||||
sb.append(" <b>")
|
||||
sb.append(event.title)
|
||||
sb.append(": ")
|
||||
sb.append(":</b> ")
|
||||
sb.append(action.shortDescription())
|
||||
sb.append(": ")
|
||||
sb.append(result.comment)
|
||||
|
|
|
@ -21,17 +21,29 @@ import info.nightscout.androidaps.plugins.general.automation.elements.InputProfi
|
|||
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.JsonHelper;
|
||||
|
||||
public class ActionProfileSwitch extends Action {
|
||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||
public InputProfileName inputProfileName = new InputProfileName(ProfileFunctions.getInstance().getProfileName());
|
||||
InputProfileName inputProfileName;
|
||||
String profileName = "";
|
||||
|
||||
public ActionProfileSwitch() {
|
||||
// Prevent action if active profile is already active
|
||||
// but we don't have a trigger IS_NOT_EQUAL
|
||||
// so check is in the doRun()
|
||||
ProfileInterface profileInterface = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface();
|
||||
if (profileInterface != null) {
|
||||
ProfileStore profileStore = profileInterface.getProfile();
|
||||
if (profileStore != null) {
|
||||
String name = profileStore.getDefaultProfileName();
|
||||
if (name != null) {
|
||||
profileName = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputProfileName = new InputProfileName(profileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,23 +62,43 @@ public class ActionProfileSwitch extends Action {
|
|||
|
||||
String activeProfileName = ProfileFunctions.getInstance().getProfileName();
|
||||
//Check for uninitialized profileName
|
||||
if ( profileName.equals("")){ profileName = activeProfileName; }
|
||||
|
||||
if ( profileName.equals("")){
|
||||
log.error("Selected profile not initialized");
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(false).comment(R.string.error_field_must_not_be_empty)).run();
|
||||
return;
|
||||
}
|
||||
if ( ProfileFunctions.getInstance().getProfile() == null){
|
||||
log.error("ProfileFunctions not initialized");
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(false).comment(R.string.noprofile)).run();
|
||||
return;
|
||||
}
|
||||
if (profileName.equals(activeProfileName)) {
|
||||
// Profile is already switched
|
||||
if (L.isEnabled(L.AUTOMATION))
|
||||
log.debug("Profile is already switched");
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(true).comment(R.string.alreadyset)).run();
|
||||
return;
|
||||
}
|
||||
ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface();
|
||||
if (activeProfile == null) return;
|
||||
if (activeProfile == null) {
|
||||
log.error("ProfileInterface not initialized");
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(false).comment(R.string.noprofile)).run();
|
||||
return;
|
||||
}
|
||||
ProfileStore profileStore = activeProfile.getProfile();
|
||||
if (profileStore == null) return;
|
||||
if(profileStore.getSpecificProfile(profileName) == null) {
|
||||
if (L.isEnabled(L.AUTOMATION))
|
||||
log.error("Selected profile does not exist! - "+ profileName);
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(false).comment(R.string.notexists)).run();
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileFunctions.doProfileSwitch(profileStore, profileName, 0, 100, 0);
|
||||
ProfileFunctions.doProfileSwitch(profileStore, profileName, 0, 100, 0, DateUtil.now());
|
||||
if (callback != null)
|
||||
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class ActionStartTempTarget extends Action {
|
|||
int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol;
|
||||
|
||||
new LayoutBuilder()
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + " [" + MainApp.gs(unitResId) + "]", "", value))
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + "\n[" + MainApp.gs(unitResId) + "]", "", value))
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
||||
.build(root);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ class ActionListAdapter(private val fragmentManager: FragmentManager, private va
|
|||
|
||||
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter<ViewHolder>, position : Int, actionList: MutableList<Action>) {
|
||||
fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter<ViewHolder>, position: Int, actionList: MutableList<Action>) {
|
||||
view.findViewById<LinearLayout>(R.id.automation_layoutText).setOnClickListener {
|
||||
if (action.hasDialog()) {
|
||||
val args = Bundle()
|
||||
|
@ -48,6 +48,7 @@ class ActionListAdapter(private val fragmentManager: FragmentManager, private va
|
|||
recyclerView.notifyDataSetChanged()
|
||||
RxBus.send(EventAutomationUpdateGui())
|
||||
}
|
||||
if (action.icon().isPresent) view.findViewById<ImageView>(R.id.automation_action_image).setImageResource(action.icon().get())
|
||||
view.findViewById<TextView>(R.id.automation_viewActionTitle).text = action.shortDescription()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,18 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationAddAction
|
||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||
import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
|
||||
class ChooseActionDialog : DialogFragment() {
|
||||
class ChooseActionDialog : DialogFragmentWithDate() {
|
||||
|
||||
var checkedIndex = -1
|
||||
private var checkedIndex = -1
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
@ -26,7 +25,7 @@ class ChooseActionDialog : DialogFragment() {
|
|||
checkedIndex = bundle.getInt("checkedIndex")
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.automation_dialog_choose_action, container, false)
|
||||
}
|
||||
|
||||
|
@ -42,27 +41,19 @@ class ChooseActionDialog : DialogFragment() {
|
|||
|
||||
if (checkedIndex != -1)
|
||||
(automation_radioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
|
||||
}
|
||||
|
||||
// OK button
|
||||
ok.setOnClickListener {
|
||||
dismiss()
|
||||
instantiateAction()?.let {
|
||||
RxBus.send(EventAutomationAddAction(it))
|
||||
RxBus.send(EventAutomationUpdateGui())
|
||||
}
|
||||
override fun submit(): Boolean {
|
||||
instantiateAction()?.let {
|
||||
RxBus.send(EventAutomationAddAction(it))
|
||||
RxBus.send(EventAutomationUpdateGui())
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
bundle.putInt("checkedIndex", determineCheckedIndex())
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putInt("checkedIndex", determineCheckedIndex())
|
||||
}
|
||||
|
||||
private fun instantiateAction(): Action? {
|
||||
|
@ -86,5 +77,4 @@ class ChooseActionDialog : DialogFragment() {
|
|||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,17 +5,15 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||
import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
|
||||
class ChooseTriggerDialog : DialogFragment() {
|
||||
class ChooseTriggerDialog : DialogFragmentWithDate() {
|
||||
|
||||
private var checkedIndex = -1
|
||||
|
||||
private var clickListener: OnClickListener? = null
|
||||
|
||||
interface OnClickListener {
|
||||
|
@ -29,7 +27,7 @@ class ChooseTriggerDialog : DialogFragment() {
|
|||
checkedIndex = bundle.getInt("checkedIndex")
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.automation_dialog_choose_trigger, container, false)
|
||||
}
|
||||
|
||||
|
@ -45,30 +43,22 @@ class ChooseTriggerDialog : DialogFragment() {
|
|||
|
||||
if (checkedIndex != -1)
|
||||
(automation_chooseTriggerRadioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
|
||||
|
||||
// OK button
|
||||
ok.setOnClickListener {
|
||||
dismiss()
|
||||
instantiateTrigger()?.let {
|
||||
clickListener?.onClick(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
override fun submit(): Boolean {
|
||||
instantiateTrigger()?.let {
|
||||
clickListener?.onClick(it)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun setOnClickListener(clickListener: OnClickListener) {
|
||||
this.clickListener = clickListener
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
bundle.putInt("checkedIndex", determineCheckedIndex())
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putInt("checkedIndex", determineCheckedIndex())
|
||||
}
|
||||
|
||||
private fun instantiateTrigger(): Trigger? {
|
||||
|
@ -92,5 +82,4 @@ class ChooseTriggerDialog : DialogFragment() {
|
|||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,16 +4,15 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
|
||||
import kotlinx.android.synthetic.main.automation_dialog_action.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.json.JSONObject
|
||||
|
||||
class EditActionDialog : DialogFragment() {
|
||||
class EditActionDialog : DialogFragmentWithDate() {
|
||||
private var action: Action? = null
|
||||
private var actionPosition: Int = -1
|
||||
|
||||
|
@ -24,8 +23,7 @@ class EditActionDialog : DialogFragment() {
|
|||
actionPosition = bundle.getInt("actionPosition", -1)
|
||||
bundle.getString("action")?.let { action = Action.instantiate(JSONObject(it)) }
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.automation_dialog_action, container, false)
|
||||
}
|
||||
|
||||
|
@ -37,22 +35,13 @@ class EditActionDialog : DialogFragment() {
|
|||
automation_editActionLayout.removeAllViews()
|
||||
it.generateDialog(automation_editActionLayout)
|
||||
}
|
||||
|
||||
// OK button
|
||||
ok.setOnClickListener {
|
||||
dismiss()
|
||||
action?.let {
|
||||
RxBus.send(EventAutomationUpdateAction(it, actionPosition))
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
override fun submit(): Boolean {
|
||||
action?.let {
|
||||
RxBus.send(EventAutomationUpdateAction(it, actionPosition))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
|
|
|
@ -4,9 +4,9 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||
|
@ -17,9 +17,8 @@ import info.nightscout.androidaps.utils.ToastUtils
|
|||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.automation_dialog_event.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
|
||||
class EditEventDialog : DialogFragment() {
|
||||
class EditEventDialog : DialogFragmentWithDate() {
|
||||
|
||||
private var actionListAdapter: ActionListAdapter? = null
|
||||
private var event: AutomationEvent = AutomationEvent()
|
||||
|
@ -35,7 +34,7 @@ class EditEventDialog : DialogFragment() {
|
|||
bundle.getString("event")?.let { event = AutomationEvent().fromJSON(it) }
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.automation_dialog_event, container, false)
|
||||
}
|
||||
|
||||
|
@ -60,39 +59,6 @@ class EditEventDialog : DialogFragment() {
|
|||
|
||||
automation_addAction.setOnClickListener { fragmentManager?.let { ChooseActionDialog().show(it, "ChooseActionDialog") } }
|
||||
|
||||
// OK button
|
||||
ok.setOnClickListener {
|
||||
// check for title
|
||||
val title = automation_inputEventTitle.text.toString()
|
||||
if (title.isEmpty()) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
|
||||
return@setOnClickListener
|
||||
}
|
||||
event.title = title
|
||||
// check for at least one trigger
|
||||
val con = event.trigger as TriggerConnector
|
||||
if (con.size() == 0) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
||||
return@setOnClickListener
|
||||
}
|
||||
// check for at least one action
|
||||
if (event.actions.isEmpty()) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
|
||||
return@setOnClickListener
|
||||
}
|
||||
// store
|
||||
if (position == -1)
|
||||
AutomationPlugin.automationEvents.add(event)
|
||||
else
|
||||
AutomationPlugin.automationEvents[position] = event
|
||||
|
||||
dismiss()
|
||||
RxBus.send(EventAutomationDataChanged())
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
|
||||
showPreconditions()
|
||||
|
||||
disposable.add(RxBus
|
||||
|
@ -137,9 +103,33 @@ class EditEventDialog : DialogFragment() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
override fun submit() : Boolean{
|
||||
// check for title
|
||||
val title = automation_inputEventTitle.text.toString()
|
||||
if (title.isEmpty()) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
|
||||
return false
|
||||
}
|
||||
event.title = title
|
||||
// check for at least one trigger
|
||||
val con = event.trigger as TriggerConnector
|
||||
if (con.size() == 0) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
||||
return false
|
||||
}
|
||||
// check for at least one action
|
||||
if (event.actions.isEmpty()) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
|
||||
return false
|
||||
}
|
||||
// store
|
||||
if (position == -1)
|
||||
AutomationPlugin.automationEvents.add(event)
|
||||
else
|
||||
AutomationPlugin.automationEvents[position] = event
|
||||
|
||||
RxBus.send(EventAutomationDataChanged())
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -147,10 +137,10 @@ class EditEventDialog : DialogFragment() {
|
|||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
super.onSaveInstanceState(bundle)
|
||||
bundle.putString("event", event.toJSON())
|
||||
bundle.putInt("position", position)
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putString("event", event.toJSON())
|
||||
savedInstanceState.putInt("position", position)
|
||||
}
|
||||
|
||||
private fun showPreconditions() {
|
||||
|
@ -164,5 +154,4 @@ class EditEventDialog : DialogFragment() {
|
|||
automation_forcedTriggerDescriptionLabel.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,15 +4,14 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
|
||||
class EditTriggerDialog : DialogFragment() {
|
||||
class EditTriggerDialog : DialogFragmentWithDate() {
|
||||
|
||||
private var trigger: Trigger? = null
|
||||
|
||||
|
@ -23,7 +22,7 @@ class EditTriggerDialog : DialogFragment() {
|
|||
bundle.getString("trigger")?.let { trigger = Trigger.instantiate(it) }
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.automation_dialog_edit_trigger, container, false)
|
||||
}
|
||||
|
||||
|
@ -32,24 +31,15 @@ class EditTriggerDialog : DialogFragment() {
|
|||
|
||||
// display root trigger
|
||||
trigger?.generateDialog(automation_layoutTrigger, fragmentManager)
|
||||
|
||||
// OK button
|
||||
ok.setOnClickListener {
|
||||
dismiss()
|
||||
trigger?.let { trigger -> RxBus.send(EventAutomationUpdateTrigger(trigger)) }
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
override fun submit():Boolean {
|
||||
trigger?.let { trigger -> RxBus.send(EventAutomationUpdateTrigger(trigger)) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
super.onSaveInstanceState(bundle)
|
||||
trigger?.let { bundle.putString("trigger", it.toJSON()) }
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
trigger?.let { savedInstanceState.putString("trigger", it.toJSON()) }
|
||||
}
|
||||
}
|
|
@ -75,7 +75,7 @@ public class TriggerListAdapter {
|
|||
|
||||
private Spinner createSpinner() {
|
||||
Spinner spinner = new Spinner(mContext);
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, R.layout.spinner_centered, TriggerConnector.Type.labels());
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(spinnerArrayAdapter);
|
||||
return spinner;
|
||||
|
|
|
@ -87,7 +87,7 @@ public class Comparator extends Element {
|
|||
@Override
|
||||
public void addToLayout(LinearLayout root) {
|
||||
Spinner spinner = new Spinner(root.getContext());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(spinnerArrayAdapter);
|
||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ComparatorExists extends Element {
|
|||
@Override
|
||||
public void addToLayout(LinearLayout root) {
|
||||
Spinner spinner = new Spinner(root.getContext());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(spinnerArrayAdapter);
|
||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||
|
|
|
@ -87,7 +87,7 @@ public class InputDelta extends Element {
|
|||
@Override
|
||||
public void addToLayout(LinearLayout root) {
|
||||
Spinner spinner = new Spinner(root.getContext());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, DeltaType.labels());
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, DeltaType.labels());
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(spinnerArrayAdapter);
|
||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
public class InputLocationMode extends Element {
|
||||
|
||||
public enum Mode {
|
||||
INSIDE,
|
||||
OUTSIDE,
|
||||
GOING_IN,
|
||||
GOING_OUT;
|
||||
|
||||
public @StringRes
|
||||
int getStringRes() {
|
||||
switch (this) {
|
||||
case INSIDE:
|
||||
return R.string.location_inside;
|
||||
case OUTSIDE:
|
||||
return R.string.location_outside;
|
||||
case GOING_IN:
|
||||
return R.string.location_going_in;
|
||||
case GOING_OUT:
|
||||
return R.string.location_going_out;
|
||||
default:
|
||||
return R.string.unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> labels() {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Mode c : Mode.values()) {
|
||||
list.add(MainApp.gs(c.getStringRes()));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Mode fromString(String wanted){
|
||||
for (Mode c : Mode.values()) {
|
||||
if(c.toString() == wanted)
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Mode mode;
|
||||
|
||||
public InputLocationMode() {
|
||||
super();
|
||||
mode = Mode.INSIDE;
|
||||
}
|
||||
|
||||
public InputLocationMode(InputLocationMode another) {
|
||||
super();
|
||||
this.mode = another.mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToLayout(LinearLayout root) {
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(root.getContext(),
|
||||
R.layout.spinner_centered, Mode.labels());
|
||||
Spinner spinner = new Spinner(root.getContext());
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
||||
spinner.setLayoutParams(spinnerParams);
|
||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
setValue(Mode.values()[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
spinner.setSelection(this.getValue().ordinal());
|
||||
root.addView(spinner);
|
||||
|
||||
}
|
||||
|
||||
public Mode getValue() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public InputLocationMode setValue(Mode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import info.nightscout.androidaps.R;
|
|||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputButton;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||
|
@ -28,12 +29,17 @@ import info.nightscout.androidaps.utils.DateUtil;
|
|||
import info.nightscout.androidaps.utils.JsonHelper;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode.Mode.*;
|
||||
|
||||
public class TriggerLocation extends Trigger {
|
||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||
|
||||
InputDouble latitude = new InputDouble(0d, -90d, +90d, 0.000001d, new DecimalFormat("0.000000"));
|
||||
InputDouble longitude = new InputDouble(0d, -180d, +180d, 0.000001d, new DecimalFormat("0.000000"));
|
||||
InputDouble distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
|
||||
InputLocationMode modeSelected = new InputLocationMode();
|
||||
InputLocationMode.Mode lastMode = INSIDE;
|
||||
|
||||
InputString name = new InputString();
|
||||
|
||||
private Runnable buttonAction = () -> {
|
||||
|
@ -54,13 +60,16 @@ public class TriggerLocation extends Trigger {
|
|||
latitude = new InputDouble(triggerLocation.latitude);
|
||||
longitude = new InputDouble(triggerLocation.longitude);
|
||||
distance = new InputDouble(triggerLocation.distance);
|
||||
modeSelected = new InputLocationMode(triggerLocation.modeSelected);
|
||||
if (modeSelected.getValue() == GOING_OUT)
|
||||
lastMode = OUTSIDE;
|
||||
lastRun = triggerLocation.lastRun;
|
||||
name = triggerLocation.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean shouldRun() {
|
||||
Location location = LocationService.getLastLocation();
|
||||
Location location = this.getCurrentLocation();
|
||||
if (location == null)
|
||||
return false;
|
||||
|
||||
|
@ -72,11 +81,20 @@ public class TriggerLocation extends Trigger {
|
|||
a.setLongitude(longitude.getValue());
|
||||
double calculatedDistance = location.distanceTo(a);
|
||||
|
||||
if (calculatedDistance < distance.getValue()) {
|
||||
// log.debug("Moded(current/last/wanted): "+(currentMode(calculatedDistance))+"/"+lastMode+"/"+modeSelected.getValue());
|
||||
// log.debug("Distance: "+calculatedDistance + "("+distance.getValue()+")");
|
||||
|
||||
if ((modeSelected.getValue() == INSIDE) && (calculatedDistance <= distance.getValue()) ||
|
||||
((modeSelected.getValue() == OUTSIDE) && (calculatedDistance > distance.getValue())) ||
|
||||
((modeSelected.getValue() == GOING_IN) && (calculatedDistance <= distance.getValue()) && (lastMode == OUTSIDE)) ||
|
||||
((modeSelected.getValue() == GOING_OUT) && (calculatedDistance > distance.getValue()) && (lastMode == INSIDE))
|
||||
) {
|
||||
if (L.isEnabled(L.AUTOMATION))
|
||||
log.debug("Ready for execution: " + friendlyDescription());
|
||||
lastMode = currentMode(calculatedDistance);
|
||||
return true;
|
||||
}
|
||||
lastMode = currentMode(calculatedDistance); // current mode will be last mode for the next check
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -90,6 +108,7 @@ public class TriggerLocation extends Trigger {
|
|||
data.put("longitude", longitude.getValue());
|
||||
data.put("distance", distance.getValue());
|
||||
data.put("name", name.getValue());
|
||||
data.put("mode", modeSelected.getValue());
|
||||
data.put("lastRun", lastRun);
|
||||
o.put("data", data);
|
||||
} catch (JSONException e) {
|
||||
|
@ -106,7 +125,10 @@ public class TriggerLocation extends Trigger {
|
|||
longitude.setValue(JsonHelper.safeGetDouble(d, "longitude"));
|
||||
distance.setValue(JsonHelper.safeGetDouble(d, "distance"));
|
||||
name.setValue(JsonHelper.safeGetString(d, "name"));
|
||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||
modeSelected.setValue(InputLocationMode.Mode.valueOf(JsonHelper.safeGetString(d, "mode")));
|
||||
if (modeSelected.getValue() == GOING_OUT)
|
||||
lastMode = OUTSIDE;
|
||||
lastRun = DateUtil.now(); // set lastRun to now to give the service 5 mins to get the location properly
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -120,7 +142,7 @@ public class TriggerLocation extends Trigger {
|
|||
|
||||
@Override
|
||||
public String friendlyDescription() {
|
||||
return MainApp.gs(R.string.locationis, name.getValue());
|
||||
return MainApp.gs(R.string.locationis, MainApp.gs(modeSelected.getValue().getStringRes()), " " + name.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -154,6 +176,11 @@ public class TriggerLocation extends Trigger {
|
|||
return this;
|
||||
}
|
||||
|
||||
TriggerLocation setMode(InputLocationMode.Mode value) {
|
||||
modeSelected.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||
new LayoutBuilder()
|
||||
|
@ -162,7 +189,21 @@ public class TriggerLocation extends Trigger {
|
|||
.add(new LabelWithElement(MainApp.gs(R.string.latitude_short), "", latitude))
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.longitude_short), "", longitude))
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.distance_short), "", distance))
|
||||
.add(new LabelWithElement(MainApp.gs(R.string.location_mode), "", modeSelected))
|
||||
.add(new InputButton(MainApp.gs(R.string.currentlocation), buttonAction), LocationService.getLastLocation() != null)
|
||||
.build(root);
|
||||
}
|
||||
|
||||
// Method to return the actual mode based on the current distance
|
||||
InputLocationMode.Mode currentMode(double currentDistance){
|
||||
if ( currentDistance <= this.distance.getValue() )
|
||||
return INSIDE;
|
||||
else
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
static Location getCurrentLocation(){
|
||||
return LocationService.getLastLocation();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public class TriggerTempTarget extends Trigger {
|
|||
|
||||
@Override
|
||||
public int friendlyName() {
|
||||
return R.string.temptarget;
|
||||
return R.string.careportal_temporarytarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,7 +124,7 @@ public class TriggerTempTarget extends Trigger {
|
|||
@Override
|
||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||
new LayoutBuilder()
|
||||
.add(new StaticLabel(R.string.temptarget))
|
||||
.add(new StaticLabel(R.string.careportal_temporarytarget))
|
||||
.add(comparator)
|
||||
.build(root);
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ public class TriggerTimeRange extends Trigger {
|
|||
|
||||
public int getMinSinceMidnight(long time) {
|
||||
// if passed argument is smaller than 1440 ( 24 h * 60 min ) that value is already converted
|
||||
if (0 < time && time < 1441)
|
||||
if (0 <= time && time < 1441)
|
||||
return (int) time;
|
||||
Calendar calendar = DateUtil.gregorianCalendar();
|
||||
calendar.setTimeInMillis(time);
|
||||
|
|
|
@ -63,7 +63,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
|
|||
public static final OptionsToShow TEMPBASALSTART = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart).date().bg().duration().percent().absolute();
|
||||
public static final OptionsToShow TEMPBASALEND = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend).date().bg();
|
||||
public static final OptionsToShow PROFILESWITCH = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).date().duration().profile();
|
||||
public static final OptionsToShow PROFILESWITCHDIRECT = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).duration().profile();
|
||||
public static final OptionsToShow OPENAPSOFFLINE = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline).date().duration();
|
||||
public static final OptionsToShow TEMPTARGET = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget).date().duration().tempTarget();
|
||||
|
||||
|
@ -180,7 +179,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
|
|||
newDialog.setOptions(NOTE, R.string.careportal_note);
|
||||
break;
|
||||
case R.id.careportal_profileswitch:
|
||||
PROFILESWITCH.executeProfileSwitch = false;
|
||||
newDialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
|
||||
break;
|
||||
case R.id.careportal_pumpsitechange:
|
||||
|
@ -202,7 +200,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
|
|||
newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline);
|
||||
break;
|
||||
case R.id.careportal_temporarytarget:
|
||||
TEMPTARGET.executeTempTarget = false;
|
||||
newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget);
|
||||
break;
|
||||
default:
|
||||
|
@ -222,7 +219,7 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
|
|||
activity.runOnUiThread(
|
||||
() -> {
|
||||
CareportalEvent careportalEvent;
|
||||
NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
|
||||
NSSettingsStatus nsSettings = NSSettingsStatus.getInstance();
|
||||
|
||||
double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
|
||||
double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.careportal;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
|
@ -22,10 +23,14 @@ public class CareportalPlugin extends PluginBase {
|
|||
.fragmentClass(CareportalFragment.class.getName())
|
||||
.pluginName(R.string.careportal)
|
||||
.shortName(R.string.careportal_shortname)
|
||||
.visibleByDefault(true)
|
||||
.enableByDefault(true)
|
||||
.visibleByDefault(Config.NSCLIENT)
|
||||
.enableByDefault(Config.NSCLIENT)
|
||||
.description(R.string.description_careportal)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialEnableCondition() {
|
||||
return Config.NSCLIENT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.careportal.Dialogs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
@ -9,6 +8,8 @@ import android.text.format.DateFormat;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
|
@ -18,7 +19,6 @@ import android.widget.RadioButton;
|
|||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
|
@ -45,8 +45,6 @@ import info.nightscout.androidaps.data.ProfileStore;
|
|||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
|
||||
|
@ -58,6 +56,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper;
|
|||
import info.nightscout.androidaps.utils.HardLimits;
|
||||
import info.nightscout.androidaps.utils.JsonHelper;
|
||||
import info.nightscout.androidaps.utils.NumberPicker;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
import info.nightscout.androidaps.utils.Translator;
|
||||
|
@ -68,7 +67,7 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
private static OptionsToShow options;
|
||||
private static String event;
|
||||
|
||||
Profile profile;
|
||||
private Profile profile;
|
||||
public ProfileStore profileStore;
|
||||
|
||||
TextView eventTypeText;
|
||||
|
@ -105,9 +104,10 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
|
||||
private static Integer seconds = null;
|
||||
|
||||
public void setOptions(OptionsToShow options, int event) {
|
||||
public NewNSTreatmentDialog setOptions(OptionsToShow options, int event) {
|
||||
this.options = options;
|
||||
this.event = MainApp.gs(event);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NewNSTreatmentDialog() {
|
||||
|
@ -122,7 +122,10 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
if (options == null) return null;
|
||||
getDialog().setTitle(MainApp.gs(options.eventName));
|
||||
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
setCancelable(true);
|
||||
getDialog().setCanceledOnTouchOutside(false);
|
||||
setStyle(DialogFragment.STYLE_NORMAL, getTheme());
|
||||
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
|
||||
|
||||
|
@ -200,16 +203,15 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
boolean erase = false;
|
||||
|
||||
String units = ProfileFunctions.getSystemUnits();
|
||||
DefaultValueHelper helper = new DefaultValueHelper();
|
||||
if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineEatingSoonTTDuration();
|
||||
defaultTarget = helper.determineEatingSoonTT();
|
||||
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration();
|
||||
defaultTarget = DefaultValueHelper.determineEatingSoonTT();
|
||||
} else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineActivityTTDuration();
|
||||
defaultTarget = helper.determineActivityTT();
|
||||
defaultDuration = DefaultValueHelper.determineActivityTTDuration();
|
||||
defaultTarget = DefaultValueHelper.determineActivityTT();
|
||||
} else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineHypoTTDuration();
|
||||
defaultTarget = helper.determineHypoTT();
|
||||
defaultDuration = DefaultValueHelper.determineHypoTTDuration();
|
||||
defaultTarget = DefaultValueHelper.determineHypoTT();
|
||||
} else if (editDuration.getValue() != 0) {
|
||||
defaultDuration = editDuration.getValue();
|
||||
} else {
|
||||
|
@ -394,6 +396,13 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
@ -585,12 +594,12 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
|
||||
String buildConfirmText(JSONObject data) {
|
||||
String ret = "";
|
||||
if (data.has("eventType")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
|
||||
ret += ": ";
|
||||
ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
|
||||
ret += "\n";
|
||||
}
|
||||
// if (data.has("eventType")) {
|
||||
// ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
|
||||
// ret += ": ";
|
||||
// ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
|
||||
// ret += "\n";
|
||||
// }
|
||||
if (data.has("glucose")) {
|
||||
ret += MainApp.gs(R.string.treatments_wizard_bg_label);
|
||||
ret += ": ";
|
||||
|
@ -672,7 +681,7 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
ret += "\n";
|
||||
}
|
||||
if (data.has("created_at")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
|
||||
ret += MainApp.gs(R.string.event_time_label);
|
||||
ret += ": ";
|
||||
ret += eventTime.toLocaleString();
|
||||
ret += "\n";
|
||||
|
@ -687,61 +696,25 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
|
|||
return ret;
|
||||
}
|
||||
|
||||
void confirmNSTreatmentCreation() {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
final JSONObject data = gatherData();
|
||||
final String confirmText = buildConfirmText(data);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmText);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
}
|
||||
private void confirmNSTreatmentCreation() {
|
||||
final JSONObject data = gatherData();
|
||||
OKDialog.showConfirmation(getContext(), Translator.translate(JsonHelper.safeGetString(data, "eventType", MainApp.gs(R.string.overview_treatment_label))), buildConfirmText(data), () -> createNSTreatment(data));
|
||||
}
|
||||
|
||||
|
||||
void createNSTreatment(JSONObject data) {
|
||||
if (options.executeProfileSwitch) {
|
||||
if (data.has("profile")) {
|
||||
ProfileFunctions.doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
|
||||
}
|
||||
} else if (options.executeTempTarget) {
|
||||
final int duration = JsonHelper.safeGetInt(data, "duration");
|
||||
final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
|
||||
final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
|
||||
final String reason = JsonHelper.safeGetString(data, "reason", "");
|
||||
if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
|
||||
TempTarget tempTarget = new TempTarget()
|
||||
.date(eventTime.getTime())
|
||||
.duration(duration)
|
||||
.reason(reason)
|
||||
.source(Source.USER);
|
||||
if (tempTarget.durationInMinutes != 0) {
|
||||
tempTarget.low(Profile.toMgdl(targetBottom, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(targetTop, ProfileFunctions.getSystemUnits()));
|
||||
} else {
|
||||
tempTarget.low(0).high(0);
|
||||
}
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
|
||||
}
|
||||
if (duration == 10)
|
||||
SP.putBoolean(R.string.key_objectiveusetemptarget, true);
|
||||
if (JsonHelper.safeGetString(data, "eventType", "").equals(CareportalEvent.PROFILESWITCH)) {
|
||||
ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch(
|
||||
profileStore,
|
||||
JsonHelper.safeGetString(data, "profile"),
|
||||
JsonHelper.safeGetInt(data, "duration"),
|
||||
JsonHelper.safeGetInt(data, "percentage"),
|
||||
JsonHelper.safeGetInt(data, "timeshift"),
|
||||
eventTime.getTime()
|
||||
);
|
||||
NSUpload.uploadProfileSwitch(profileSwitch);
|
||||
} else {
|
||||
if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) {
|
||||
ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch(
|
||||
profileStore,
|
||||
JsonHelper.safeGetString(data, "profile"),
|
||||
JsonHelper.safeGetInt(data, "duration"),
|
||||
JsonHelper.safeGetInt(data, "percentage"),
|
||||
JsonHelper.safeGetInt(data, "timeshift"),
|
||||
eventTime.getTime()
|
||||
);
|
||||
NSUpload.uploadProfileSwitch(profileSwitch);
|
||||
} else {
|
||||
NSUpload.uploadCareportalEntryToNS(data);
|
||||
}
|
||||
NSUpload.uploadCareportalEntryToNS(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,6 @@ public class OptionsToShow {
|
|||
public boolean split;
|
||||
public boolean tempTarget;
|
||||
|
||||
// perform direct actions
|
||||
public boolean executeProfileSwitch = false;
|
||||
public boolean executeTempTarget = false;
|
||||
|
||||
public OptionsToShow(int eventType, int eventName) {
|
||||
this.eventType = eventType;
|
||||
this.eventName = eventName;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.general.food;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
|
@ -14,14 +13,11 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -33,6 +29,7 @@ import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
|||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SpinnerHelper;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
@ -42,43 +39,36 @@ import io.reactivex.disposables.CompositeDisposable;
|
|||
*/
|
||||
|
||||
public class FoodFragment extends Fragment {
|
||||
private static Logger log = LoggerFactory.getLogger(FoodFragment.class);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
EditText filter;
|
||||
ImageView clearFilter;
|
||||
SpinnerHelper category;
|
||||
SpinnerHelper subcategory;
|
||||
RecyclerView recyclerView;
|
||||
private EditText filter;
|
||||
private SpinnerHelper category;
|
||||
private SpinnerHelper subcategory;
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
List<Food> unfiltered;
|
||||
List<Food> filtered;
|
||||
ArrayList<CharSequence> categories;
|
||||
ArrayList<CharSequence> subcategories;
|
||||
private List<Food> unfiltered;
|
||||
private List<Food> filtered;
|
||||
|
||||
final String EMPTY = MainApp.gs(R.string.none);
|
||||
private final String EMPTY = MainApp.gs(R.string.none);
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.food_fragment, container, false);
|
||||
filter = (EditText) view.findViewById(R.id.food_filter);
|
||||
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
|
||||
filter = view.findViewById(R.id.food_filter);
|
||||
ImageView clearFilter = view.findViewById(R.id.food_clearfilter);
|
||||
category = new SpinnerHelper(view.findViewById(R.id.food_category));
|
||||
subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory));
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview);
|
||||
recyclerView = view.findViewById(R.id.food_recyclerview);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
LinearLayoutManager llm = new LinearLayoutManager(view.getContext());
|
||||
recyclerView.setLayoutManager(llm);
|
||||
|
||||
clearFilter.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
filter.setText("");
|
||||
category.setSelection(0);
|
||||
subcategory.setSelection(0);
|
||||
filterData();
|
||||
}
|
||||
clearFilter.setOnClickListener(v -> {
|
||||
filter.setText("");
|
||||
category.setSelection(0);
|
||||
subcategory.setSelection(0);
|
||||
filterData();
|
||||
});
|
||||
|
||||
category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
|
@ -149,11 +139,11 @@ public class FoodFragment extends Fragment {
|
|||
disposable.clear();
|
||||
}
|
||||
|
||||
void loadData() {
|
||||
private void loadData() {
|
||||
unfiltered = FoodPlugin.getPlugin().getService().getFoodData();
|
||||
}
|
||||
|
||||
void fillCategories() {
|
||||
private void fillCategories() {
|
||||
Set<CharSequence> catSet = new HashSet<>();
|
||||
|
||||
for (Food f : unfiltered) {
|
||||
|
@ -162,7 +152,7 @@ public class FoodFragment extends Fragment {
|
|||
}
|
||||
|
||||
// make it unique
|
||||
categories = new ArrayList<>(catSet);
|
||||
ArrayList<CharSequence> categories = new ArrayList<>(catSet);
|
||||
categories.add(0, MainApp.gs(R.string.none));
|
||||
|
||||
ArrayAdapter<CharSequence> adapterCategories = new ArrayAdapter<>(getContext(),
|
||||
|
@ -170,7 +160,7 @@ public class FoodFragment extends Fragment {
|
|||
category.setAdapter(adapterCategories);
|
||||
}
|
||||
|
||||
void fillSubcategories() {
|
||||
private void fillSubcategories() {
|
||||
String categoryFilter = category.getSelectedItem().toString();
|
||||
|
||||
Set<CharSequence> subCatSet = new HashSet<>();
|
||||
|
@ -184,7 +174,7 @@ public class FoodFragment extends Fragment {
|
|||
}
|
||||
|
||||
// make it unique
|
||||
subcategories = new ArrayList<>(subCatSet);
|
||||
ArrayList<CharSequence> subcategories = new ArrayList<>(subCatSet);
|
||||
subcategories.add(0, MainApp.gs(R.string.none));
|
||||
|
||||
ArrayAdapter<CharSequence> adapterSubcategories = new ArrayAdapter<>(getContext(),
|
||||
|
@ -192,7 +182,7 @@ public class FoodFragment extends Fragment {
|
|||
subcategory.setAdapter(adapterSubcategories);
|
||||
}
|
||||
|
||||
void filterData() {
|
||||
private void filterData() {
|
||||
String textFilter = filter.getText().toString();
|
||||
String categoryFilter = category.getSelectedItem().toString();
|
||||
String subcategoryFilter = subcategory.getSelectedItem().toString();
|
||||
|
@ -227,6 +217,7 @@ public class FoodFragment extends Fragment {
|
|||
this.foodList = foodList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false);
|
||||
|
@ -257,7 +248,7 @@ public class FoodFragment extends Fragment {
|
|||
return foodList.size();
|
||||
}
|
||||
|
||||
class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
class FoodsViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView name;
|
||||
TextView portion;
|
||||
TextView carbs;
|
||||
|
@ -269,43 +260,26 @@ public class FoodFragment extends Fragment {
|
|||
|
||||
FoodsViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
name = (TextView) itemView.findViewById(R.id.food_name);
|
||||
portion = (TextView) itemView.findViewById(R.id.food_portion);
|
||||
carbs = (TextView) itemView.findViewById(R.id.food_carbs);
|
||||
fat = (TextView) itemView.findViewById(R.id.food_fat);
|
||||
protein = (TextView) itemView.findViewById(R.id.food_protein);
|
||||
energy = (TextView) itemView.findViewById(R.id.food_energy);
|
||||
ns = (TextView) itemView.findViewById(R.id.ns_sign);
|
||||
remove = (TextView) itemView.findViewById(R.id.food_remove);
|
||||
remove.setOnClickListener(this);
|
||||
name = itemView.findViewById(R.id.food_name);
|
||||
portion = itemView.findViewById(R.id.food_portion);
|
||||
carbs = itemView.findViewById(R.id.food_carbs);
|
||||
fat = itemView.findViewById(R.id.food_fat);
|
||||
protein = itemView.findViewById(R.id.food_protein);
|
||||
energy = itemView.findViewById(R.id.food_energy);
|
||||
ns = itemView.findViewById(R.id.ns_sign);
|
||||
remove = itemView.findViewById(R.id.food_remove);
|
||||
remove.setOnClickListener(v -> {
|
||||
final Food food = (Food) v.getTag();
|
||||
OKDialog.showConfirmation(getContext(), MainApp.gs(R.string.confirmation), MainApp.gs(R.string.removerecord) + "\n" + food.name, (dialog, id) -> {
|
||||
final String _id = food._id;
|
||||
if (_id != null && !_id.equals("")) {
|
||||
NSUpload.removeFoodFromNS(_id);
|
||||
}
|
||||
FoodPlugin.getPlugin().getService().delete(food);
|
||||
}, null);
|
||||
});
|
||||
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Food food = (Food) v.getTag();
|
||||
switch (v.getId()) {
|
||||
|
||||
case R.id.food_remove:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + food.name);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
final String _id = food._id;
|
||||
if (_id != null && !_id.equals("")) {
|
||||
NSUpload.removeFoodFromNS(_id);
|
||||
}
|
||||
FoodPlugin.getPlugin().getService().delete(food);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@ package info.nightscout.androidaps.plugins.general.maintenance;
|
|||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -39,7 +38,7 @@ import info.nightscout.androidaps.utils.ToastUtils;
|
|||
|
||||
public class ImportExportPrefs {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
static File path = new File(Environment.getExternalStorageDirectory().toString());
|
||||
private static File path = new File(Environment.getExternalStorageDirectory().toString());
|
||||
static public final File file = new File(path, MainApp.gs(R.string.app_name) + "Preferences");
|
||||
|
||||
private static final int REQUEST_EXTERNAL_STORAGE = 1;
|
||||
|
@ -48,21 +47,7 @@ public class ImportExportPrefs {
|
|||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
};
|
||||
|
||||
public static void verifyStoragePermissions(Activity activity) {
|
||||
// Check if we have write permission
|
||||
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
|
||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
||||
// We don't have permission so prompt the user
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
PERMISSIONS_STORAGE,
|
||||
REQUEST_EXTERNAL_STORAGE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyStoragePermissions(Fragment fragment) {
|
||||
static void verifyStoragePermissions(Fragment fragment) {
|
||||
int permission = ContextCompat.checkSelfPermission(fragment.getContext(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
|
||||
|
@ -73,85 +58,71 @@ public class ImportExportPrefs {
|
|||
|
||||
}
|
||||
|
||||
public static void exportSharedPreferences(final Fragment f) {
|
||||
static void exportSharedPreferences(final Fragment f) {
|
||||
exportSharedPreferences(f.getContext());
|
||||
}
|
||||
|
||||
public static void exportSharedPreferences(final Context c) {
|
||||
|
||||
new AlertDialog.Builder(c)
|
||||
.setMessage(MainApp.gs(R.string.export_to) + " " + file + " ?")
|
||||
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
|
||||
try {
|
||||
FileWriter fw = new FileWriter(file);
|
||||
PrintWriter pw = new PrintWriter(fw);
|
||||
Map<String, ?> prefsMap = prefs.getAll();
|
||||
for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
|
||||
pw.println(entry.getKey() + "::" + entry.getValue().toString());
|
||||
}
|
||||
pw.close();
|
||||
fw.close();
|
||||
ToastUtils.showToastInUiThread(c, MainApp.gs(R.string.exported));
|
||||
} catch (FileNotFoundException e) {
|
||||
ToastUtils.showToastInUiThread(c, MainApp.gs(R.string.filenotfound) + " " + file);
|
||||
log.error("Unhandled exception", e);
|
||||
} catch (IOException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
private static void exportSharedPreferences(final Context context) {
|
||||
OKDialog.showConfirmation(context, MainApp.gs(R.string.maintenance), MainApp.gs(R.string.export_to) + " " + file + " ?", () -> {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
try {
|
||||
FileWriter fw = new FileWriter(file);
|
||||
PrintWriter pw = new PrintWriter(fw);
|
||||
Map<String, ?> prefsMap = prefs.getAll();
|
||||
for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
|
||||
pw.println(entry.getKey() + "::" + entry.getValue().toString());
|
||||
}
|
||||
pw.close();
|
||||
fw.close();
|
||||
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.exported));
|
||||
} catch (FileNotFoundException e) {
|
||||
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.filenotfound) + " " + file);
|
||||
log.error("Unhandled exception", e);
|
||||
} catch (IOException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void importSharedPreferences(final Fragment fragment) {
|
||||
static void importSharedPreferences(final Fragment fragment) {
|
||||
importSharedPreferences(fragment.getContext());
|
||||
}
|
||||
|
||||
public static void importSharedPreferences(final Context context) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(MainApp.gs(R.string.import_from) + " " + file + " ?")
|
||||
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
|
||||
OKDialog.showConfirmation(context, MainApp.gs(R.string.maintenance), MainApp.gs(R.string.import_from) + " " + file + " ?", () -> {
|
||||
String line;
|
||||
String[] lineParts;
|
||||
try {
|
||||
SP.clear();
|
||||
|
||||
String line;
|
||||
String[] lineParts;
|
||||
try {
|
||||
SP.clear();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lineParts = line.split("::");
|
||||
if (lineParts.length == 2) {
|
||||
if (lineParts[1].equals("true") || lineParts[1].equals("false")) {
|
||||
SP.putBoolean(lineParts[0], Boolean.parseBoolean(lineParts[1]));
|
||||
} else {
|
||||
SP.putString(lineParts[0], lineParts[1]);
|
||||
}
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lineParts = line.split("::");
|
||||
if (lineParts.length == 2) {
|
||||
if (lineParts[1].equals("true") || lineParts[1].equals("false")) {
|
||||
SP.putBoolean(lineParts[0], Boolean.parseBoolean(lineParts[1]));
|
||||
} else {
|
||||
SP.putString(lineParts[0], lineParts[1]);
|
||||
}
|
||||
reader.close();
|
||||
SP.putBoolean(R.string.key_setupwizard_processed, true);
|
||||
OKDialog.show(context, MainApp.gs(R.string.setting_imported), MainApp.gs(R.string.restartingapp), () -> {
|
||||
log.debug("Exiting");
|
||||
MainApp.instance().stopKeepAliveService();
|
||||
RxBus.INSTANCE.send(new EventAppExit());
|
||||
MainApp.closeDbHelper();
|
||||
if (context instanceof Activity) {
|
||||
((Activity)context).finish();
|
||||
}
|
||||
System.runFinalization();
|
||||
System.exit(0);
|
||||
});
|
||||
} catch (FileNotFoundException e) {
|
||||
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.filenotfound) + " " + file);
|
||||
log.error("Unhandled exception", e);
|
||||
} catch (IOException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
reader.close();
|
||||
SP.putBoolean(R.string.key_setupwizard_processed, true);
|
||||
OKDialog.show(context, MainApp.gs(R.string.setting_imported), MainApp.gs(R.string.restartingapp), () -> {
|
||||
log.debug("Exiting");
|
||||
RxBus.INSTANCE.send(new EventAppExit());
|
||||
if (context instanceof Activity) {
|
||||
((Activity) context).finish();
|
||||
}
|
||||
System.runFinalization();
|
||||
System.exit(0);
|
||||
});
|
||||
} catch (FileNotFoundException e) {
|
||||
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.filenotfound) + " " + file);
|
||||
log.error("Unhandled exception", e);
|
||||
} catch (IOException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,81 +2,58 @@ package info.nightscout.androidaps.plugins.general.maintenance;
|
|||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MaintenanceFragment extends Fragment {
|
||||
|
||||
private Fragment f;
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.f = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
this.f = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.maintenance_fragment, container, false);
|
||||
|
||||
final Fragment f = this;
|
||||
|
||||
view.findViewById(R.id.log_send).setOnClickListener(view1 -> MaintenancePlugin.getPlugin().sendLogs());
|
||||
|
||||
view.findViewById(R.id.log_delete).setOnClickListener(view1 -> MaintenancePlugin.getPlugin().deleteLogs());
|
||||
|
||||
view.findViewById(R.id.nav_resetdb).setOnClickListener(view1 -> new AlertDialog.Builder(f.getContext())
|
||||
.setTitle(R.string.nav_resetdb)
|
||||
.setMessage(R.string.reset_db_confirm)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
view.findViewById(R.id.nav_resetdb).setOnClickListener(view1 ->
|
||||
OKDialog.showConfirmation(getContext(), MainApp.gs(R.string.maintenance), MainApp.gs(R.string.reset_db_confirm), () -> {
|
||||
MainApp.getDbHelper().resetDatabases();
|
||||
// should be handled by Plugin-Interface and
|
||||
// additional service interface and plugin registry
|
||||
FoodPlugin.getPlugin().getService().resetFood();
|
||||
TreatmentsPlugin.getPlugin().getService().resetTreatments();
|
||||
})
|
||||
.create()
|
||||
.show());
|
||||
|
||||
);
|
||||
view.findViewById(R.id.nav_export).setOnClickListener(view1 -> {
|
||||
// start activity for checking permissions...
|
||||
ImportExportPrefs.verifyStoragePermissions(f);
|
||||
ImportExportPrefs.exportSharedPreferences(f);
|
||||
ImportExportPrefs.verifyStoragePermissions(this);
|
||||
ImportExportPrefs.exportSharedPreferences(this);
|
||||
});
|
||||
|
||||
view.findViewById(R.id.nav_import).setOnClickListener(view1 -> {
|
||||
// start activity for checking permissions...
|
||||
ImportExportPrefs.verifyStoragePermissions(f);
|
||||
ImportExportPrefs.importSharedPreferences(f);
|
||||
ImportExportPrefs.verifyStoragePermissions(this);
|
||||
ImportExportPrefs.importSharedPreferences(this);
|
||||
});
|
||||
|
||||
view.findViewById(R.id.nav_logsettings).setOnClickListener(view1 -> {
|
||||
startActivity(new Intent(getActivity(), LogSettingActivity.class));
|
||||
});
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient;
|
||||
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
|
@ -25,6 +22,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientN
|
|||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
@ -113,20 +111,11 @@ public class NSClientFragment extends Fragment implements View.OnClickListener,
|
|||
NSClientPlugin.getPlugin().clearLog();
|
||||
break;
|
||||
case R.id.nsclientinternal_clearqueue:
|
||||
final Context context = getContext();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage("Clear queue? All data in queue will be lost!");
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
UploadQueue.clearQueue();
|
||||
updateGui();
|
||||
FabricPrivacy.getInstance().logCustom("NSClientClearQueue");
|
||||
}
|
||||
OKDialog.showConfirmation(getContext(),MainApp.gs(R.string.nsclientinternal), MainApp.gs(R.string.clearqueueconfirm), () -> {
|
||||
UploadQueue.clearQueue();
|
||||
updateGui();
|
||||
FabricPrivacy.getInstance().logCustom("NSClientClearQueue");
|
||||
});
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
break;
|
||||
case R.id.nsclientinternal_showqueue:
|
||||
RxBus.INSTANCE.send(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList()));
|
||||
|
|
|
@ -32,6 +32,8 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
|
|||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
|
||||
|
@ -250,4 +252,25 @@ public class NSClientPlugin extends PluginBase {
|
|||
public boolean hasWritePermission() {
|
||||
return nsClientService.hasWriteAuth;
|
||||
}
|
||||
|
||||
public void handleClearAlarm(NSAlarm originalAlarm, long silenceTimeInMsec) {
|
||||
|
||||
if (!isEnabled(PluginType.GENERAL)) {
|
||||
return;
|
||||
}
|
||||
if (SP.getBoolean(R.string.key_ns_noupload, false)) {
|
||||
if (L.isEnabled(L.NSCLIENT))
|
||||
log.debug("Upload disabled. Message dropped");
|
||||
return;
|
||||
}
|
||||
|
||||
AlarmAck ack = new AlarmAck();
|
||||
ack.level = originalAlarm.getLevel();
|
||||
ack.group = originalAlarm.getGroup();
|
||||
ack.silenceTime = silenceTimeInMsec;
|
||||
|
||||
if (nsClientService != null)
|
||||
nsClientService.sendAlarmAck(ack);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONArray;
|
||||
|
@ -24,22 +23,23 @@ import java.util.Locale;
|
|||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.services.Intents;
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.DbRequest;
|
||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.DeviceStatus;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DbLogger;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.utils.BatteryLevel;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
@ -53,7 +53,6 @@ public class NSUpload {
|
|||
|
||||
public static void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.TEMPBASAL);
|
||||
data.put("duration", temporaryBasal.durationInMinutes);
|
||||
|
@ -65,15 +64,7 @@ public class NSUpload {
|
|||
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
|
||||
if (originalExtendedAmount != null)
|
||||
data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -96,7 +87,6 @@ public class NSUpload {
|
|||
uploadTempBasalStartAbsolute(t, null);
|
||||
}
|
||||
} else {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.TEMPBASAL);
|
||||
data.put("duration", temporaryBasal.durationInMinutes);
|
||||
|
@ -107,15 +97,7 @@ public class NSUpload {
|
|||
data.put("pumpId", temporaryBasal.pumpId);
|
||||
data.put("created_at", DateUtil.toISOString(temporaryBasal.date));
|
||||
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -124,7 +106,6 @@ public class NSUpload {
|
|||
|
||||
public static void uploadTempBasalEnd(long time, boolean isFakedTempBasal, long pumpId) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.TEMPBASAL);
|
||||
data.put("created_at", DateUtil.toISOString(time));
|
||||
|
@ -133,15 +114,7 @@ public class NSUpload {
|
|||
data.put("isFakedTempBasal", isFakedTempBasal);
|
||||
if (pumpId != 0)
|
||||
data.put("pumpId", pumpId);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -149,7 +122,6 @@ public class NSUpload {
|
|||
|
||||
public static void uploadExtendedBolus(ExtendedBolus extendedBolus) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.COMBOBOLUS);
|
||||
data.put("duration", extendedBolus.durationInMinutes);
|
||||
|
@ -161,15 +133,7 @@ public class NSUpload {
|
|||
data.put("pumpId", extendedBolus.pumpId);
|
||||
data.put("created_at", DateUtil.toISOString(extendedBolus.date));
|
||||
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -177,7 +141,6 @@ public class NSUpload {
|
|||
|
||||
public static void uploadExtendedBolusEnd(long time, long pumpId) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.COMBOBOLUS);
|
||||
data.put("duration", 0);
|
||||
|
@ -189,15 +152,7 @@ public class NSUpload {
|
|||
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
|
||||
if (pumpId != 0)
|
||||
data.put("pumpId", pumpId);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -246,7 +201,12 @@ public class NSUpload {
|
|||
}
|
||||
} else {
|
||||
if (L.isEnabled(L.NSCLIENT))
|
||||
log.debug("OpenAPS data too old to upload");
|
||||
log.debug("OpenAPS data too old to upload, sending iob only");
|
||||
IobTotal[] iob = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(profile);
|
||||
if (iob.length > 0) {
|
||||
deviceStatus.iob = iob[0].json();
|
||||
deviceStatus.iob.put("time", DateUtil.toISOString(DateUtil.now()));
|
||||
}
|
||||
}
|
||||
deviceStatus.device = "openaps://" + Build.MANUFACTURER + " " + Build.MODEL;
|
||||
JSONObject pumpstatus = ConfigBuilderPlugin.getPlugin().getActivePump().getJSONStatus(profile, profileName);
|
||||
|
@ -258,16 +218,7 @@ public class NSUpload {
|
|||
deviceStatus.uploaderBattery = batteryLevel;
|
||||
|
||||
deviceStatus.created_at = DateUtil.toISOString(new Date());
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "devicestatus");
|
||||
bundle.putString("data", deviceStatus.mongoRecord().toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, deviceStatus.mongoRecord().toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "devicestatus", deviceStatus.mongoRecord()));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -315,11 +266,13 @@ public class NSUpload {
|
|||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", CareportalEvent.TEMPORARYTARGET);
|
||||
data.put("duration", tempTarget.durationInMinutes);
|
||||
data.put("reason", tempTarget.reason);
|
||||
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.low, ProfileFunctions.getSystemUnits()));
|
||||
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.high, ProfileFunctions.getSystemUnits()));
|
||||
if (tempTarget.low > 0) {
|
||||
data.put("reason", tempTarget.reason);
|
||||
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.low, ProfileFunctions.getSystemUnits()));
|
||||
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.high, ProfileFunctions.getSystemUnits()));
|
||||
data.put("units", ProfileFunctions.getSystemUnits());
|
||||
}
|
||||
data.put("created_at", DateUtil.toISOString(tempTarget.date));
|
||||
data.put("units", ProfileFunctions.getSystemUnits());
|
||||
data.put("enteredBy", MainApp.gs(R.string.app_name));
|
||||
uploadCareportalEntryToNS(data);
|
||||
} catch (JSONException e) {
|
||||
|
@ -331,17 +284,7 @@ public class NSUpload {
|
|||
try {
|
||||
JSONObject data = getJson(profileSwitch);
|
||||
if (profileSwitch._id != null) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbUpdate");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
bundle.putString("_id", profileSwitch._id);
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbUpdate", "treatments", profileSwitch._id, data));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -380,16 +323,7 @@ public class NSUpload {
|
|||
prebolus.put("created_at", DateUtil.toISOString(preBolusDate));
|
||||
uploadCareportalEntryToNS(prebolus);
|
||||
}
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -397,40 +331,17 @@ public class NSUpload {
|
|||
}
|
||||
|
||||
public static void removeCareportalEntryFromNS(String _id) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbRemove");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("_id", _id);
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbRemove(intent, _id);
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
||||
UploadQueue.add(new DbRequest("dbRemove", "treatments", _id));
|
||||
}
|
||||
|
||||
public static void uploadOpenAPSOffline(double durationInMinutes) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("eventType", "OpenAPS Offline");
|
||||
data.put("duration", durationInMinutes);
|
||||
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -441,10 +352,6 @@ public class NSUpload {
|
|||
}
|
||||
|
||||
public static void uploadError(String error, Date date) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("eventType", "Announcement");
|
||||
|
@ -455,19 +362,10 @@ public class NSUpload {
|
|||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
}
|
||||
|
||||
public static void uploadBg(BgReading reading, String source) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "entries");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("device", source);
|
||||
|
@ -479,20 +377,11 @@ public class NSUpload {
|
|||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "entries", data));
|
||||
}
|
||||
|
||||
public static void uploadAppStart() {
|
||||
if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("eventType", "Note");
|
||||
|
@ -501,35 +390,17 @@ public class NSUpload {
|
|||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
}
|
||||
}
|
||||
|
||||
public static void uploadProfileStore(JSONObject profileStore) {
|
||||
if (SP.getBoolean(R.string.key_ns_uploadlocalprofile, false)) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "profile");
|
||||
bundle.putString("data", String.valueOf(profileStore));
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, String.valueOf(profileStore));
|
||||
UploadQueue.add(new DbRequest("dbAdd", "profile", String.valueOf(profileStore)));
|
||||
}
|
||||
}
|
||||
|
||||
public static void uploadEvent(String careportalEvent, long time, @Nullable String notes) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("eventType", careportalEvent);
|
||||
|
@ -541,26 +412,12 @@ public class NSUpload {
|
|||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString());
|
||||
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
|
||||
}
|
||||
|
||||
public static void removeFoodFromNS(String _id) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbRemove");
|
||||
bundle.putString("collection", "food");
|
||||
bundle.putString("_id", _id);
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
DbLogger.dbRemove(intent, _id);
|
||||
UploadQueue.add(new DbRequest("dbRemove", "food", _id));
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,17 @@ public class UploadQueue {
|
|||
NSClientService.handler.post(() -> {
|
||||
if (L.isEnabled(L.NSCLIENT))
|
||||
log.debug("Adding to queue: " + dbr.data);
|
||||
MainApp.getDbHelper().create(dbr);
|
||||
try {
|
||||
MainApp.getDbHelper().create(dbr);
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
dbr.nsClientID += "1";
|
||||
try {
|
||||
MainApp.getDbHelper().create(dbr);
|
||||
} catch (Exception e1) {
|
||||
log.error("Unhandled exception", e1);
|
||||
}
|
||||
}
|
||||
NSClientPlugin plugin = NSClientPlugin.getPlugin();
|
||||
if (plugin != null) {
|
||||
plugin.resend("newdata");
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.services.Intents;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 11.06.2017.
|
||||
*/
|
||||
|
||||
public class BroadcastAckAlarm {
|
||||
|
||||
public static void handleClearAlarm(NSAlarm originalAlarm, Context context, long silenceTimeInMsec) {
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("level", originalAlarm.getLevel());
|
||||
bundle.putString("group", originalAlarm.getGroup());
|
||||
bundle.putLong("silenceTime", silenceTimeInMsec);
|
||||
Intent intent = new Intent(Intents.ACTION_ACK_ALARM);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
|
||||
|
||||
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
|
||||
bundle = new Bundle();
|
||||
bundle.putInt("level", originalAlarm.getLevel());
|
||||
bundle.putString("group", originalAlarm.getGroup());
|
||||
bundle.putLong("silenceTime", silenceTimeInMsec);
|
||||
intent = new Intent(Intents.ACTION_ACK_ALARM);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -25,12 +25,11 @@ import info.nightscout.androidaps.utils.SP;
|
|||
public class BroadcastTreatment {
|
||||
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
|
||||
|
||||
public static void handleNewTreatment(JSONObject treatment, boolean isDelta, boolean isLocalBypass) {
|
||||
public static void handleNewTreatment(JSONObject treatment, boolean isDelta) {
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("treatment", treatment.toString());
|
||||
bundle.putBoolean("delta", isDelta);
|
||||
bundle.putBoolean("islocal", isLocalBypass);
|
||||
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient.data;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* Created by mike on 02.07.2016.
|
||||
*/
|
||||
public class DbLogger {
|
||||
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
|
||||
|
||||
public static void dbAdd(Intent intent, String data) {
|
||||
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0);
|
||||
if (q.size() < 1) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.nsclientnotinstalled));
|
||||
log.error("DBADD No receivers");
|
||||
} else if (L.isEnabled(L.NSCLIENT)) {
|
||||
if (L.isEnabled(L.NSCLIENT))
|
||||
log.debug("DBADD dbAdd " + q.size() + " receivers " + data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dbRemove(Intent intent, String data) {
|
||||
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0);
|
||||
if (q.size() < 1) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.nsclientnotinstalled));
|
||||
log.error("DBREMOVE No receivers");
|
||||
} else if (L.isEnabled(L.NSCLIENT)) {
|
||||
if (L.isEnabled(L.NSCLIENT))
|
||||
log.debug("DBREMOVE dbRemove " + q.size() + " receivers " + data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -407,7 +407,7 @@ public class NSDeviceStatus {
|
|||
}
|
||||
Uploader uploader = uploaders.get(device);
|
||||
// check if this is new data
|
||||
if (clock != 0 && (uploader != null && clock > uploader.clock || uploader == null)) {
|
||||
if (clock != 0 && battery != null && (uploader != null && clock > uploader.clock || uploader == null)) {
|
||||
if (uploader == null)
|
||||
uploader = new Uploader();
|
||||
uploader.battery = battery;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue